]> granicus.if.org Git - php/commitdiff
- Fixed bug #35106 (nested foreach fails when array variable has a reference).
authorDmitry Stogov <dmitry@php.net>
Wed, 10 Jan 2007 15:58:08 +0000 (15:58 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 10 Jan 2007 15:58:08 +0000 (15:58 +0000)
- Fixed bug #36214 (__get method works properly only when conditional operator is used).
- Fixed bug #39449 (Overloaded array properties do not work correctly).
- Fixed bug #39990 (Cannot "foreach" over overloaded properties).

16 files changed:
NEWS
Zend/tests/bug35106.phpt [new file with mode: 0755]
Zend/tests/bug36214.phpt [new file with mode: 0755]
Zend/tests/bug38146.phpt
Zend/tests/bug39449.phpt [new file with mode: 0755]
Zend/tests/bug39990.phpt [new file with mode: 0755]
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_execute.h
Zend/zend_hash.c
Zend/zend_hash.h
Zend/zend_language_parser.y
Zend/zend_object_handlers.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS
index 9e34a38ce7d3c4e05e72bbb71716acb2722b5391..b2e33ab4a0a882dceb2866d1bc1f6516626d5679 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,13 +13,20 @@ PHP                                                                        NEWS
 - Fixed bug #40036 (empty() does not work correctly with ArrayObject when using
   ARRAY_AS_PROPS). (Ilia)
 - Fixed bug #40002 (Try/Catch performs poorly). (Dmitry)
+- Fixed bug #39990 (Cannot "foreach" over overloaded properties). (Dmitry)
 - Fixed bug #39979 (PGSQL_CONNECT_FORCE_NEW will causes next connect to
   establish a new connection). (Ilia)
 - Fixed bug #39504 (xmlwriter_write_dtd_entity() creates Attlist tag,
   not entity). (Hannes)
+- Fixed bug #39449 (Overloaded array properties do not work correctly).
+  (Dmitry)
 - Fixed bug #39394 (Missing check for older variants of openssl). (Ilia)
 - Fixed bug #38325 (spl_autoload_register() gaves wrong line for "class
   not found"). (Ilia)
+- Fixed bug #36214 (__get method works properly only when conditional operator
+  is used). (Dmitry)
+- Fixed bug #35106 (nested foreach fails when array variable has a reference).
+  (Dmitry)
 
 04 Jan 2007, PHP 5.2.1RC2
 - Small optimization of the date() function (Matt,Ilia)
diff --git a/Zend/tests/bug35106.phpt b/Zend/tests/bug35106.phpt
new file mode 100755 (executable)
index 0000000..61a66d0
--- /dev/null
@@ -0,0 +1,14 @@
+--TEST--
+Bug #35106 (nested foreach fails when array variable has a reference)
+--FILE--
+<?php
+$a=array("1","2");
+$b=&$a;
+foreach($a as $i){
+    echo $i;
+    foreach($a as $p);
+}
+echo "\n";
+?>
+--EXPECT--
+12
diff --git a/Zend/tests/bug36214.phpt b/Zend/tests/bug36214.phpt
new file mode 100755 (executable)
index 0000000..f18ca3e
--- /dev/null
@@ -0,0 +1,52 @@
+--TEST--
+Bug #36214 (__get method works properly only when conditional operator is used)
+--FILE--
+<?php
+class context {
+  public $stack = array();
+
+  public function __set($name,$var) {
+    $this->stack[$name] = $var;return;
+  }
+
+  public function &__get($name) {
+    return $this->stack[$name];
+  }
+}
+
+$ctx = new context;
+$ctx->comment_preview = array();
+$ctx->comment_preview[0] = 1;
+$ctx->comment_preview[1] = 2;
+var_dump($ctx->comment_preview);
+
+$comment_preview = array();
+$comment_preview[0] = 1;
+$comment_preview[1] = 2;
+$ctx->comment_preview = $comment_preview;
+var_dump($ctx->comment_preview);
+
+$ctx->comment_preview = new ArrayObject();
+$ctx->comment_preview[0] = 1;
+$ctx->comment_preview[1] = 2;
+var_dump($ctx->comment_preview);
+?>
+--EXPECT--
+array(2) {
+  [0]=>
+  int(1)
+  [1]=>
+  int(2)
+}
+array(2) {
+  [0]=>
+  int(1)
+  [1]=>
+  int(2)
+}
+object(ArrayObject)#2 (2) {
+  [0]=>
+  int(1)
+  [1]=>
+  int(2)
+}
index 04cb1fa8a0f041aef1e044950d9c492ffe6cd496..e321e11c8c65d5770f2a1b016fb88328f3466292 100755 (executable)
@@ -14,7 +14,6 @@ foreach($f->bar as $key => $value) {
     print "$key => $value\n";
 }
 ?>
---EXPECTF--
-Notice: Indirect modification of overloaded property foo::$bar has no effect in %sbug38146.php on line 10
+--EXPECT--
 foo => bar
 bar => foo
diff --git a/Zend/tests/bug39449.phpt b/Zend/tests/bug39449.phpt
new file mode 100755 (executable)
index 0000000..c725147
--- /dev/null
@@ -0,0 +1,40 @@
+--TEST--
+Bug #39449 (Overloaded array properties do not work correctly)
+--FILE--
+<?php
+class A {
+  private $keys = array();
+  public function & __get($val) {
+    return $this->keys[$val];
+  }
+  public function __set($k, $v) {
+    $this->keys[$k] = $v;
+  }
+}
+
+$a =new A();
+$a->arr = array('a','b','c');
+
+$b = &$a->arr;
+$b[]= 'd';
+
+foreach ($a->arr as $k => $v) {
+  echo "$k => $v\n";
+}
+
+$a->arr[]='d';
+
+foreach ($a->arr as $k => $v) {
+  echo "$k => $v\n";
+}
+?>
+--EXPECT--
+0 => a
+1 => b
+2 => c
+3 => d
+0 => a
+1 => b
+2 => c
+3 => d
+4 => d
diff --git a/Zend/tests/bug39990.phpt b/Zend/tests/bug39990.phpt
new file mode 100755 (executable)
index 0000000..d7545ee
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Bug #39990 (Cannot "foreach" over overloaded properties)
+--FILE--
+<?php
+  class Foo {
+    public function __get($name) {
+      return array('Hello', 'World');    
+    }
+  }
+  
+  $obj=new Foo();
+  foreach($obj->arr as $value)
+    echo "$value\n";
+?>
+--EXPECT--
+Hello
+World
index f7a0012c21a9edd74ee258a87ce029061e95a3e8..e758e3c80fd5932d3934541bca22d83a10a28ea6 100644 (file)
@@ -3677,11 +3677,12 @@ void zend_do_instanceof(znode *result, znode *expr, znode *class_znode, int type
 }
 
 
-void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, znode *array, int variable TSRMLS_DC)
+void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, znode *array, znode *as_token, int variable TSRMLS_DC)
 {
        zend_op *opline;
        zend_bool is_variable;
        zend_bool push_container = 0;
+       zend_op dummy_opline;
 
        if (variable) {
                if (zend_is_function_or_method_call(array)) {
@@ -3689,6 +3690,8 @@ void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, zno
                } else {
                        is_variable = 1;
                }
+               /* save the location of FETCH_W instruction(s) */
+               open_brackets_token->u.opline_num = get_next_op_number(CG(active_op_array));
                zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
                if (CG(active_op_array)->last > 0 &&
                    CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode == ZEND_FETCH_OBJ_W) {
@@ -3700,6 +3703,7 @@ void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, zno
                }
        } else {
                is_variable = 0;
+               open_brackets_token->u.opline_num = get_next_op_number(CG(active_op_array));
        }
 
        /* save the location of FE_RESET */
@@ -3714,28 +3718,17 @@ void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, zno
        opline->op1 = *array;
        SET_UNUSED(opline->op2);
        opline->extended_value = is_variable ? ZEND_FE_RESET_VARIABLE : 0;
-       *open_brackets_token = opline->result;
 
-       {
-               zend_op dummy_opline;
-
-               dummy_opline.result = opline->result;
-               if (push_container) {
-                       dummy_opline.op1 = CG(active_op_array)->opcodes[CG(active_op_array)->last-2].op1;
-               } else {
-                       znode tmp;
+       dummy_opline.result = opline->result;
+       if (push_container) {
+               dummy_opline.op1 = CG(active_op_array)->opcodes[CG(active_op_array)->last-2].op1;
+       } else {
+               znode tmp;
 
-                       tmp.op_type = IS_UNUSED;
-                       dummy_opline.op1 = tmp;
-               }
-               zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
+               tmp.op_type = IS_UNUSED;
+               dummy_opline.op1 = tmp;
        }
-}
-
-
-void zend_do_foreach_fetch(znode *foreach_token, znode *open_brackets_token, znode *as_token TSRMLS_DC)
-{
-       zend_op *opline;
+       zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
 
        /* save the location of FE_FETCH */
        as_token->u.opline_num = get_next_op_number(CG(active_op_array));
@@ -3744,7 +3737,7 @@ void zend_do_foreach_fetch(znode *foreach_token, znode *open_brackets_token, zno
        opline->opcode = ZEND_FE_FETCH;
        opline->result.op_type = IS_VAR;
        opline->result.u.var = get_temporary_variable(CG(active_op_array));
-       opline->op1 = *open_brackets_token;
+       opline->op1 = dummy_opline.result;
        opline->extended_value = 0;
        SET_UNUSED(opline->op2);
 
@@ -3756,7 +3749,7 @@ void zend_do_foreach_fetch(znode *foreach_token, znode *open_brackets_token, zno
 }
 
 
-void zend_do_foreach_cont(znode *foreach_token, znode *as_token, znode *value, znode *key TSRMLS_DC)
+void zend_do_foreach_cont(znode *foreach_token, znode *open_brackets_token, znode *as_token, znode *value, znode *key TSRMLS_DC)
 {
        zend_op *opline;
        znode dummy, value_node;
@@ -3787,6 +3780,19 @@ void zend_do_foreach_cont(znode *foreach_token, znode *as_token, znode *value, z
                /* Mark extended_value for assign-by-reference */
                opline->extended_value |= ZEND_FE_FETCH_BYREF;
                CG(active_op_array)->opcodes[foreach_token->u.opline_num].extended_value |= ZEND_FE_RESET_REFERENCE;
+       } else {
+               zend_op *foreach_copy;
+               zend_op *fetch = &CG(active_op_array)->opcodes[foreach_token->u.opline_num];
+               zend_op *end = &CG(active_op_array)->opcodes[open_brackets_token->u.opline_num];
+
+               /* Change "write context" into "read context" */
+               fetch->extended_value = 0;  /* reset ZEND_FE_RESET_VARIABLE */
+               while (fetch != end) {
+                       (--fetch)->opcode -= 3; /* FETCH_W -> FETCH_R */
+               }
+               /* prevent double SWITCH_FREE */
+               zend_stack_top(&CG(foreach_copy_stack), (void **) &foreach_copy);
+               foreach_copy->op1.op_type = IS_UNUSED;
        }
 
        value_node = opline->result;
index 2d3c6d11c210213c098ed6cd2e4877ca33c33ed7..f47169461128530f34113a444d15422c74eef9cc 100644 (file)
@@ -476,9 +476,8 @@ void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC
 
 void zend_do_instanceof(znode *result, znode *expr, znode *class_znode, int type TSRMLS_DC);
 
-void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, znode *array, int variable TSRMLS_DC);
-void zend_do_foreach_fetch(znode *foreach_token, znode *open_brackets_token, znode *as_token TSRMLS_DC);
-void zend_do_foreach_cont(znode *foreach_token, znode *as_token, znode *value, znode *key TSRMLS_DC);
+void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, znode *array, znode *as_token, int variable TSRMLS_DC);
+void zend_do_foreach_cont(znode *foreach_token, znode *open_brackets_token, znode *as_token, znode *value, znode *key TSRMLS_DC);
 void zend_do_foreach_end(znode *foreach_token, znode *as_token TSRMLS_DC);
 
 void zend_do_declare_begin(TSRMLS_D);
index ddecce87cdd26b397ee1beb8bbbcfac6149af08f..caa0aac2ac577f6e3e9a88ac3dcb8efd1c21e0c8 100644 (file)
@@ -1163,7 +1163,8 @@ static void zend_fetch_dimension_address(temp_variable *result, zval **container
                                overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC);
 
                                if (overloaded_result) {
-                                       if (type == BP_VAR_W || type == BP_VAR_RW  || type == BP_VAR_UNSET) {
+                                       if (!overloaded_result->is_ref &&
+                                           (type == BP_VAR_W || type == BP_VAR_RW  || type == BP_VAR_UNSET)) {
                                                if (overloaded_result->refcount > 0) {
                                                        zval *tmp = overloaded_result;
 
index 8756730c889230e9a30eaf5fda7ff12e2a741566..a206f003ed077c88a5857316233c51e092467bf8 100644 (file)
@@ -41,6 +41,12 @@ typedef union _temp_variable {
                zval *str;
                zend_uint offset;
        } str_offset;
+       struct {
+               zval **ptr_ptr;
+               zval *ptr;
+               zend_bool fcall_returned_reference;
+               HashPointer fe_pos;
+       } fe;
        zend_class_entry *class_entry;
 } temp_variable;
 
index f8d97ac66675ed9992d05c3ebb3073b9e2b6e36c..b547d99ee8f4c3b4e6ad8cd6fece6849ce114317 100644 (file)
@@ -1006,6 +1006,37 @@ ZEND_API int zend_hash_num_elements(HashTable *ht)
 }
 
 
+ZEND_API int zend_hash_get_pointer(HashTable *ht, HashPointer *ptr)
+{
+       ptr->pos = ht->pInternalPointer;
+       if (ht->pInternalPointer) {
+               ptr->h = ht->pInternalPointer->h;
+               return 1;
+       } else {
+               ptr->h = 0;
+               return 0;
+       }
+}
+
+ZEND_API int zend_hash_set_pointer(HashTable *ht, const HashPointer *ptr)
+{
+       if (ht->pInternalPointer != ptr->pos) {
+               Bucket *p;
+
+               IS_CONSISTENT(ht);
+               p = ht->arBuckets[ptr->h & ht->nTableMask];
+               while (p != NULL) {
+                       if (p == ptr->pos) {
+                               ht->pInternalPointer = p;
+                               return 1;
+                       }
+                       p = p->pNext;
+               }
+               return 0;
+       }
+       return 1;
+}
+
 ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos)
 {
        IS_CONSISTENT(ht);
index 0ce0c187311642e57083f0e15f4e718723c42cc9..64e9ebbe61d65828d84f00f17ada12f07f75b0dd 100644 (file)
@@ -176,6 +176,14 @@ ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *p
 ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos);
 ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, char *str_index, uint str_length, ulong num_index, HashPosition *pos);
 
+typedef struct _HashPointer {
+       HashPosition pos;
+       ulong h;
+} HashPointer;
+
+ZEND_API int zend_hash_get_pointer(HashTable *ht, HashPointer *ptr);
+ZEND_API int zend_hash_set_pointer(HashTable *ht, const HashPointer *ptr);
+
 #define zend_hash_has_more_elements(ht) \
        zend_hash_has_more_elements_ex(ht, NULL)
 #define zend_hash_move_forward(ht) \
index b22da7a95f2458a770e1107d1879261c4080aa6c..88b9a483fea2fda557c5cc0f014f08baa2f230d8 100644 (file)
@@ -214,14 +214,14 @@ unticked_statement:
        |       expr ';'                                { zend_do_free(&$1 TSRMLS_CC); }
        |       T_USE use_filename ';'          { zend_error(E_COMPILE_ERROR,"use: Not yet supported. Please use include_once() or require_once()");  zval_dtor(&$2.u.constant); }
        |       T_UNSET '(' unset_variables ')' ';'
-       |       T_FOREACH '(' variable { zend_do_foreach_begin(&$1, &$2, &$3, 1 TSRMLS_CC); } T_AS
-               { zend_do_foreach_fetch(&$1, &$2, &$5 TSRMLS_CC); }
-               foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$1, &$5, &$7, &$8 TSRMLS_CC); }
-               foreach_statement { zend_do_foreach_end(&$1, &$5 TSRMLS_CC); }
-       |       T_FOREACH '(' expr_without_variable { zend_do_foreach_begin(&$1, &$2, &$3, 0 TSRMLS_CC); } T_AS
-               { zend_do_foreach_fetch(&$1, &$2, &$5 TSRMLS_CC); }
-               variable foreach_optional_arg ')' { zend_check_writable_variable(&$7); zend_do_foreach_cont(&$1, &$5, &$7, &$8 TSRMLS_CC); }
-               foreach_statement { zend_do_foreach_end(&$1, &$5 TSRMLS_CC); }
+       |       T_FOREACH '(' variable T_AS
+               { zend_do_foreach_begin(&$1, &$2, &$3, &$4, 1 TSRMLS_CC); }
+               foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
+               foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
+       |       T_FOREACH '(' expr_without_variable T_AS
+               { zend_do_foreach_begin(&$1, &$2, &$3, &$4, 0 TSRMLS_CC); }
+               variable foreach_optional_arg ')' { zend_check_writable_variable(&$6); zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
+               foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
        |       T_DECLARE { $1.u.opline_num = get_next_op_number(CG(active_op_array)); zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(&$1 TSRMLS_CC); }
        |       ';'             /* empty statement */
        |       T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}'
index cf7f748aed943b2592ef4451eb966f3c0122d8ce..fd5128ab289e972362e94f92678cd34ce989b0df 100644 (file)
@@ -334,7 +334,8 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC)
 
                        if (rv) {
                                retval = &rv;
-                               if (type == BP_VAR_W || type == BP_VAR_RW  || type == BP_VAR_UNSET) {
+                               if (!rv->is_ref &&
+                                   (type == BP_VAR_W || type == BP_VAR_RW  || type == BP_VAR_UNSET)) {
                                        if (rv->refcount > 0) {
                                                zval *tmp = rv;
 
index 19782fecdeb237f3750741fb8af0ace3bfbde653..fcc52c0a4e4763bde3f95a673c2fe893949afc8f 100644 (file)
@@ -3207,6 +3207,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
                        }
                }
                is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
+               zend_hash_get_pointer(fe_ht, &EX_T(opline->result.u.var).fe.fe_pos);
        } else {
                zend_error(E_WARNING, "Invalid argument supplied for foreach()");
                is_empty = 1;
@@ -3251,6 +3252,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
                        zend_object *zobj = zend_objects_get_address(array TSRMLS_CC);
 
                        fe_ht = HASH_OF(array);
+                       zend_hash_set_pointer(fe_ht, &EX_T(opline->op1.u.var).fe.fe_pos);
                        do {
                                if (zend_hash_get_current_data(fe_ht, (void **) &value)==FAILURE) {
                                        /* reached end of iteration */
@@ -3262,6 +3264,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
                        } while (key_type == HASH_KEY_NON_EXISTANT ||
                                 (key_type != HASH_KEY_IS_LONG &&
                                  zend_check_property_access(zobj, str_key, str_key_len-1 TSRMLS_CC) != SUCCESS));
+                       zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.u.var).fe.fe_pos);
                        if (use_key && key_type != HASH_KEY_IS_LONG) {
                                zend_unmangle_property_name(str_key, str_key_len-1, &class_name, &prop_name);
                                str_key_len = strlen(prop_name);
@@ -3273,6 +3276,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
 
                case ZEND_ITER_PLAIN_ARRAY:
                        fe_ht = HASH_OF(array);
+                       zend_hash_set_pointer(fe_ht, &EX_T(opline->op1.u.var).fe.fe_pos);
                        if (zend_hash_get_current_data(fe_ht, (void **) &value)==FAILURE) {
                                /* reached end of iteration */
                                ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
@@ -3281,6 +3285,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
                                key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 1, NULL);
                        }
                        zend_hash_move_forward(fe_ht);
+                       zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.u.var).fe.fe_pos);
                        break;
 
                case ZEND_ITER_OBJECT:
index 02ff3986b57e6e991ca05a91b42040bbd9ed6ed7..ee53a7455ce6f6406b8f4d1e06494c8076920c18 100644 (file)
@@ -2256,6 +2256,7 @@ static int ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                        }
                }
                is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
+               zend_hash_get_pointer(fe_ht, &EX_T(opline->result.u.var).fe.fe_pos);
        } else {
                zend_error(E_WARNING, "Invalid argument supplied for foreach()");
                is_empty = 1;
@@ -4796,6 +4797,7 @@ static int ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                        }
                }
                is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
+               zend_hash_get_pointer(fe_ht, &EX_T(opline->result.u.var).fe.fe_pos);
        } else {
                zend_error(E_WARNING, "Invalid argument supplied for foreach()");
                is_empty = 1;
@@ -7926,6 +7928,7 @@ static int ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                        }
                }
                is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
+               zend_hash_get_pointer(fe_ht, &EX_T(opline->result.u.var).fe.fe_pos);
        } else {
                zend_error(E_WARNING, "Invalid argument supplied for foreach()");
                is_empty = 1;
@@ -7970,6 +7973,7 @@ static int ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                        zend_object *zobj = zend_objects_get_address(array TSRMLS_CC);
 
                        fe_ht = HASH_OF(array);
+                       zend_hash_set_pointer(fe_ht, &EX_T(opline->op1.u.var).fe.fe_pos);
                        do {
                                if (zend_hash_get_current_data(fe_ht, (void **) &value)==FAILURE) {
                                        /* reached end of iteration */
@@ -7981,6 +7985,7 @@ static int ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                        } while (key_type == HASH_KEY_NON_EXISTANT ||
                                 (key_type != HASH_KEY_IS_LONG &&
                                  zend_check_property_access(zobj, str_key, str_key_len-1 TSRMLS_CC) != SUCCESS));
+                       zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.u.var).fe.fe_pos);
                        if (use_key && key_type != HASH_KEY_IS_LONG) {
                                zend_unmangle_property_name(str_key, str_key_len-1, &class_name, &prop_name);
                                str_key_len = strlen(prop_name);
@@ -7992,6 +7997,7 @@ static int ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 
                case ZEND_ITER_PLAIN_ARRAY:
                        fe_ht = HASH_OF(array);
+                       zend_hash_set_pointer(fe_ht, &EX_T(opline->op1.u.var).fe.fe_pos);
                        if (zend_hash_get_current_data(fe_ht, (void **) &value)==FAILURE) {
                                /* reached end of iteration */
                                ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
@@ -8000,6 +8006,7 @@ static int ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                                key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 1, NULL);
                        }
                        zend_hash_move_forward(fe_ht);
+                       zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.u.var).fe.fe_pos);
                        break;
 
                case ZEND_ITER_OBJECT:
@@ -19982,6 +19989,7 @@ static int ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                        }
                }
                is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
+               zend_hash_get_pointer(fe_ht, &EX_T(opline->result.u.var).fe.fe_pos);
        } else {
                zend_error(E_WARNING, "Invalid argument supplied for foreach()");
                is_empty = 1;