Separating only immutable arrays is not enough.
--- /dev/null
+--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)
+}
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;
}
}
if (separate) {
- zval_copy_ctor(args);
+ SEPARATE_ARRAY(args);
ht = Z_ARRVAL_P(args);
}
}
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));
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;
}
}
if (separate) {
- zval_copy_ctor(args);
+ SEPARATE_ARRAY(args);
ht = Z_ARRVAL_P(args);
}
}
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));