diff options
author | Andi Gutmans <andi@php.net> | 2000-08-10 22:08:02 +0000 |
---|---|---|
committer | Andi Gutmans <andi@php.net> | 2000-08-10 22:08:02 +0000 |
commit | e5015ed581823672e65c8251d1b46c0a155d6b4b (patch) | |
tree | 0b2b65094d8d7c81560dc025029682cb2b3fa2a3 /Zend | |
parent | d6f2f2c3965c0ba87d02e09f9d43b17204eeaa98 (diff) | |
download | php-git-e5015ed581823672e65c8251d1b46c0a155d6b4b.tar.gz |
@ Fix problem with nested foreach()'s (Andi, Zend Engine)
Diffstat (limited to 'Zend')
-rw-r--r-- | Zend/zend-parser.y | 3 | ||||
-rw-r--r-- | Zend/zend_compile.c | 7 | ||||
-rw-r--r-- | Zend/zend_compile.h | 2 | ||||
-rw-r--r-- | Zend/zend_execute.c | 29 |
4 files changed, 26 insertions, 15 deletions
diff --git a/Zend/zend-parser.y b/Zend/zend-parser.y index 482e72267b..bf7d7261ca 100644 --- a/Zend/zend-parser.y +++ b/Zend/zend-parser.y @@ -197,7 +197,8 @@ unticked_statement: | expr ';' { do_free(&$1 CLS_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 '(' expr T_AS { do_foreach_begin(&$1, &$3, &$2, &$4 CLS_CC); } w_cvar foreach_optional_arg ')' { do_foreach_cont(&$6, &$7, &$4 CLS_CC); } foreach_statement { do_foreach_end(&$1, &$2 CLS_CC); } + | T_FOREACH '(' w_cvar T_AS { do_foreach_begin(&$1, &$3, &$2, &$4, 1 CLS_CC); } w_cvar foreach_optional_arg ')' { do_foreach_cont(&$6, &$7, &$4 CLS_CC); } foreach_statement { do_foreach_end(&$1, &$2 CLS_CC); } + | T_FOREACH '(' expr_without_variable T_AS { do_foreach_begin(&$1, &$3, &$2, &$4, 0 CLS_CC); } w_cvar foreach_optional_arg ')' { do_foreach_cont(&$6, &$7, &$4 CLS_CC); } foreach_statement { do_foreach_end(&$1, &$2 CLS_CC); } | T_DECLARE { do_declare_begin(CLS_C); } '(' declare_list ')' declare_statement { do_declare_end(CLS_C); } | ';' /* empty statement */ ; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 0629190e22..e76e542ba8 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2012,7 +2012,7 @@ void do_isset_or_isempty(int type, znode *result, znode *variable CLS_DC) } -void do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token CLS_DC) +void do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token, int variable CLS_DC) { zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); @@ -2022,6 +2022,11 @@ void do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_t opline->result.u.var = get_temporary_variable(CG(active_op_array)); opline->op1 = *array; SET_UNUSED(opline->op2); + if (variable) { + opline->extended_value = 1; + } else { + opline->extended_value = 0; + } *open_brackets_token = opline->result; zend_stack_push(&CG(foreach_copy_stack), (void *) &opline->result, sizeof(znode)); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 67a49711fe..bb49951afb 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -344,7 +344,7 @@ void do_include_or_eval(int type, znode *result, znode *op1 CLS_DC); void do_unset(znode *variable CLS_DC); void do_isset_or_isempty(int type, znode *result, znode *variable CLS_DC); -void do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token CLS_DC); +void do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token, int variable CLS_DC); void do_foreach_cont(znode *value, znode *key, znode *as_token CLS_DC); void do_foreach_end(znode *foreach_token, znode *open_brackets_token CLS_DC); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index fbb77e3765..1017543cf3 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2131,22 +2131,27 @@ send_by_ref: } NEXT_OPCODE(); case ZEND_FE_RESET: { - zval *array_ptr; + zval *array_ptr, **array_ptr_ptr; HashTable *fe_ht; - array_ptr = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R); - - if (EG(free_op1)) { /* IS_TMP_VAR */ - zval *tmp; - - ALLOC_ZVAL(tmp); - *tmp = *array_ptr; - INIT_PZVAL(tmp); - array_ptr = tmp; - } else { + if (opline->extended_value) { + array_ptr_ptr = get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_R); + SEPARATE_ZVAL_IF_NOT_REF(array_ptr_ptr); + array_ptr = *array_ptr_ptr; array_ptr->refcount++; + } else { + array_ptr = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R); + if (EG(free_op1)) { /* IS_TMP_VAR */ + zval *tmp; + + ALLOC_ZVAL(tmp); + *tmp = *array_ptr; + INIT_PZVAL(tmp); + array_ptr = tmp; + } else { + array_ptr->refcount++; + } } - PZVAL_LOCK(array_ptr); Ts[opline->result.u.var].var.ptr = array_ptr; Ts[opline->result.u.var].var.ptr_ptr = &Ts[opline->result.u.var].var.ptr; |