From: Dmitry Stogov Date: Mon, 10 Oct 2005 09:50:05 +0000 (+0000) Subject: Fixed bug #34467 (foreach + __get + __set incosistency) X-Git-Tag: php-5.1.0RC2~50 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=45794ee259ce0c6c9ccc32cd149ac97b695f9c67;p=php Fixed bug #34467 (foreach + __get + __set incosistency) --- diff --git a/NEWS b/NEWS index 2cc68dd59f..37cfe1d1b6 100644 --- a/NEWS +++ b/NEWS @@ -70,6 +70,7 @@ PHP NEWS - Fixed bug #34505 (Possible memory corruption when unmangling properties with empty names). (Tony) - Fixed bug #34478 (Incorrect parsing of url's fragment (#...)). (Dmitry) +- Fixed bug #34467 (foreach + __get + __set incosistency). (Dmitry) - Fixed bug #34456 (Possible crash inside pspell extension). (Nuno) - Fixed bug #34453 (parsing http://www.w3.org/2001/xml.xsd exception). (Dmitry) - Fixed bug #34450 (Segfault when calling mysqli_close() in destructor). (Tony) diff --git a/Zend/tests/bug34467.phpt b/Zend/tests/bug34467.phpt new file mode 100755 index 0000000000..5f0ccafc4f --- /dev/null +++ b/Zend/tests/bug34467.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #34467 (foreach + __get + __set incosistency) +--FILE-- +arr[$key] = $value; + } + + function __get ($key) { + return $this->arr[$key]; + } +} +$abc = new abc(); +foreach (array (1,2,3) as $abc->k => $abc->v) { + var_dump($abc->k,$abc->v); +} +?> +--EXPECT-- +int(0) +int(1) +int(1) +int(2) +int(2) +int(3) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 4ea2d7c4bc..4ce4f1fe93 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -537,40 +537,53 @@ static zend_bool opline_is_fetch_this(zend_op *opline TSRMLS_DC) void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC) { - int last_op_number = get_next_op_number(CG(active_op_array)); zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); - if (last_op_number > 0) { - zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1]; + if (variable->op_type == IS_VAR) { + int last_op_number = get_next_op_number(CG(active_op_array)); + int n = 0; - if (variable->op_type == IS_VAR && - last_op->opcode == ZEND_FETCH_OBJ_W && - last_op->result.op_type == IS_VAR && - last_op->result.u.var == variable->u.var) { - last_op->opcode = ZEND_ASSIGN_OBJ; - - zend_do_op_data(opline, value TSRMLS_CC); - SET_UNUSED(opline->result); - *result = last_op->result; - return; - } else if (variable->op_type == IS_VAR && - last_op->opcode == ZEND_FETCH_DIM_W && - last_op->result.op_type == IS_VAR && - last_op->result.u.var == variable->u.var) { - last_op->opcode = ZEND_ASSIGN_DIM; - - zend_do_op_data(opline, value TSRMLS_CC); - opline->op2.u.var = get_temporary_variable(CG(active_op_array)); - opline->op2.u.EA.type = 0; - opline->op2.op_type = IS_VAR; - SET_UNUSED(opline->result); - *result = last_op->result; - return; - } else { - if (variable->op_type == IS_VAR && - opline_is_fetch_this(last_op TSRMLS_CC)) { - zend_error(E_COMPILE_ERROR, "Cannot re-assign $this"); + while (last_op_number - n > 0) { + zend_op *last_op; + + last_op = &CG(active_op_array)->opcodes[last_op_number-n-1]; + + if (last_op->result.op_type == IS_VAR && + last_op->result.u.var == variable->u.var) { + if (last_op->opcode == ZEND_FETCH_OBJ_W) { + if (n > 0) { + *opline = *last_op; + MAKE_NOP(last_op); + last_op = opline; + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + } + last_op->opcode = ZEND_ASSIGN_OBJ; + zend_do_op_data(opline, value TSRMLS_CC); + SET_UNUSED(opline->result); + *result = last_op->result; + return; + } else if (last_op->opcode == ZEND_FETCH_DIM_W) { + if (n > 0) { + *opline = *last_op; + MAKE_NOP(last_op); + last_op = opline; + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + } + last_op->opcode = ZEND_ASSIGN_DIM; + zend_do_op_data(opline, value TSRMLS_CC); + opline->op2.u.var = get_temporary_variable(CG(active_op_array)); + opline->op2.u.EA.type = 0; + opline->op2.op_type = IS_VAR; + SET_UNUSED(opline->result); + *result = last_op->result; + return; + } else if (opline_is_fetch_this(last_op TSRMLS_CC)) { + zend_error(E_COMPILE_ERROR, "Cannot re-assign $this"); + } else { + break; + } } + n++; } }