summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/tests/call_user_func_array_prefer_ref.phpt47
-rw-r--r--Zend/zend_vm_def.h26
-rw-r--r--Zend/zend_vm_execute.h26
3 files changed, 51 insertions, 48 deletions
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--
+<?php
+
+namespace {
+ call_user_func_array('array_multisort', [[3, 2, 1]]);
+
+ $args = [[3, 2, 1]];
+ call_user_func_array('array_multisort', $args);
+ var_dump($args);
+ unset($args);
+}
+
+namespace Foo {
+ call_user_func_array('array_multisort', [[3, 2, 1]]);
+
+ $args = [[3, 2, 1]];
+ call_user_func_array('array_multisort', $args);
+ var_dump($args);
+ unset($args);
+}
+
+?>
+--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++;