com php-src: Fixed operand destruction in case of exceptions in iterator: Zend/tests/foreach_003.phpt Zend/tests/foreach_ 004.phpt Zend/zend_vm_def.h Zend/zend_vm_ execute.h

[email protected] (Rasmus Lerdorf)
Newsgroups php.cvs
Message-ID <[email protected]>
Commit:    92e90c09f085c22707ff4a59201f016f56e0ef8b
Author:    Dmitry Stogov <[email protected]>         Wed, 28 Jan 2015 12:44:57 +0300
Parents:   dd2a36a2074bbb0cb31de00b66dcf2812d6d753f
Branches:  dstogov-foreach

Link:       http://git.php.net/?p=php-src.git;a=commitdiff;h=92e90c09f085c22707ff4a59201f016f56e0ef8b

Log:
Fixed operand destruction in case of exceptions in iterator

Changed paths:
  A  Zend/tests/foreach_003.phpt
  A  Zend/tests/foreach_004.phpt
  M  Zend/zend_vm_def.h
  M  Zend/zend_vm_execute.h
diff_92e90c09f085c22707ff4a59201f016f56e0ef8b.txt (text/plain, 21.9 KB)
diff --git a/Zend/tests/foreach_003.phpt b/Zend/tests/foreach_003.phpt
new file mode 100644
index 0000000..71b0f2a
--- /dev/null
+++ b/Zend/tests/foreach_003.phpt
@@ -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
index 0000000..1f754a7
--- /dev/null
+++ b/Zend/tests/foreach_004.phpt
@@ -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
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index b04324c..52a24d0 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 3eead75..3d0dd2e 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));
 	}
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.