From 45794ee259ce0c6c9ccc32cd149ac97b695f9c67 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 10 Oct 2005 09:50:05 +0000 Subject: [PATCH] Fixed bug #34467 (foreach + __get + __set incosistency) --- NEWS | 1 + Zend/tests/bug34467.phpt | 27 +++++++++++++++ Zend/zend_compile.c | 73 +++++++++++++++++++++++----------------- 3 files changed, 71 insertions(+), 30 deletions(-) create mode 100755 Zend/tests/bug34467.phpt 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++; } } -- 2.50.1