From: Dmitry Stogov Date: Wed, 10 Jan 2007 15:58:08 +0000 (+0000) Subject: - Fixed bug #35106 (nested foreach fails when array variable has a reference). X-Git-Tag: php-5.2.1RC3~55 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e470e22e20fa327ac7331c560dc034522ca89aae;p=php - Fixed bug #35106 (nested foreach fails when array variable has a reference). - 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). --- diff --git a/NEWS b/NEWS index 9e34a38ce7..b2e33ab4a0 100644 --- 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 index 0000000000..61a66d0147 --- /dev/null +++ b/Zend/tests/bug35106.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #35106 (nested foreach fails when array variable has a reference) +--FILE-- + +--EXPECT-- +12 diff --git a/Zend/tests/bug36214.phpt b/Zend/tests/bug36214.phpt new file mode 100755 index 0000000000..f18ca3e815 --- /dev/null +++ b/Zend/tests/bug36214.phpt @@ -0,0 +1,52 @@ +--TEST-- +Bug #36214 (__get method works properly only when conditional operator is used) +--FILE-- +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) +} diff --git a/Zend/tests/bug38146.phpt b/Zend/tests/bug38146.phpt index 04cb1fa8a0..e321e11c8c 100755 --- a/Zend/tests/bug38146.phpt +++ b/Zend/tests/bug38146.phpt @@ -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 index 0000000000..c725147acf --- /dev/null +++ b/Zend/tests/bug39449.phpt @@ -0,0 +1,40 @@ +--TEST-- +Bug #39449 (Overloaded array properties do not work correctly) +--FILE-- +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 index 0000000000..d7545eeecb --- /dev/null +++ b/Zend/tests/bug39990.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #39990 (Cannot "foreach" over overloaded properties) +--FILE-- +arr as $value) + echo "$value\n"; +?> +--EXPECT-- +Hello +World diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index f7a0012c21..e758e3c80f 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 2d3c6d11c2..f471694611 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -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); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index ddecce87cd..caa0aac2ac 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -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; diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 8756730c88..a206f003ed 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -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; diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index f8d97ac666..b547d99ee8 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -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); diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 0ce0c18731..64e9ebbe61 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -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) \ diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index b22da7a95f..88b9a483fe 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -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 '}' diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index cf7f748aed..fd5128ab28 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -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; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 19782fecde..fcc52c0a4e 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -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: diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 02ff3986b5..ee53a7455c 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -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;