summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@php.net>2006-04-12 11:37:50 +0000
committerDmitry Stogov <dmitry@php.net>2006-04-12 11:37:50 +0000
commitf23d01ad4d7cbc5d1a0d382e1c896bdbfd9ad0d3 (patch)
tree96b826cc0570c9c2efa8464594c810b11c9e7c4f
parent6e762e648cf4d731048b3398baf7974277ab02e0 (diff)
downloadphp-git-f23d01ad4d7cbc5d1a0d382e1c896bdbfd9ad0d3.tar.gz
Fixed bug #37046 (foreach breaks static scope)
-rw-r--r--NEWS3
-rwxr-xr-xZend/tests/bug37046.phpt23
-rw-r--r--Zend/zend_vm_def.h15
-rw-r--r--Zend/zend_vm_execute.h64
4 files changed, 97 insertions, 8 deletions
diff --git a/NEWS b/NEWS
index b3be54834a..30ca4743e5 100644
--- a/NEWS
+++ b/NEWS
@@ -1,8 +1,9 @@
PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? Apr 2006, PHP 5.1.3
+- Fixed bug #37046 (foreach breaks static scope). (Dmitry)
- Fixed bug #37002 (Have to quote literals in INI when concatenating with
- vars). (Dmitry)
+ vars). (Dmitry)
06 Apr 2006, PHP 5.1.3RC3
- Eliminated run-time constant fetching for TRUE, FALSE and NULL. (Dmitry)
diff --git a/Zend/tests/bug37046.phpt b/Zend/tests/bug37046.phpt
new file mode 100755
index 0000000000..8ade2a653c
--- /dev/null
+++ b/Zend/tests/bug37046.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Bug #37046 (foreach breaks static scope)
+--FILE--
+<?php
+function s() {
+ static $storage = array(array('x', 'y'));
+ return $storage[0];
+}
+
+foreach (s() as $k => $function) {
+ echo "op1 $k\n";
+ if ($k == 0) {
+ foreach (s() as $k => $function) {
+ echo "op2 $k\n";
+ }
+ }
+}
+?>
+--EXPEXT--
+op1 0
+op2 0
+op2 1
+op1 1
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 5c1ebc15c9..60851b418a 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -3017,7 +3017,20 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
ce = Z_OBJCE_P(array_ptr);
} else {
- array_ptr->refcount++;
+ if (OP1_TYPE == IS_VAR &&
+ free_op1.var == NULL &&
+ !array_ptr->is_ref &&
+ array_ptr->refcount > 1) {
+ /* non-separated return value from function */
+ zval *tmp;
+
+ ALLOC_ZVAL(tmp);
+ INIT_PZVAL_COPY(tmp, array_ptr);
+ zval_copy_ctor(tmp);
+ array_ptr = tmp;
+ } else {
+ array_ptr->refcount++;
+ }
}
}
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 4ce5c0f3be..be4a32c838 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -2059,7 +2059,7 @@ static int ZEND_UNSET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_op *opline = EX(opline);
-
+ zend_free_op free_op1;
zval *array_ptr, **array_ptr_ptr;
HashTable *fe_ht;
zend_object_iterator *iter = NULL;
@@ -2100,7 +2100,20 @@ static int ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
ce = Z_OBJCE_P(array_ptr);
} else {
- array_ptr->refcount++;
+ if (IS_CONST == IS_VAR &&
+ free_op1.var == NULL &&
+ !array_ptr->is_ref &&
+ array_ptr->refcount > 1) {
+ /* non-separated return value from function */
+ zval *tmp;
+
+ ALLOC_ZVAL(tmp);
+ INIT_PZVAL_COPY(tmp, array_ptr);
+ zval_copy_ctor(tmp);
+ array_ptr = tmp;
+ } else {
+ array_ptr->refcount++;
+ }
}
}
@@ -4518,7 +4531,20 @@ static int ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
ce = Z_OBJCE_P(array_ptr);
} else {
- array_ptr->refcount++;
+ if (IS_TMP_VAR == IS_VAR &&
+ free_op1.var == NULL &&
+ !array_ptr->is_ref &&
+ array_ptr->refcount > 1) {
+ /* non-separated return value from function */
+ zval *tmp;
+
+ ALLOC_ZVAL(tmp);
+ INIT_PZVAL_COPY(tmp, array_ptr);
+ zval_copy_ctor(tmp);
+ array_ptr = tmp;
+ } else {
+ array_ptr->refcount++;
+ }
}
}
@@ -7518,7 +7544,20 @@ static int ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
ce = Z_OBJCE_P(array_ptr);
} else {
- array_ptr->refcount++;
+ if (IS_VAR == IS_VAR &&
+ free_op1.var == NULL &&
+ !array_ptr->is_ref &&
+ array_ptr->refcount > 1) {
+ /* non-separated return value from function */
+ zval *tmp;
+
+ ALLOC_ZVAL(tmp);
+ INIT_PZVAL_COPY(tmp, array_ptr);
+ zval_copy_ctor(tmp);
+ array_ptr = tmp;
+ } else {
+ array_ptr->refcount++;
+ }
}
}
@@ -19576,7 +19615,7 @@ static int ZEND_UNSET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_op *opline = EX(opline);
-
+ zend_free_op free_op1;
zval *array_ptr, **array_ptr_ptr;
HashTable *fe_ht;
zend_object_iterator *iter = NULL;
@@ -19617,7 +19656,20 @@ static int ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
ce = Z_OBJCE_P(array_ptr);
} else {
- array_ptr->refcount++;
+ if (IS_CV == IS_VAR &&
+ free_op1.var == NULL &&
+ !array_ptr->is_ref &&
+ array_ptr->refcount > 1) {
+ /* non-separated return value from function */
+ zval *tmp;
+
+ ALLOC_ZVAL(tmp);
+ INIT_PZVAL_COPY(tmp, array_ptr);
+ zval_copy_ctor(tmp);
+ array_ptr = tmp;
+ } else {
+ array_ptr->refcount++;
+ }
}
}