我有一个简单的PHP扩展方法
PHP_METHOD(NaviModel, addRules) {
zval *ruleParam, *rules, function, rv, args[2];
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ZVAL(ruleParam)
ZEND_PARSE_PARAMETERS_END();
rules = zend_read_property(naviModelCe, Z_OBJ_P(ZEND_THIS), ZEND_STRL("rules"), ZEND_FETCH_CLASS_SILENT, &rv);
ZVAL_STRING(&function, "array_replace_recursive");
args[0] = *ruleParam;
args[1] = *rules;
call_user_function(NULL, NULL, &function, rules, 2, args);
zval_ptr_dtor(ruleParam);
zval_ptr_dtor(&function);
zval_dtor(args);
}
当我用valgrind运行测试时,它显示了几个错误,从大小为4的的无效读取开始
==52047== Invalid read of size 4
==52047== at 0x708994: zend_gc_addref (zend_types.h:1161)
==52047== by 0x70C02F: zend_call_function (zend_execute_API.c:798)
==52047== by 0x70B983: _call_user_function_impl (zend_execute_API.c:659)
==52047== by 0x72A4707: zim_NaviModel_addRules (model.c:98)
==52047== by 0x76651B: ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER (zend_vm_execute.h:1755)
==52047== by 0x7E8E9F: execute_ex (zend_vm_execute.h:55172)
==52047== by 0x7ED5A7: zend_execute (zend_vm_execute.h:59499)
==52047== by 0x725AAB: zend_execute_scripts (zend.c:1694)
==52047== by 0x676877: php_execute_script (main.c:2543)
==52047== by 0x833443: do_cli (php_cli.c:949)
==52047== by 0x8342E7: main (php_cli.c:1337)
==52047== Address 0x715b380 is 0 bytes inside a block of size 56 free'd
==52047== at 0x4851A40: free (in /usr/libexec/valgrind/vgpreload_memcheck-arm64-linux.so)
==52047== by 0x6E651B: _efree_custom (zend_alloc.c:2427)
==52047== by 0x6E669B: _efree (zend_alloc.c:2547)
==52047== by 0x73F673: zend_array_destroy (zend_hash.c:1662)
==52047== by 0x720FC7: rc_dtor_func (zend_variables.c:57)
==52047== by 0x720F3F: i_zval_ptr_dtor (zend_variables.h:44)
==52047== by 0x72117B: zval_ptr_dtor (zend_variables.c:84)
==52047== by 0x72B02D3: naviModelNewsRules (news.c:35)
==52047== by 0x72B09FF: zim_NaviModelNews___construct (news.c:104)
==52047== by 0x76651B: ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER (zend_vm_execute.h:1755)
==52047== by 0x7E8E9F: execute_ex (zend_vm_execute.h:55172)
==52047== by 0x7ED5A7: zend_execute (zend_vm_execute.h:59499)
c:98是行call_user_function(NULL,NULL,&function,rules,2,args(;你能帮忙指出问题吗?
zval retval;
call_user_function(NULL, NULL, &function, &retval, 2, args);
Zend会在调用函数之前清除返回值,但返回值和第二个参数指向同一地址,这就是问题所在。