com php-src: Fixed foreach by reference iteration over constant array: Zend/tests/foreach_006.phpt Zend/zend_vm_def. h Zend/zend_vm_execute.h

[email protected] (Rasmus Lerdorf)
Newsgroups php.cvs
Message-ID <[email protected]>
Commit:    eef80c583762d1e98d177cdbb27e3a8a6b0c4539
Author:    Dmitry Stogov <[email protected]>         Wed, 28 Jan 2015 16:52:21 +0300
Parents:   61e739187391661e2d541947bec25d7dcc4479f3
Branches:  dstogov-foreach

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

Log:
Fixed foreach by reference iteration over constant array

Changed paths:
  A  Zend/tests/foreach_006.phpt
  M  Zend/zend_vm_def.h
  M  Zend/zend_vm_execute.h
diff_eef80c583762d1e98d177cdbb27e3a8a6b0c4539.txt (text/plain, 8 KB)
diff --git a/Zend/tests/foreach_006.phpt b/Zend/tests/foreach_006.phpt
new file mode 100644
index 0000000..65d6fdc
--- /dev/null
+++ b/Zend/tests/foreach_006.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Foreach by reference on constant
+--FILE--
+<?php
+for ($i = 0; $i < 3; $i++) {
+	foreach ([1,2,3] as &$val) {
+		echo "$val\n";
+	}
+}
+?>
+--EXPECT--
+1
+2
+3
+1
+2
+3
+1
+2
+3
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 52a24d0..5ddc903 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -4703,11 +4703,9 @@ ZEND_VM_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, ANY)
 	SAVE_OPLINE();
 
 	if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
-		array_ref = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R);
-		ZVAL_MAKE_REF(array_ref);
-		array_ptr = Z_REFVAL_P(array_ref);
-		if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
-			SEPARATE_ARRAY(array_ptr);
+		array_ref = array_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R);
+		if (Z_ISREF_P(array_ref)) {
+			array_ptr = Z_REFVAL_P(array_ref);
 		}
 	} else {
 		array_ref = array_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
@@ -4778,12 +4776,25 @@ ZEND_VM_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, ANY)
 		HashPosition pos = 0;
 		Bucket *p;
 
-		if (OP1_TYPE != IS_TMP_VAR) {
-			if (Z_REFCOUNTED_P(array_ref)) {
-				Z_ADDREF_P(array_ref);
+		if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
+			if (array_ptr == array_ref) {
+				ZVAL_NEW_REF(array_ref, array_ref);
+				array_ptr = Z_REFVAL_P(array_ref);
+			}
+			Z_ADDREF_P(array_ref);
+			ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
+		} else {
+			array_ptr = EX_VAR(opline->result.var);
+			ZVAL_COPY_VALUE(array_ptr, array_ref);
+		}
+		if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
+			if (OP1_TYPE == IS_CONST) {
+				zval_copy_ctor_func(array_ptr);
+			} else {
+				SEPARATE_ARRAY(array_ptr);
 			}
+			fe_ht = Z_ARRVAL_P(array_ptr);
 		}
-		ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);	
 		while (1) {
 			if (pos >= fe_ht->nNumUsed) {
 				FREE_OP1_VAR_PTR();
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 3d0dd2e..362f450 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -3120,11 +3120,9 @@ static int ZEND_FASTCALL  ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE
 	SAVE_OPLINE();
 
 	if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
-		array_ref = NULL;
-		ZVAL_MAKE_REF(array_ref);
-		array_ptr = Z_REFVAL_P(array_ref);
-		if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
-			SEPARATE_ARRAY(array_ptr);
+		array_ref = array_ptr = NULL;
+		if (Z_ISREF_P(array_ref)) {
+			array_ptr = Z_REFVAL_P(array_ref);
 		}
 	} else {
 		array_ref = array_ptr = EX_CONSTANT(opline->op1);
@@ -3195,12 +3193,25 @@ static int ZEND_FASTCALL  ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE
 		HashPosition pos = 0;
 		Bucket *p;
 
-		if (IS_CONST != IS_TMP_VAR) {
-			if (Z_REFCOUNTED_P(array_ref)) {
-				Z_ADDREF_P(array_ref);
+		if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
+			if (array_ptr == array_ref) {
+				ZVAL_NEW_REF(array_ref, array_ref);
+				array_ptr = Z_REFVAL_P(array_ref);
+			}
+			Z_ADDREF_P(array_ref);
+			ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
+		} else {
+			array_ptr = EX_VAR(opline->result.var);
+			ZVAL_COPY_VALUE(array_ptr, array_ref);
+		}
+		if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
+			if (IS_CONST == IS_CONST) {
+				zval_copy_ctor_func(array_ptr);
+			} else {
+				SEPARATE_ARRAY(array_ptr);
 			}
+			fe_ht = Z_ARRVAL_P(array_ptr);
 		}
-		ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
 		while (1) {
 			if (pos >= fe_ht->nNumUsed) {
 
@@ -9043,11 +9054,9 @@ static int ZEND_FASTCALL  ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_
 	SAVE_OPLINE();
 
 	if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
-		array_ref = NULL;
-		ZVAL_MAKE_REF(array_ref);
-		array_ptr = Z_REFVAL_P(array_ref);
-		if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
-			SEPARATE_ARRAY(array_ptr);
+		array_ref = array_ptr = NULL;
+		if (Z_ISREF_P(array_ref)) {
+			array_ptr = Z_REFVAL_P(array_ref);
 		}
 	} else {
 		array_ref = array_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
@@ -9118,12 +9127,25 @@ static int ZEND_FASTCALL  ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_
 		HashPosition pos = 0;
 		Bucket *p;
 
-		if (IS_TMP_VAR != IS_TMP_VAR) {
-			if (Z_REFCOUNTED_P(array_ref)) {
-				Z_ADDREF_P(array_ref);
+		if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
+			if (array_ptr == array_ref) {
+				ZVAL_NEW_REF(array_ref, array_ref);
+				array_ptr = Z_REFVAL_P(array_ref);
 			}
+			Z_ADDREF_P(array_ref);
+			ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
+		} else {
+			array_ptr = EX_VAR(opline->result.var);
+			ZVAL_COPY_VALUE(array_ptr, array_ref);
+		}
+		if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
+			if (IS_TMP_VAR == IS_CONST) {
+				zval_copy_ctor_func(array_ptr);
+			} else {
+				SEPARATE_ARRAY(array_ptr);
+			}
+			fe_ht = Z_ARRVAL_P(array_ptr);
 		}
-		ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
 		while (1) {
 			if (pos >= fe_ht->nNumUsed) {
 
@@ -11868,11 +11890,9 @@ static int ZEND_FASTCALL  ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_
 	SAVE_OPLINE();
 
 	if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
-		array_ref = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
-		ZVAL_MAKE_REF(array_ref);
-		array_ptr = Z_REFVAL_P(array_ref);
-		if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
-			SEPARATE_ARRAY(array_ptr);
+		array_ref = array_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
+		if (Z_ISREF_P(array_ref)) {
+			array_ptr = Z_REFVAL_P(array_ref);
 		}
 	} else {
 		array_ref = array_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
@@ -11943,12 +11963,25 @@ static int ZEND_FASTCALL  ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_
 		HashPosition pos = 0;
 		Bucket *p;
 
-		if (IS_VAR != IS_TMP_VAR) {
-			if (Z_REFCOUNTED_P(array_ref)) {
-				Z_ADDREF_P(array_ref);
+		if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
+			if (array_ptr == array_ref) {
+				ZVAL_NEW_REF(array_ref, array_ref);
+				array_ptr = Z_REFVAL_P(array_ref);
 			}
+			Z_ADDREF_P(array_ref);
+			ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
+		} else {
+			array_ptr = EX_VAR(opline->result.var);
+			ZVAL_COPY_VALUE(array_ptr, array_ref);
+		}
+		if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
+			if (IS_VAR == IS_CONST) {
+				zval_copy_ctor_func(array_ptr);
+			} else {
+				SEPARATE_ARRAY(array_ptr);
+			}
+			fe_ht = Z_ARRVAL_P(array_ptr);
 		}
-		ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
 		while (1) {
 			if (pos >= fe_ht->nNumUsed) {
 				if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
@@ -24266,11 +24299,9 @@ static int ZEND_FASTCALL  ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A
 	SAVE_OPLINE();
 
 	if (IS_CV == IS_VAR || IS_CV == IS_CV) {
-		array_ref = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
-		ZVAL_MAKE_REF(array_ref);
-		array_ptr = Z_REFVAL_P(array_ref);
-		if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
-			SEPARATE_ARRAY(array_ptr);
+		array_ref = array_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+		if (Z_ISREF_P(array_ref)) {
+			array_ptr = Z_REFVAL_P(array_ref);
 		}
 	} else {
 		array_ref = array_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
@@ -24341,12 +24372,25 @@ static int ZEND_FASTCALL  ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A
 		HashPosition pos = 0;
 		Bucket *p;
 
-		if (IS_CV != IS_TMP_VAR) {
-			if (Z_REFCOUNTED_P(array_ref)) {
-				Z_ADDREF_P(array_ref);
+		if (IS_CV == IS_VAR || IS_CV == IS_CV) {
+			if (array_ptr == array_ref) {
+				ZVAL_NEW_REF(array_ref, array_ref);
+				array_ptr = Z_REFVAL_P(array_ref);
+			}
+			Z_ADDREF_P(array_ref);
+			ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
+		} else {
+			array_ptr = EX_VAR(opline->result.var);
+			ZVAL_COPY_VALUE(array_ptr, array_ref);
+		}
+		if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
+			if (IS_CV == IS_CONST) {
+				zval_copy_ctor_func(array_ptr);
+			} else {
+				SEPARATE_ARRAY(array_ptr);
 			}
+			fe_ht = Z_ARRVAL_P(array_ptr);
 		}
-		ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
 		while (1) {
 			if (pos >= fe_ht->nNumUsed) {
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.