From: Dmitry Stogov Date: Fri, 3 Apr 2015 13:35:06 +0000 (+0300) Subject: Don't relay on reference-counter when parameter expected to be a reference, but value... X-Git-Tag: PRE_PHP7_NSAPI_REMOVAL~400 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dcaa79546b25723136e37589e56fc602a503db12;p=php Don't relay on reference-counter when parameter expected to be a reference, but value given. --- diff --git a/Zend/tests/bug29890.phpt b/Zend/tests/bug29890.phpt index 32e8e1bd5d..1fdcdc4291 100644 --- a/Zend/tests/bug29890.phpt +++ b/Zend/tests/bug29890.phpt @@ -2,7 +2,7 @@ Bug #29890 (crash if error handler fails) --FILE-- retval); @@ -775,26 +774,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / for (i=0; iparam_count; i++) { zval *param; + zval *arg = &fci->params[i]; if (ARG_SHOULD_BE_SENT_BY_REF(func, i + 1)) { - // TODO: Scalar values don't have reference counters anymore. - // They are assumed to be 1, and they may be easily passed by - // reference now. However, previously scalars with refcount==1 - // might be passed and with refcount>1 might not. We can support - // only single behavior ??? -#if 0 - if (Z_REFCOUNTED(fci->params[i]) && - // This solution breaks the following test (omit warning message) ??? - // Zend/tests/bug61273.phpt - // ext/reflection/tests/bug42976.phpt - // ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt -#else - if (!Z_REFCOUNTED(fci->params[i]) || - // This solution breaks the following test (emit warning message) ??? - // ext/pdo_sqlite/tests/pdo_005.phpt -#endif - (!Z_ISREF(fci->params[i]) && Z_REFCOUNT(fci->params[i]) > 1)) { - + if (UNEXPECTED(!Z_ISREF_P(arg))) { if (fci->no_separation && !ARG_MAY_BE_SENT_BY_REF(func, i + 1)) { if (i) { @@ -815,29 +798,21 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / return FAILURE; } - if (Z_REFCOUNTED(fci->params[i])) { - Z_DELREF(fci->params[i]); - } - ZVAL_DUP(&tmp, &fci->params[i]); - ZVAL_NEW_REF(&fci->params[i], &tmp); - Z_ADDREF(fci->params[i]); - } else if (!Z_ISREF(fci->params[i])) { - ZVAL_NEW_REF(&fci->params[i], &fci->params[i]); - Z_ADDREF(fci->params[i]); - } else if (Z_REFCOUNTED(fci->params[i])) { - Z_ADDREF(fci->params[i]); + ZVAL_NEW_REF(arg, arg); } - param = ZEND_CALL_ARG(call, i+1); - ZVAL_COPY_VALUE(param, &fci->params[i]); - } else if (Z_ISREF(fci->params[i]) && - /* don't separate references for __call */ - (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) { - param = ZEND_CALL_ARG(call, i+1); - ZVAL_DUP(param, Z_REFVAL(fci->params[i])); + Z_ADDREF_P(arg); } else { - param = ZEND_CALL_ARG(call, i+1); - ZVAL_COPY(param, &fci->params[i]); + if (Z_ISREF_P(arg) && + (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) { + /* don't separate references for __call */ + arg = Z_REFVAL_P(arg); + } + if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } } + param = ZEND_CALL_ARG(call, i+1); + ZVAL_COPY_VALUE(param, arg); } EG(scope) = calling_scope; diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 369f20f56f..a7d8d99611 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -699,6 +699,14 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) { Z_TYPE_INFO_P(__z) = IS_REFERENCE_EX; \ } while (0) +#define ZVAL_NEW_EMPTY_REF(z) do { \ + zend_reference *_ref = emalloc(sizeof(zend_reference)); \ + GC_REFCOUNT(_ref) = 1; \ + GC_TYPE_INFO(_ref) = IS_REFERENCE; \ + Z_REF_P(z) = _ref; \ + Z_TYPE_INFO_P(z) = IS_REFERENCE_EX; \ + } while (0) + #define ZVAL_NEW_REF(z, r) do { \ zend_reference *_ref = emalloc(sizeof(zend_reference)); \ GC_REFCOUNT(_ref) = 1; \ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 4dd9a1f448..91d541ab4c 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4381,7 +4381,7 @@ ZEND_VM_HANDLER(119, ZEND_SEND_ARRAY, ANY, ANY) } else { uint32_t arg_num; HashTable *ht; - zval *arg, *param, tmp; + zval *arg, *param; ZEND_VM_C_LABEL(send_array): ht = Z_ARRVAL_P(args); @@ -4407,24 +4407,7 @@ ZEND_VM_C_LABEL(send_array): param = ZEND_CALL_ARG(EX(call), 1); ZEND_HASH_FOREACH_VAL(ht, arg) { if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - // TODO: Scalar values don't have reference counters anymore. - // They are assumed to be 1, and they may be easily passed by - // reference now. However, previously scalars with refcount==1 - // might be passed and with refcount>1 might not. We can support - // only single behavior ??? -#if 0 - if (Z_REFCOUNTED_P(arg) && - // This solution breaks the following test (omit warning message) ??? - // Zend/tests/bug61273.phpt - // ext/reflection/tests/bug42976.phpt - // ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt -#else - if (!Z_REFCOUNTED_P(arg) || - // This solution breaks the following test (emit warning message) ??? - // ext/pdo_sqlite/tests/pdo_005.phpt -#endif - (!Z_ISREF_P(arg) && Z_REFCOUNT_P(arg) > 1)) { - + if (UNEXPECTED(!Z_ISREF_P(arg))) { if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num)) { zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given", @@ -4446,26 +4429,20 @@ ZEND_VM_C_LABEL(send_array): break; } - if (Z_REFCOUNTED_P(arg)) { - Z_DELREF_P(arg); - } - ZVAL_DUP(&tmp, arg); - ZVAL_NEW_REF(arg, &tmp); - Z_ADDREF_P(arg); - } else if (!Z_ISREF_P(arg)) { ZVAL_NEW_REF(arg, arg); - Z_ADDREF_P(arg); - } else if (Z_REFCOUNTED_P(arg)) { + } + Z_ADDREF_P(arg); + } else{ + if (Z_ISREF_P(arg) && + (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) { + /* don't separate references for __call */ + arg = Z_REFVAL_P(arg); + } + if (Z_OPT_REFCOUNTED_P(arg)) { Z_ADDREF_P(arg); } - ZVAL_COPY_VALUE(param, arg); - } else if (Z_ISREF_P(arg) && - /* don't separate references for __call */ - (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) { - ZVAL_DUP(param, Z_REFVAL_P(arg)); - } else { - ZVAL_COPY(param, arg); } + ZVAL_COPY_VALUE(param, arg); ZEND_CALL_NUM_ARGS(EX(call))++; arg_num++; param++; @@ -4479,7 +4456,7 @@ ZEND_VM_C_LABEL(send_array): ZEND_VM_HANDLER(120, ZEND_SEND_USER, VAR|CV, ANY) { USE_OPLINE - zval *arg, *param, tmp; + zval *arg, *param; zend_free_op free_op1; SAVE_OPLINE(); @@ -4487,23 +4464,7 @@ ZEND_VM_HANDLER(120, ZEND_SEND_USER, VAR|CV, ANY) param = ZEND_CALL_VAR(EX(call), opline->result.var); if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { - // TODO: Scalar values don't have reference counters anymore. - // They are assumed to be 1, and they may be easily passed by - // reference now. However, previously scalars with refcount==1 - // might be passed and with refcount>1 might not. We can support - // only single behavior ??? -#if 0 - if (Z_REFCOUNTED_P(arg) && - // This solution breaks the following test (omit warning message) ??? - // Zend/tests/bug61273.phpt - // ext/reflection/tests/bug42976.phpt - // ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt -#else - if (!Z_REFCOUNTED_P(arg) || - // This solution breaks the following test (emit warning message) ??? - // ext/pdo_sqlite/tests/pdo_005.phpt -#endif - (!Z_ISREF_P(arg) /*&& Z_REFCOUNT_P(arg) > 1???*/)) { + if (UNEXPECTED(!Z_ISREF_P(arg))) { if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { @@ -4529,26 +4490,20 @@ ZEND_VM_HANDLER(120, ZEND_SEND_USER, VAR|CV, ANY) ZEND_VM_NEXT_OPCODE(); } - if (Z_REFCOUNTED_P(arg)) { - Z_DELREF_P(arg); - } - ZVAL_DUP(&tmp, arg); - ZVAL_NEW_REF(arg, &tmp); - Z_ADDREF_P(arg); - } else if (!Z_ISREF_P(arg)) { ZVAL_NEW_REF(arg, arg); - Z_ADDREF_P(arg); - } else if (Z_REFCOUNTED_P(arg)) { - Z_ADDREF_P(arg); } - ZVAL_COPY_VALUE(param, arg); - } else if (Z_ISREF_P(arg) && - /* don't separate references for __call */ - (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) { - ZVAL_DUP(param, Z_REFVAL_P(arg)); + Z_ADDREF_P(arg); } else { - ZVAL_COPY(param, arg); + if (Z_ISREF_P(arg) && + (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) { + /* don't separate references for __call */ + arg = Z_REFVAL_P(arg); + } + if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } } + ZVAL_COPY_VALUE(param, arg); FREE_OP1(); CHECK_EXCEPTION(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index baa176529a..a03d07ae1c 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1115,7 +1115,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_O } else { uint32_t arg_num; HashTable *ht; - zval *arg, *param, tmp; + zval *arg, *param; send_array: ht = Z_ARRVAL_P(args); @@ -1141,24 +1141,7 @@ send_array: param = ZEND_CALL_ARG(EX(call), 1); ZEND_HASH_FOREACH_VAL(ht, arg) { if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - // TODO: Scalar values don't have reference counters anymore. - // They are assumed to be 1, and they may be easily passed by - // reference now. However, previously scalars with refcount==1 - // might be passed and with refcount>1 might not. We can support - // only single behavior ??? -#if 0 - if (Z_REFCOUNTED_P(arg) && - // This solution breaks the following test (omit warning message) ??? - // Zend/tests/bug61273.phpt - // ext/reflection/tests/bug42976.phpt - // ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt -#else - if (!Z_REFCOUNTED_P(arg) || - // This solution breaks the following test (emit warning message) ??? - // ext/pdo_sqlite/tests/pdo_005.phpt -#endif - (!Z_ISREF_P(arg) && Z_REFCOUNT_P(arg) > 1)) { - + if (UNEXPECTED(!Z_ISREF_P(arg))) { if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num)) { zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given", @@ -1180,26 +1163,20 @@ send_array: break; } - if (Z_REFCOUNTED_P(arg)) { - Z_DELREF_P(arg); - } - ZVAL_DUP(&tmp, arg); - ZVAL_NEW_REF(arg, &tmp); - Z_ADDREF_P(arg); - } else if (!Z_ISREF_P(arg)) { ZVAL_NEW_REF(arg, arg); - Z_ADDREF_P(arg); - } else if (Z_REFCOUNTED_P(arg)) { + } + Z_ADDREF_P(arg); + } else{ + if (Z_ISREF_P(arg) && + (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) { + /* don't separate references for __call */ + arg = Z_REFVAL_P(arg); + } + if (Z_OPT_REFCOUNTED_P(arg)) { Z_ADDREF_P(arg); } - ZVAL_COPY_VALUE(param, arg); - } else if (Z_ISREF_P(arg) && - /* don't separate references for __call */ - (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) { - ZVAL_DUP(param, Z_REFVAL_P(arg)); - } else { - ZVAL_COPY(param, arg); } + ZVAL_COPY_VALUE(param, arg); ZEND_CALL_NUM_ARGS(EX(call))++; arg_num++; param++; @@ -14012,7 +13989,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *arg, *param, tmp; + zval *arg, *param; zend_free_op free_op1; SAVE_OPLINE(); @@ -14020,23 +13997,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEN param = ZEND_CALL_VAR(EX(call), opline->result.var); if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { - // TODO: Scalar values don't have reference counters anymore. - // They are assumed to be 1, and they may be easily passed by - // reference now. However, previously scalars with refcount==1 - // might be passed and with refcount>1 might not. We can support - // only single behavior ??? -#if 0 - if (Z_REFCOUNTED_P(arg) && - // This solution breaks the following test (omit warning message) ??? - // Zend/tests/bug61273.phpt - // ext/reflection/tests/bug42976.phpt - // ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt -#else - if (!Z_REFCOUNTED_P(arg) || - // This solution breaks the following test (emit warning message) ??? - // ext/pdo_sqlite/tests/pdo_005.phpt -#endif - (!Z_ISREF_P(arg) /*&& Z_REFCOUNT_P(arg) > 1???*/)) { + if (UNEXPECTED(!Z_ISREF_P(arg))) { if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { @@ -14062,26 +14023,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEN ZEND_VM_NEXT_OPCODE(); } - if (Z_REFCOUNTED_P(arg)) { - Z_DELREF_P(arg); - } - ZVAL_DUP(&tmp, arg); - ZVAL_NEW_REF(arg, &tmp); - Z_ADDREF_P(arg); - } else if (!Z_ISREF_P(arg)) { ZVAL_NEW_REF(arg, arg); - Z_ADDREF_P(arg); - } else if (Z_REFCOUNTED_P(arg)) { - Z_ADDREF_P(arg); } - ZVAL_COPY_VALUE(param, arg); - } else if (Z_ISREF_P(arg) && - /* don't separate references for __call */ - (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) { - ZVAL_DUP(param, Z_REFVAL_P(arg)); + Z_ADDREF_P(arg); } else { - ZVAL_COPY(param, arg); + if (Z_ISREF_P(arg) && + (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) { + /* don't separate references for __call */ + arg = Z_REFVAL_P(arg); + } + if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } } + ZVAL_COPY_VALUE(param, arg); zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); @@ -27605,7 +27560,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_HANDLER(ZE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *arg, *param, tmp; + zval *arg, *param; SAVE_OPLINE(); @@ -27613,23 +27568,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND param = ZEND_CALL_VAR(EX(call), opline->result.var); if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { - // TODO: Scalar values don't have reference counters anymore. - // They are assumed to be 1, and they may be easily passed by - // reference now. However, previously scalars with refcount==1 - // might be passed and with refcount>1 might not. We can support - // only single behavior ??? -#if 0 - if (Z_REFCOUNTED_P(arg) && - // This solution breaks the following test (omit warning message) ??? - // Zend/tests/bug61273.phpt - // ext/reflection/tests/bug42976.phpt - // ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt -#else - if (!Z_REFCOUNTED_P(arg) || - // This solution breaks the following test (emit warning message) ??? - // ext/pdo_sqlite/tests/pdo_005.phpt -#endif - (!Z_ISREF_P(arg) /*&& Z_REFCOUNT_P(arg) > 1???*/)) { + if (UNEXPECTED(!Z_ISREF_P(arg))) { if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { @@ -27654,26 +27593,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND ZEND_VM_NEXT_OPCODE(); } - if (Z_REFCOUNTED_P(arg)) { - Z_DELREF_P(arg); - } - ZVAL_DUP(&tmp, arg); - ZVAL_NEW_REF(arg, &tmp); - Z_ADDREF_P(arg); - } else if (!Z_ISREF_P(arg)) { ZVAL_NEW_REF(arg, arg); - Z_ADDREF_P(arg); - } else if (Z_REFCOUNTED_P(arg)) { - Z_ADDREF_P(arg); } - ZVAL_COPY_VALUE(param, arg); - } else if (Z_ISREF_P(arg) && - /* don't separate references for __call */ - (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) { - ZVAL_DUP(param, Z_REFVAL_P(arg)); + Z_ADDREF_P(arg); } else { - ZVAL_COPY(param, arg); + if (Z_ISREF_P(arg) && + (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) { + /* don't separate references for __call */ + arg = Z_REFVAL_P(arg); + } + if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } } + ZVAL_COPY_VALUE(param, arg); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 12abb704aa..5e62bad6e4 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -1474,49 +1474,49 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam { spl_array_object *intern = Z_SPLARRAY_P(getThis()); HashTable *aht = spl_array_get_hash_table(intern, 0); - zval tmp, *arg = NULL; - zval retval; + zval function_name, params[2], *arg = NULL; uint32_t old_refcount; + ZVAL_STRINGL(&function_name, fname, fname_len); + /* A tricky way to pass "aht" by reference, reset refcount */ //??? It may be not safe, if user comparison handler accesses "aht" old_refcount = GC_REFCOUNT(aht); GC_REFCOUNT(aht) = 1; - ZVAL_ARR(&tmp, aht); + ZVAL_NEW_EMPTY_REF(¶ms[0]); + ZVAL_ARR(Z_REFVAL(params[0]), aht); if (!use_arg) { aht->u.v.nApplyCount++; - zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval, 1, &tmp, NULL); + call_user_function_ex(EG(function_table), NULL, &function_name, return_value, 1, params, 1, NULL); aht->u.v.nApplyCount--; } else if (use_arg == SPL_ARRAY_METHOD_MAY_USER_ARG) { if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "|z", &arg) == FAILURE) { - GC_REFCOUNT(aht) = old_refcount; zend_throw_exception(spl_ce_BadMethodCallException, "Function expects one argument at most", 0); - return; + goto exit; + } + if (arg) { + ZVAL_COPY_VALUE(¶ms[1], arg); } aht->u.v.nApplyCount++; - zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval, arg? 2 : 1, &tmp, arg); + call_user_function_ex(EG(function_table), NULL, &function_name, return_value, arg ? 2 : 1, params, 1, NULL); aht->u.v.nApplyCount--; } else { if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "z", &arg) == FAILURE) { - GC_REFCOUNT(aht) = old_refcount; zend_throw_exception(spl_ce_BadMethodCallException, "Function expects exactly one argument", 0); - return; + goto exit; } + ZVAL_COPY_VALUE(¶ms[1], arg); aht->u.v.nApplyCount++; - zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval, 2, &tmp, arg); + call_user_function_ex(EG(function_table), NULL, &function_name, return_value, 2, params, 1, NULL); aht->u.v.nApplyCount--; } + +exit: /* A tricky way to pass "aht" by reference, copy back and cleanup */ - if (Z_ISREF(tmp) && Z_TYPE_P(Z_REFVAL(tmp))) { - *aht = *Z_ARRVAL_P(Z_REFVAL(tmp)); - GC_REMOVE_FROM_BUFFER(Z_ARR_P(Z_REFVAL(tmp))); - efree(Z_REF(tmp)); - } GC_REFCOUNT(aht) = old_refcount; - if (!Z_ISUNDEF(retval)) { - ZVAL_COPY_VALUE(return_value, &retval); - } + efree(Z_REF(params[0])); + zend_string_free(Z_STR(function_name)); } /* }}} */ #define SPL_ARRAY_METHOD(cname, fname, use_arg) \ diff --git a/ext/standard/tests/array/array_map_variation2.phpt b/ext/standard/tests/array/array_map_variation2.phpt index 16561abffc..b24aa07bc4 100644 --- a/ext/standard/tests/array/array_map_variation2.phpt +++ b/ext/standard/tests/array/array_map_variation2.phpt @@ -77,16 +77,7 @@ array(4) { [0]=> &string(2) "v1" [1]=> - &array(4) { - ["k1"]=> - &string(2) "v1" - ["k2"]=> - string(2) "v2" - [0]=> - &string(2) "v1" - [1]=> - *RECURSION* - } + *RECURSION* } } }