]> 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:59:56 +0000 (15:59 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 10 Jan 2007 15:59:56 +0000 (15:59 +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).

15 files changed:
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/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 ba565d003d0f7c44f812a792eb32165d45449f13..ff581002751097c698aa807129f7d69caab0cdba 100644 (file)
@@ -3900,11 +3900,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)) {
@@ -3912,6 +3913,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) {
@@ -3923,6 +3926,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 */
@@ -3937,28 +3941,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));
@@ -3967,7 +3960,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);
 
@@ -3979,7 +3972,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;
@@ -4010,6 +4003,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 e50e0a0391253e2fb3f7c4b221ce0d2961f74815..6e272afdec8de425d5bc4e58c519d26376e39be7 100644 (file)
@@ -488,9 +488,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 c8292ad5a0e34606c01347fc3247d9cd19087089..e92bf2b606ebd45c326fe0b325eaf292eb4414c0 100644 (file)
@@ -1167,7 +1167,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 498b577fa583c478d35dbc97311a2da905b10119..e9c0c398f9013ddf2b571733f4d886e0d281b8b2 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 d567e7451ca91667aaf6c732bc8ad74a71ed57f7..03b682717f482d9004afecfdfa8205e40fd6dbb8 100644 (file)
@@ -1425,6 +1425,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 3d87e9c01eb34213e8682f3c493642f54284c55c..2de1fef6e400c10a069914ceb1b688c5a27505f7 100644 (file)
@@ -237,6 +237,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, zstr 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 be189bf6a02d08c1c72277e4878395c6600aec34..5d4d7399ddc778596f35880ca96014b10707cd72 100644 (file)
@@ -218,14 +218,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 9ecd4fbb1d82ecc301961425800fc61fdfe0816a..eb4281be0e708d3a9c6f72e0f37431e9a3bfbd08 100644 (file)
@@ -342,7 +342,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 a69e8eb4f55782193790c8c31f617dbd158374df..14f5297797622bc3da75cb0c342edf7e23621e25 100644 (file)
@@ -3293,6 +3293,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;
@@ -3337,6 +3338,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 */
@@ -3348,6 +3350,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, key_type == HASH_KEY_IS_UNICODE?IS_UNICODE:IS_STRING, 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_u_unmangle_property_name(key_type == HASH_KEY_IS_UNICODE?IS_UNICODE:IS_STRING, str_key, str_key_len-1, &class_name, &prop_name);
                                if (key_type == HASH_KEY_IS_UNICODE) {
@@ -3364,6 +3367,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);
@@ -3372,6 +3376,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 1adab93144182660c72c1dfd9b85825a0ee59e1f..da59e3c46d5370787fa2d5df3f492247c5f3bdfa 100644 (file)
@@ -1386,7 +1386,8 @@ static int ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        zval *z = &opline->op1.u.constant;
        UErrorCode status = U_ZERO_ERROR;
 
-       /* Convert inline HTML blocks to the output encoding, but only if necessary. */
+       /* UTODO: review this
+        * Convert inline HTML blocks to the output encoding, but only if necessary. */
        if (opline->extended_value &&
                strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
                           EX(op_array)->script_encoding)) {
@@ -2235,6 +2236,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;
@@ -3992,7 +3994,8 @@ static int ZEND_ECHO_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        zval *z = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
        UErrorCode status = U_ZERO_ERROR;
 
-       /* Convert inline HTML blocks to the output encoding, but only if necessary. */
+       /* UTODO: review this
+        * Convert inline HTML blocks to the output encoding, but only if necessary. */
        if (opline->extended_value &&
                strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
                           EX(op_array)->script_encoding)) {
@@ -4843,6 +4846,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;
@@ -7106,7 +7110,8 @@ static int ZEND_ECHO_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        zval *z = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
        UErrorCode status = U_ZERO_ERROR;
 
-       /* Convert inline HTML blocks to the output encoding, but only if necessary. */
+       /* UTODO: review this
+        * Convert inline HTML blocks to the output encoding, but only if necessary. */
        if (opline->extended_value &&
                strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
                           EX(op_array)->script_encoding)) {
@@ -8056,6 +8061,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;
@@ -8100,6 +8106,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 */
@@ -8111,6 +8118,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, key_type == HASH_KEY_IS_UNICODE?IS_UNICODE:IS_STRING, 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_u_unmangle_property_name(key_type == HASH_KEY_IS_UNICODE?IS_UNICODE:IS_STRING, str_key, str_key_len-1, &class_name, &prop_name);
                                if (key_type == HASH_KEY_IS_UNICODE) {
@@ -8127,6 +8135,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);
@@ -8135,6 +8144,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:
@@ -19678,7 +19688,8 @@ static int ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        zval *z = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
        UErrorCode status = U_ZERO_ERROR;
 
-       /* Convert inline HTML blocks to the output encoding, but only if necessary. */
+       /* UTODO: review this
+        * Convert inline HTML blocks to the output encoding, but only if necessary. */
        if (opline->extended_value &&
                strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
                           EX(op_array)->script_encoding)) {
@@ -20614,6 +20625,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;