]> granicus.if.org Git - php/commitdiff
Fixed bug #37046 (foreach breaks static scope)
authorDmitry Stogov <dmitry@php.net>
Wed, 12 Apr 2006 11:37:50 +0000 (11:37 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 12 Apr 2006 11:37:50 +0000 (11:37 +0000)
NEWS
Zend/tests/bug37046.phpt [new file with mode: 0755]
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS
index b3be54834af09b7a92507335d5c84af432497b48..30ca4743e5c470f7ce989eebe390d547e075df6f 100644 (file)
--- 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 (executable)
index 0000000..8ade2a6
--- /dev/null
@@ -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
index 5c1ebc15c95fdf64e60001155da199bb4a261c8d..60851b418abb6e71c34b59bc424494ff6b7b8d12 100644 (file)
@@ -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++;
+                       }
                }
        }
 
index 4ce5c0f3befd144034a3ab3aeb650037ee18bd9d..be4a32c838866b60209aad46e6891a50c33aa955 100644 (file)
@@ -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++;
+                       }
                }
        }