summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2014-09-20 21:58:06 +0200
committerNikita Popov <nikic@php.net>2014-09-20 21:58:06 +0200
commit6219a4e844e82f8eacd9ad6d24bb92739dcd6ff6 (patch)
tree2c1adab8272d1629669a2fa1365a745bf7f44846
parent2fc1a1dce557875d029f16d58bd3d4cd22af54fb (diff)
parent308c0a727ec496ff551f67052b0835de3c152c11 (diff)
downloadphp-git-6219a4e844e82f8eacd9ad6d24bb92739dcd6ff6.tar.gz
Merge branch 'PHP-5.6'
Conflicts: Zend/zend_compile.c
-rw-r--r--Zend/tests/bug67633.phpt44
-rw-r--r--Zend/zend_compile.c4
2 files changed, 48 insertions, 0 deletions
diff --git a/Zend/tests/bug67633.phpt b/Zend/tests/bug67633.phpt
new file mode 100644
index 0000000000..a9e05d10ab
--- /dev/null
+++ b/Zend/tests/bug67633.phpt
@@ -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"
+}
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index c5337595c5..15902256db 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -3413,6 +3413,10 @@ void zend_compile_foreach(zend_ast *ast TSRMLS_DC) /* {{{ */
zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
}
+ if (by_ref) {
+ zend_separate_if_call_and_write(&expr_node, expr_ast, BP_VAR_W TSRMLS_CC);
+ }
+
opnum_reset = get_next_op_number(CG(active_op_array));
opline = zend_emit_op(&reset_node, ZEND_FE_RESET, &expr_node, NULL TSRMLS_CC);
if (by_ref && is_variable) {