summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/tests/arg_unpack/by_ref_separation.phpt36
-rw-r--r--Zend/zend_vm_def.h6
-rw-r--r--Zend/zend_vm_execute.h6
3 files changed, 42 insertions, 6 deletions
diff --git a/Zend/tests/arg_unpack/by_ref_separation.phpt b/Zend/tests/arg_unpack/by_ref_separation.phpt
new file mode 100644
index 0000000000..b52c28168a
--- /dev/null
+++ b/Zend/tests/arg_unpack/by_ref_separation.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Array must be separated if unpacking by reference
+--FILE--
+<?php
+
+function inc(&... $args) {
+ foreach ($args as &$arg) {
+ $arg++;
+ }
+}
+
+$arr = [1, 2];
+$arr[] = 3;
+$arr2 = $arr;
+inc(...$arr);
+var_dump($arr);
+var_dump($arr2);
+
+?>
+--EXPECT--
+array(3) {
+ [0]=>
+ int(2)
+ [1]=>
+ int(3)
+ [2]=>
+ int(4)
+}
+array(3) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(2)
+ [2]=>
+ int(3)
+}
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 00a9effcfa..8d01d99ee9 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -4422,7 +4422,7 @@ ZEND_VM_C_LABEL(send_again):
zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht));
- if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
+ if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_TMP_VAR && Z_REFCOUNT_P(args) > 1) {
uint32_t i;
int separate = 0;
@@ -4434,7 +4434,7 @@ ZEND_VM_C_LABEL(send_again):
}
}
if (separate) {
- zval_copy_ctor(args);
+ SEPARATE_ARRAY(args);
ht = Z_ARRVAL_P(args);
}
}
@@ -4448,7 +4448,7 @@ ZEND_VM_C_LABEL(send_again):
top = ZEND_CALL_ARG(EX(call), arg_num);
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
- if (!Z_IMMUTABLE_P(args)) {
+ if (Z_REFCOUNT_P(args) == 1) {
ZVAL_MAKE_REF(arg);
Z_ADDREF_P(arg);
ZVAL_REF(top, Z_REF_P(arg));
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 86dbd0ab37..592681cd98 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -954,7 +954,7 @@ send_again:
zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht));
- if (opline->op1_type != IS_CONST && opline->op1_type != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
+ if (opline->op1_type != IS_CONST && opline->op1_type != IS_TMP_VAR && Z_REFCOUNT_P(args) > 1) {
uint32_t i;
int separate = 0;
@@ -966,7 +966,7 @@ send_again:
}
}
if (separate) {
- zval_copy_ctor(args);
+ SEPARATE_ARRAY(args);
ht = Z_ARRVAL_P(args);
}
}
@@ -980,7 +980,7 @@ send_again:
top = ZEND_CALL_ARG(EX(call), arg_num);
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
- if (!Z_IMMUTABLE_P(args)) {
+ if (Z_REFCOUNT_P(args) == 1) {
ZVAL_MAKE_REF(arg);
Z_ADDREF_P(arg);
ZVAL_REF(top, Z_REF_P(arg));