From: Nikita Popov Date: Mon, 18 Apr 2016 16:24:45 +0000 (+0200) Subject: Fix SEND_ARRAY+PREFER_REF SHM corruption X-Git-Tag: php-7.1.0alpha1~301^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a8792158bddb9b9eadf6fed1e18ce6125c334fc1;p=php Fix SEND_ARRAY+PREFER_REF SHM corruption Make the behavior consistent between namespaced and not and with PHP 5.6. --- diff --git a/Zend/tests/call_user_func_array_prefer_ref.phpt b/Zend/tests/call_user_func_array_prefer_ref.phpt new file mode 100644 index 0000000000..9c1d822d69 --- /dev/null +++ b/Zend/tests/call_user_func_array_prefer_ref.phpt @@ -0,0 +1,47 @@ +--TEST-- +call_user_func_array() passes value to prefer-ref arg if element wasn't a reference +--FILE-- + +--EXPECT-- +array(1) { + [0]=> + array(3) { + [0]=> + int(3) + [1]=> + int(2) + [2]=> + int(1) + } +} +array(1) { + [0]=> + array(3) { + [0]=> + int(3) + [1]=> + int(2) + [2]=> + int(1) + } +} diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index fd995475fb..6ca584d69f 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4600,22 +4600,6 @@ ZEND_VM_C_LABEL(send_array): ht = Z_ARRVAL_P(args); zend_vm_stack_extend_call_frame(&EX(call), 0, zend_hash_num_elements(ht)); - if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_TMP_VAR && Z_IMMUTABLE_P(args)) { - int separate = 0; - - /* check if any of arguments are going to be passed by reference */ - for (arg_num = 0; arg_num < zend_hash_num_elements(ht); arg_num++) { - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + 1)) { - separate = 1; - break; - } - } - if (separate) { - zval_copy_ctor(args); - ht = Z_ARRVAL_P(args); - } - } - arg_num = 1; param = ZEND_CALL_ARG(EX(call), 1); ZEND_HASH_FOREACH_VAL(ht, arg) { @@ -4641,21 +4625,15 @@ ZEND_VM_C_LABEL(send_array): break; } - - ZVAL_NEW_REF(arg, arg); } - Z_ADDREF_P(arg); - } else{ + } else { if (Z_ISREF_P(arg) && !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { /* 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_COPY(param, arg); ZEND_CALL_NUM_ARGS(EX(call))++; arg_num++; param++; diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index c057695586..90c3d0fa19 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1132,22 +1132,6 @@ send_array: ht = Z_ARRVAL_P(args); zend_vm_stack_extend_call_frame(&EX(call), 0, zend_hash_num_elements(ht)); - if (opline->op1_type != IS_CONST && opline->op1_type != IS_TMP_VAR && Z_IMMUTABLE_P(args)) { - int separate = 0; - - /* check if any of arguments are going to be passed by reference */ - for (arg_num = 0; arg_num < zend_hash_num_elements(ht); arg_num++) { - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + 1)) { - separate = 1; - break; - } - } - if (separate) { - zval_copy_ctor(args); - ht = Z_ARRVAL_P(args); - } - } - arg_num = 1; param = ZEND_CALL_ARG(EX(call), 1); ZEND_HASH_FOREACH_VAL(ht, arg) { @@ -1173,21 +1157,15 @@ send_array: break; } - - ZVAL_NEW_REF(arg, arg); } - Z_ADDREF_P(arg); - } else{ + } else { if (Z_ISREF_P(arg) && !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { /* 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_COPY(param, arg); ZEND_CALL_NUM_ARGS(EX(call))++; arg_num++; param++;