From 92e90c09f085c22707ff4a59201f016f56e0ef8b Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 28 Jan 2015 12:44:57 +0300 Subject: [PATCH] Fixed operand destruction in case of exceptions in iterator --- Zend/tests/foreach_003.phpt | 71 ++++++++++++++ Zend/tests/foreach_004.phpt | 65 +++++++++++++ Zend/zend_vm_def.h | 56 ++++++++---- Zend/zend_vm_execute.h | 178 ++++++++++++++++++++++++++---------- 4 files changed, 305 insertions(+), 65 deletions(-) create mode 100644 Zend/tests/foreach_003.phpt create mode 100644 Zend/tests/foreach_004.phpt diff --git a/Zend/tests/foreach_003.phpt b/Zend/tests/foreach_003.phpt new file mode 100644 index 0000000000..71b0f2a5a3 --- /dev/null +++ b/Zend/tests/foreach_003.phpt @@ -0,0 +1,71 @@ +--TEST-- +Iterator exceptions in foreach by value +--FILE-- +count = $count; + $this->trap = $trap; + } + + function trap($trap) { + if ($trap === $this->trap) { + throw new Exception($trap); + } + } + + function rewind() {$this->trap(__FUNCTION__); $this->n = 0;} + function valid() {$this->trap(__FUNCTION__); return $this->n < $this->count;} + function key() {$this->trap(__FUNCTION__); return $this->n;} + function current() {$this->trap(__FUNCTION__); return $this->n;} + function next() {$this->trap(__FUNCTION__); $this->n++;} +} + +foreach(['rewind', 'valid', 'key', 'current', 'next'] as $trap) { + $obj = new IT(3, $trap); + try { + // IS_CV + foreach ($obj as $key => $val) echo "$val\n"; + } catch (Exception $e) { + echo $e->getMessage() . "\n"; + } + unset($obj); + + try { + // IS_VAR + foreach (new IT(3, $trap) as $key => $val) echo "$val\n"; + } catch (Exception $e) { + echo $e->getMessage() . "\n"; + } + + try { + // IS_TMP_VAR + foreach ((object)new IT(2, $trap) as $key => $val) echo "$val\n"; + } catch (Exception $e) { + echo $e->getMessage() . "\n"; + } +} +?> +--EXPECT-- +rewind +rewind +rewind +valid +valid +valid +key +key +key +current +current +current +0 +next +0 +next +0 +next diff --git a/Zend/tests/foreach_004.phpt b/Zend/tests/foreach_004.phpt new file mode 100644 index 0000000000..1f754a77ed --- /dev/null +++ b/Zend/tests/foreach_004.phpt @@ -0,0 +1,65 @@ +--TEST-- +Iterator exceptions in foreach by reference +--FILE-- +trap = $trap; + } + + function trap($trap) { + if ($trap === $this->trap) { + throw new Exception($trap); + } + } + + function rewind() {$this->trap(__FUNCTION__); return parent::rewind();} + function valid() {$this->trap(__FUNCTION__); return parent::valid();} + function key() {$this->trap(__FUNCTION__); return parent::key();} + function next() {$this->trap(__FUNCTION__); return parent::next();} +} + +foreach(['rewind', 'valid', 'key', 'next'] as $trap) { + $obj = new IT($trap); + try { + // IS_CV + foreach ($obj as $key => &$val) echo "$val\n"; + } catch (Exception $e) { + echo $e->getMessage() . "\n"; + } + unset($obj); + + try { + // IS_VAR + foreach (new IT($trap) as $key => &$val) echo "$val\n"; + } catch (Exception $e) { + echo $e->getMessage() . "\n"; + } + + try { + // IS_TMP_VAR + foreach ((object)new IT($trap) as $key => &$val) echo "$val\n"; + } catch (Exception $e) { + echo $e->getMessage() . "\n"; + } +} +?> +--EXPECT-- +rewind +rewind +rewind +valid +valid +valid +key +key +key +0 +next +0 +next +0 +next diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index b04324c4ed..52a24d0859 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4637,7 +4637,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, ANY) zend_bool is_empty; if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - FREE_OP1_IF_VAR(); + FREE_OP1(); if (!EG(exception)) { zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } @@ -4649,8 +4649,8 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, ANY) if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - FREE_OP1_IF_VAR(); OBJ_RELEASE(&iter->std); + FREE_OP1(); HANDLE_EXCEPTION(); } } @@ -4658,15 +4658,15 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, ANY) is_empty = iter->funcs->valid(iter) != SUCCESS; if (UNEXPECTED(EG(exception) != NULL)) { - FREE_OP1_IF_VAR(); OBJ_RELEASE(&iter->std); + FREE_OP1(); HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); - FREE_OP1_IF_VAR(); + FREE_OP1(); if (is_empty) { ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } else { @@ -4674,13 +4674,13 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, ANY) ZEND_VM_NEXT_OPCODE(); } } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - if (OP1_TYPE != IS_TMP_VAR) { - if (Z_REFCOUNTED_P(array_ptr)) { - Z_ADDREF_P(array_ptr); - } + zval *result = EX_VAR(opline->result.var); + + ZVAL_COPY_VALUE(result, array_ptr); + if (OP1_TYPE != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(array_ptr); } - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ptr); - Z_FE_POS_P(EX_VAR(opline->result.var)) = 0; + Z_FE_POS_P(result) = 0; FREE_OP1_IF_VAR(); CHECK_EXCEPTION(); @@ -4720,7 +4720,11 @@ ZEND_VM_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, ANY) zend_bool is_empty; if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - FREE_OP1_VAR_PTR(); + if (OP1_TYPE == IS_VAR) { + FREE_OP1_VAR_PTR(); + } else { + FREE_OP1(); + } if (!EG(exception)) { zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } @@ -4732,8 +4736,12 @@ ZEND_VM_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, ANY) if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - FREE_OP1_VAR_PTR(); OBJ_RELEASE(&iter->std); + if (OP1_TYPE == IS_VAR) { + FREE_OP1_VAR_PTR(); + } else { + FREE_OP1(); + } HANDLE_EXCEPTION(); } } @@ -4741,8 +4749,12 @@ ZEND_VM_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, ANY) is_empty = iter->funcs->valid(iter) != SUCCESS; if (UNEXPECTED(EG(exception) != NULL)) { - FREE_OP1_VAR_PTR(); OBJ_RELEASE(&iter->std); + if (OP1_TYPE == IS_VAR) { + FREE_OP1_VAR_PTR(); + } else { + FREE_OP1(); + } HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ @@ -4751,7 +4763,11 @@ ZEND_VM_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, ANY) Z_FE_POS_P(EX_VAR(opline->result.var)) = INVALID_IDX; ZVAL_PTR(EX_VAR((opline+2)->op1.var), NULL); - FREE_OP1_VAR_PTR(); + if (OP1_TYPE == IS_VAR) { + FREE_OP1_VAR_PTR(); + } else { + FREE_OP1(); + } if (is_empty) { ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } else { @@ -4793,7 +4809,11 @@ ZEND_VM_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, ANY) } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); - FREE_OP1_VAR_PTR(); + if (OP1_TYPE == IS_VAR) { + FREE_OP1_VAR_PTR(); + } else { + FREE_OP1(); + } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } @@ -5130,9 +5150,6 @@ ZEND_VM_HANDLER(126, ZEND_FE_FETCH_RW, VAR, ANY) /* failure in get_current_data */ ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } - ZVAL_MAKE_REF(value); - Z_ADDREF_P(value); - ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value)); if (opline->extended_value) { if (iter->funcs->get_current_key) { iter->funcs->get_current_key(iter, EX_VAR((opline+1)->result.var)); @@ -5144,6 +5161,9 @@ ZEND_VM_HANDLER(126, ZEND_FE_FETCH_RW, VAR, ANY) ZVAL_LONG(EX_VAR((opline+1)->result.var), iter->index); } } + ZVAL_MAKE_REF(value); + Z_ADDREF_P(value); + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value)); ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 3eead75c73..3d0dd2e97d 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3068,8 +3068,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); } } @@ -3077,8 +3077,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER is_empty = iter->funcs->valid(iter) != SUCCESS; if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ @@ -3092,13 +3092,13 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER ZEND_VM_NEXT_OPCODE(); } } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - if (IS_CONST != IS_TMP_VAR) { - if (Z_REFCOUNTED_P(array_ptr)) { - Z_ADDREF_P(array_ptr); - } + zval *result = EX_VAR(opline->result.var); + + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_CONST != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(array_ptr); } - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ptr); - Z_FE_POS_P(EX_VAR(opline->result.var)) = 0; + Z_FE_POS_P(result) = 0; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -3137,7 +3137,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE zend_bool is_empty; if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + if (IS_CONST == IS_VAR) { + } else { + + } if (!EG(exception)) { zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } @@ -3149,8 +3153,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + if (IS_CONST == IS_VAR) { + + } else { + + } HANDLE_EXCEPTION(); } } @@ -3158,8 +3166,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE is_empty = iter->funcs->valid(iter) != SUCCESS; if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + if (IS_CONST == IS_VAR) { + + } else { + + } HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ @@ -3168,6 +3180,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE Z_FE_POS_P(EX_VAR(opline->result.var)) = INVALID_IDX; ZVAL_PTR(EX_VAR((opline+2)->op1.var), NULL); + if (IS_CONST == IS_VAR) { + + } else { + + } if (is_empty) { ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } else { @@ -3208,7 +3225,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); + if (IS_CONST == IS_VAR) { + + } else { + } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } @@ -8957,7 +8978,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A zend_bool is_empty; if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - + zval_ptr_dtor_nogc(free_op1); if (!EG(exception)) { zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } @@ -8969,8 +8990,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + zval_ptr_dtor_nogc(free_op1); HANDLE_EXCEPTION(); } } @@ -8978,14 +8999,15 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A is_empty = iter->funcs->valid(iter) != SUCCESS; if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + zval_ptr_dtor_nogc(free_op1); HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); + zval_ptr_dtor_nogc(free_op1); if (is_empty) { ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } else { @@ -8993,13 +9015,13 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A ZEND_VM_NEXT_OPCODE(); } } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - if (IS_TMP_VAR != IS_TMP_VAR) { - if (Z_REFCOUNTED_P(array_ptr)) { - Z_ADDREF_P(array_ptr); - } + zval *result = EX_VAR(opline->result.var); + + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_TMP_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(array_ptr); } - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ptr); - Z_FE_POS_P(EX_VAR(opline->result.var)) = 0; + Z_FE_POS_P(result) = 0; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -9038,7 +9060,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ zend_bool is_empty; if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + if (IS_TMP_VAR == IS_VAR) { + } else { + zval_ptr_dtor_nogc(free_op1); + } if (!EG(exception)) { zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } @@ -9050,8 +9076,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + if (IS_TMP_VAR == IS_VAR) { + + } else { + zval_ptr_dtor_nogc(free_op1); + } HANDLE_EXCEPTION(); } } @@ -9059,8 +9089,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ is_empty = iter->funcs->valid(iter) != SUCCESS; if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + if (IS_TMP_VAR == IS_VAR) { + + } else { + zval_ptr_dtor_nogc(free_op1); + } HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ @@ -9069,6 +9103,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ Z_FE_POS_P(EX_VAR(opline->result.var)) = INVALID_IDX; ZVAL_PTR(EX_VAR((opline+2)->op1.var), NULL); + if (IS_TMP_VAR == IS_VAR) { + + } else { + zval_ptr_dtor_nogc(free_op1); + } if (is_empty) { ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } else { @@ -9109,7 +9148,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); + if (IS_TMP_VAR == IS_VAR) { + } else { + zval_ptr_dtor_nogc(free_op1); + } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } @@ -11771,8 +11814,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op1); OBJ_RELEASE(&iter->std); + zval_ptr_dtor_nogc(free_op1); HANDLE_EXCEPTION(); } } @@ -11780,8 +11823,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A is_empty = iter->funcs->valid(iter) != SUCCESS; if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op1); OBJ_RELEASE(&iter->std); + zval_ptr_dtor_nogc(free_op1); HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ @@ -11796,13 +11839,13 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A ZEND_VM_NEXT_OPCODE(); } } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - if (IS_VAR != IS_TMP_VAR) { - if (Z_REFCOUNTED_P(array_ptr)) { - Z_ADDREF_P(array_ptr); - } + zval *result = EX_VAR(opline->result.var); + + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(array_ptr); } - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ptr); - Z_FE_POS_P(EX_VAR(opline->result.var)) = 0; + Z_FE_POS_P(result) = 0; zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); @@ -11842,7 +11885,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ zend_bool is_empty; if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + if (IS_VAR == IS_VAR) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } else { + zval_ptr_dtor_nogc(free_op1); + } if (!EG(exception)) { zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } @@ -11854,8 +11901,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; OBJ_RELEASE(&iter->std); + if (IS_VAR == IS_VAR) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } else { + zval_ptr_dtor_nogc(free_op1); + } HANDLE_EXCEPTION(); } } @@ -11863,8 +11914,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ is_empty = iter->funcs->valid(iter) != SUCCESS; if (UNEXPECTED(EG(exception) != NULL)) { - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; OBJ_RELEASE(&iter->std); + if (IS_VAR == IS_VAR) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } else { + zval_ptr_dtor_nogc(free_op1); + } HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ @@ -11873,7 +11928,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ Z_FE_POS_P(EX_VAR(opline->result.var)) = INVALID_IDX; ZVAL_PTR(EX_VAR((opline+2)->op1.var), NULL); - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + if (IS_VAR == IS_VAR) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } else { + zval_ptr_dtor_nogc(free_op1); + } if (is_empty) { ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } else { @@ -11915,7 +11974,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); - if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + if (IS_VAR == IS_VAR) { + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + } else { + zval_ptr_dtor_nogc(free_op1); + } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } @@ -12252,9 +12315,6 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ /* failure in get_current_data */ ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } - ZVAL_MAKE_REF(value); - Z_ADDREF_P(value); - ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value)); if (opline->extended_value) { if (iter->funcs->get_current_key) { iter->funcs->get_current_key(iter, EX_VAR((opline+1)->result.var)); @@ -12266,6 +12326,9 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ ZVAL_LONG(EX_VAR((opline+1)->result.var), iter->index); } } + ZVAL_MAKE_REF(value); + Z_ADDREF_P(value); + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value)); ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } @@ -24151,8 +24214,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_AR if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); } } @@ -24160,8 +24223,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_AR is_empty = iter->funcs->valid(iter) != SUCCESS; if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ @@ -24175,13 +24238,13 @@ static int ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_AR ZEND_VM_NEXT_OPCODE(); } } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - if (IS_CV != IS_TMP_VAR) { - if (Z_REFCOUNTED_P(array_ptr)) { - Z_ADDREF_P(array_ptr); - } + zval *result = EX_VAR(opline->result.var); + + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_CV != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(array_ptr); } - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ptr); - Z_FE_POS_P(EX_VAR(opline->result.var)) = 0; + Z_FE_POS_P(result) = 0; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -24220,7 +24283,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A zend_bool is_empty; if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + if (IS_CV == IS_VAR) { + + } else { + } if (!EG(exception)) { zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val); } @@ -24232,8 +24299,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A if (iter->funcs->rewind) { iter->funcs->rewind(iter); if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + if (IS_CV == IS_VAR) { + + } else { + + } HANDLE_EXCEPTION(); } } @@ -24241,8 +24312,12 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A is_empty = iter->funcs->valid(iter) != SUCCESS; if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + if (IS_CV == IS_VAR) { + + } else { + + } HANDLE_EXCEPTION(); } iter->index = -1; /* will be set to 0 before using next handler */ @@ -24251,6 +24326,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A Z_FE_POS_P(EX_VAR(opline->result.var)) = INVALID_IDX; ZVAL_PTR(EX_VAR((opline+2)->op1.var), NULL); + if (IS_CV == IS_VAR) { + + } else { + + } if (is_empty) { ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } else { @@ -24291,7 +24371,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); ZVAL_UNDEF(EX_VAR(opline->result.var)); + if (IS_CV == IS_VAR) { + + } else { + } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } -- 2.40.0