]> granicus.if.org Git - php/commitdiff
Fixed bug #67633
authorNikita Popov <nikic@php.net>
Sat, 20 Sep 2014 19:46:25 +0000 (21:46 +0200)
committerNikita Popov <nikic@php.net>
Sat, 20 Sep 2014 19:46:25 +0000 (21:46 +0200)
NEWS
Zend/tests/bug67633.phpt [new file with mode: 0644]
Zend/zend_compile.c

diff --git a/NEWS b/NEWS
index 3fc0f8045d11cf9a79310cceee40952eda95d925..50d2707e6c1890ac8fa73944db10cad3c6331565 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,8 @@ PHP                                                                        NEWS
     unset). (Tjerk)
   . Fixed bug #67739 (Windows 8.1/Server 2012 R2 OS build number reported
     as 6.2 (instead of 6.3)). (Christian Wenz)
+  . Fixed bug #67633 (A foreach on an array returned from a function not doing
+    copy-on-write). (Nikita)
 
 - FPM:
   . Fixed bug #65641 (PHP-FPM incorrectly defines the SCRIPT_NAME variable
diff --git a/Zend/tests/bug67633.phpt b/Zend/tests/bug67633.phpt
new file mode 100644 (file)
index 0000000..a9e05d1
--- /dev/null
@@ -0,0 +1,44 @@
+--TEST--
+Bug #67633: A foreach on an array returned from a function not doing copy-on-write
+--FILE--
+<?php
+
+function id($x) {
+    return $x;
+}
+
+function &ref_id(&$x) {
+    return $x;
+}
+
+$c = 'c';
+$array = ['a', 'b', $c];
+
+foreach(id($array) as &$v) {
+    $v .= 'q';
+}
+var_dump($array);
+
+foreach(ref_id($array) as &$v) {
+    $v .= 'q';
+}
+var_dump($array);
+
+?>
+--EXPECT--
+array(3) {
+  [0]=>
+  string(1) "a"
+  [1]=>
+  string(1) "b"
+  [2]=>
+  string(1) "c"
+}
+array(3) {
+  [0]=>
+  string(2) "aq"
+  [1]=>
+  string(2) "bq"
+  [2]=>
+  &string(2) "cq"
+}
index 0ac3bceddcc51cc677fb9e0ac80c6eed5ea69f38..bd3e1dd8131c7ed0e2e443c9f4db51da92dd0d97 100644 (file)
@@ -6231,6 +6231,15 @@ void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, zno
                /* save the location of FETCH_W instruction(s) */
                open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
                zend_do_end_variable_parse(array, BP_VAR_W, 0 TSRMLS_CC);
+
+               if (zend_is_function_or_method_call(array)) {
+                       opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+                       opline->opcode = ZEND_SEPARATE;
+                       SET_NODE(opline->op1, array);
+                       SET_UNUSED(opline->op2);
+                       opline->result_type = IS_VAR;
+                       opline->result.var = opline->op1.var;
+               }
        } else {
                is_variable = 0;
                open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array));