]> granicus.if.org Git - php/commitdiff
Fix SEND_ARRAY+PREFER_REF SHM corruption
authorNikita Popov <nikic@php.net>
Mon, 18 Apr 2016 16:24:45 +0000 (18:24 +0200)
committerNikita Popov <nikic@php.net>
Mon, 18 Apr 2016 16:26:20 +0000 (18:26 +0200)
Make the behavior consistent between namespaced and not and with
PHP 5.6.

Zend/tests/call_user_func_array_prefer_ref.phpt [new file with mode: 0644]
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

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 (file)
index 0000000..9c1d822
--- /dev/null
@@ -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)
+  }
+}
index fd995475fb7b5d3dc7270f3c058eb8aa7c42a515..6ca584d69fb330497fc0ac4cb0973239c359fd84 100644 (file)
@@ -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++;
index c057695586360bbd9ef302ff863e88e3a1e0f3dd..90c3d0fa19cfe76aeeee5e7676c64674a75cd419 100644 (file)
@@ -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++;