]> granicus.if.org Git - php/commitdiff
Fixed operand destruction in case of exceptions in iterator
authorDmitry Stogov <dmitry@zend.com>
Wed, 28 Jan 2015 09:44:57 +0000 (12:44 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 28 Jan 2015 09:44:57 +0000 (12:44 +0300)
Zend/tests/foreach_003.phpt [new file with mode: 0644]
Zend/tests/foreach_004.phpt [new file with mode: 0644]
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/Zend/tests/foreach_003.phpt b/Zend/tests/foreach_003.phpt
new file mode 100644 (file)
index 0000000..71b0f2a
--- /dev/null
@@ -0,0 +1,71 @@
+--TEST--
+Iterator exceptions in foreach by value
+--FILE--
+<?php
+class IT implements Iterator {
+    private $n = 0;
+    private $count = 0;
+    private $trap = null;
+
+    function __construct($count, $trap = null) {
+       $this->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 (file)
index 0000000..1f754a7
--- /dev/null
@@ -0,0 +1,65 @@
+--TEST--
+Iterator exceptions in foreach by reference
+--FILE--
+<?php
+class IT extends ArrayIterator {
+    private $n = 0;
+
+    function __construct($trap = null) {
+       parent::__construct([0, 1]);
+       $this->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
index b04324c4ed3cebfe815e6f42e4b81ff0c6952036..52a24d0859d75996a62e64892c7f1c9f4839b156 100644 (file)
@@ -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();
                }
index 3eead75c730baf380b591e216477d92a1066338e..3d0dd2e97d0b71944e68c508b1248d671931bd90 100644 (file)
@@ -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));
        }
 }