cvs: ZendEngine2(PHP_5_3) / zend_compile.c zend_compile.h zend_execute.c zend_vm_def.h zend_vm_execute.h /tests bug44913.phpt php-src NEWS

[email protected] ("Dmitry Stogov")
Newsgroups php.zend-engine.cvs
Message-ID <cvsdmitry1209985418@cvsserver>
dmitry		Mon May  5 11:03:38 2008 UTC

  Added files:                 (Branch: PHP_5_3)
    /ZendEngine2/tests	bug44913.phpt 

  Modified files:              
    /php-src	NEWS 
    /ZendEngine2	zend_compile.c zend_compile.h zend_execute.c 
                	zend_vm_def.h zend_vm_execute.h 
  Log:
  - Use ZEND_FREE() opcode instead of ZEND_SWITCH_FREE(IS_TMP_VAR)
  - Fixed bug #44913 (Segfault when using return in combination with nested loops
  and continue 2)
dmitry-20080505110338.txt (text/plain, 12.7 KB)
http://cvs.php.net/viewvc.cgi/php-src/NEWS?r1=1.2027.2.547.2.965.2.174&r2=1.2027.2.547.2.965.2.175&diff_format=u
Index: php-src/NEWS
diff -u php-src/NEWS:1.2027.2.547.2.965.2.174 php-src/NEWS:1.2027.2.547.2.965.2.175
--- php-src/NEWS:1.2027.2.547.2.965.2.174	Mon May  5 07:29:41 2008
+++ php-src/NEWS	Mon May  5 11:03:32 2008
@@ -109,6 +109,7 @@
 - Added Windows support for asinh(), acosh(), atanh(), log1p() and expm1() (Kalle)
 
 - Improved PHP runtime speed and memory usage:
+  . Use ZEND_FREE() opcode instead of ZEND_SWITCH_FREE(IS_TMP_VAR). (Dmitry)
   . Lazy EG(active_symbol_table) initialization. (Dmitry)
   . Optimized ZEND_RETURN opcode to not allocate and copy return value if it is
     not used. (Dmitry)
@@ -169,6 +170,8 @@
 - Fixed an issue in date() where a : was printed for the O modifier after a P
   modifier was used. (Derick)
 
+- Fixed bug #44913 (Segfault when using return in combination with nested loops
+  and continue 2). (Dmitry)
 - Fixed bug #44899 (__isset usage changes behavior of empty()) (Etienne)
 - Fixed bug #44805 (rename() function is not portable to Windows). (Pierre)
 - Fixed bug #44742 (timezone_offset_get() causes segmentation faults). (Derick)
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_compile.c?r1=1.647.2.27.2.41.2.61&r2=1.647.2.27.2.41.2.62&diff_format=u
Index: ZendEngine2/zend_compile.c
diff -u ZendEngine2/zend_compile.c:1.647.2.27.2.41.2.61 ZendEngine2/zend_compile.c:1.647.2.27.2.41.2.62
--- ZendEngine2/zend_compile.c:1.647.2.27.2.41.2.61	Mon May  5 09:44:39 2008
+++ ZendEngine2/zend_compile.c	Mon May  5 11:03:32 2008
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_compile.c,v 1.647.2.27.2.41.2.61 2008/05/05 09:44:39 dmitry Exp $ */
+/* $Id: zend_compile.c,v 1.647.2.27.2.41.2.62 2008/05/05 11:03:32 dmitry Exp $ */
 
 #include <zend_language_parser.h>
 #include "zend.h"
@@ -2024,7 +2024,7 @@
 
 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
-	opline->opcode = ZEND_SWITCH_FREE;
+	opline->opcode = (switch_entry->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
 	opline->op1 = switch_entry->cond;
 	SET_UNUSED(opline->op2);
 	opline->extended_value = 0;
@@ -2042,7 +2042,7 @@
 
 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
-	opline->opcode = ZEND_SWITCH_FREE;
+	opline->opcode = (foreach_copy->result.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
 	opline->op1 = foreach_copy->result;
 	SET_UNUSED(opline->op2);
 	opline->extended_value = 1;
@@ -2050,7 +2050,7 @@
 	if (foreach_copy->op1.op_type != IS_UNUSED) {
 		opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
-		opline->opcode = ZEND_SWITCH_FREE;
+		opline->opcode = (foreach_copy->op1.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
 		opline->op1 = foreach_copy->op1;
 		SET_UNUSED(opline->op2);
 		opline->extended_value = 0;
@@ -2062,6 +2062,7 @@
 void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC)
 {
 	zend_op *opline;
+	int start_op_number, end_op_number;
 
 	if (do_end_vparse) {
 		if (CG(active_op_array)->return_reference && !zend_is_function_or_method_call(expr)) {
@@ -2071,6 +2072,8 @@
 		}
 	}
 
+	start_op_number = get_next_op_number(CG(active_op_array));
+
 #ifdef ZTS
 	zend_stack_apply_with_argument(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_switch_expr TSRMLS_CC);
 	zend_stack_apply_with_argument(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_foreach_copy TSRMLS_CC);
@@ -2079,6 +2082,12 @@
 	zend_stack_apply(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_foreach_copy);
 #endif
 
+	end_op_number = get_next_op_number(CG(active_op_array));
+	while (start_op_number < end_op_number) {
+		CG(active_op_array)->opcodes[start_op_number].op1.u.EA.type = EXT_TYPE_FREE_ON_RETURN;
+		start_op_number++;
+	}
+
 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
 	opline->opcode = ZEND_RETURN;
@@ -3075,7 +3084,7 @@
 	if (switch_entry_ptr->cond.op_type==IS_VAR || switch_entry_ptr->cond.op_type==IS_TMP_VAR) {
 		/* emit free for the switch condition*/
 		opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-		opline->opcode = ZEND_SWITCH_FREE;
+		opline->opcode = (switch_entry_ptr->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
 		opline->op1 = switch_entry_ptr->cond;
 		SET_UNUSED(opline->op2);
 	}
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_compile.h?r1=1.316.2.8.2.12.2.21&r2=1.316.2.8.2.12.2.22&diff_format=u
Index: ZendEngine2/zend_compile.h
diff -u ZendEngine2/zend_compile.h:1.316.2.8.2.12.2.21 ZendEngine2/zend_compile.h:1.316.2.8.2.12.2.22
--- ZendEngine2/zend_compile.h:1.316.2.8.2.12.2.21	Sat Mar 29 11:52:10 2008
+++ ZendEngine2/zend_compile.h	Mon May  5 11:03:32 2008
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_compile.h,v 1.316.2.8.2.12.2.21 2008/03/29 11:52:10 felipe Exp $ */
+/* $Id: zend_compile.h,v 1.316.2.8.2.12.2.22 2008/05/05 11:03:32 dmitry Exp $ */
 
 #ifndef ZEND_COMPILE_H
 #define ZEND_COMPILE_H
@@ -323,7 +323,8 @@
 #define IS_UNUSED	(1<<3)	/* Unused variable */
 #define IS_CV		(1<<4)	/* Compiled variable */
 
-#define EXT_TYPE_UNUSED		(1<<0)
+#define EXT_TYPE_UNUSED				(1<<0)
+#define EXT_TYPE_FREE_ON_RETURN		(2<<0)
 
 #include "zend_globals.h"
 
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_execute.c?r1=1.716.2.12.2.24.2.26&r2=1.716.2.12.2.24.2.27&diff_format=u
Index: ZendEngine2/zend_execute.c
diff -u ZendEngine2/zend_execute.c:1.716.2.12.2.24.2.26 ZendEngine2/zend_execute.c:1.716.2.12.2.24.2.27
--- ZendEngine2/zend_execute.c:1.716.2.12.2.24.2.26	Tue Apr 29 08:15:16 2008
+++ ZendEngine2/zend_execute.c	Mon May  5 11:03:32 2008
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_execute.c,v 1.716.2.12.2.24.2.26 2008/04/29 08:15:16 dmitry Exp $ */
+/* $Id: zend_execute.c,v 1.716.2.12.2.24.2.27 2008/05/05 11:03:32 dmitry Exp $ */
 
 #define ZEND_INTENSIVE_DEBUGGING 0
 
@@ -377,22 +377,18 @@
 	return get_zval_ptr(op, Ts, should_free, type);
 }
 
-static inline void zend_switch_free(temp_variable *T, int type, int extended_value TSRMLS_DC)
+static inline void zend_switch_free(temp_variable *T, int extended_value TSRMLS_DC)
 {
-	if (type == IS_VAR) {
-		if (T->var.ptr) {
-			if (extended_value & ZEND_FE_RESET_VARIABLE) { /* foreach() free */
-				Z_DELREF_P(T->var.ptr);
-			}
-			zval_ptr_dtor(&T->var.ptr);
-		} else if (!T->var.ptr_ptr) {
-			/* perform the equivalent of equivalent of a
-			 * quick & silent get_zval_ptr, and FREE_OP
-			 */
-			PZVAL_UNLOCK_FREE(T->str_offset.str);
-		}
-	} else { /* IS_TMP_VAR */
-		zendi_zval_dtor(T->tmp_var);
+	if (T->var.ptr) {
+		if (extended_value & ZEND_FE_RESET_VARIABLE) { /* foreach() free */
+			Z_DELREF_P(T->var.ptr);
+		}
+		zval_ptr_dtor(&T->var.ptr);
+	} else if (!T->var.ptr_ptr) {
+		/* perform the equivalent of equivalent of a
+		 * quick & silent get_zval_ptr, and FREE_OP
+		 */
+		PZVAL_UNLOCK_FREE(T->str_offset.str);
 	}
 }
 
@@ -1241,10 +1237,14 @@
 
 			switch (brk_opline->opcode) {
 				case ZEND_SWITCH_FREE:
-					zend_switch_free(&T(brk_opline->op1.u.var), brk_opline->op1.op_type, brk_opline->extended_value TSRMLS_CC);
+					if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
+						zend_switch_free(&T(brk_opline->op1.u.var), brk_opline->extended_value TSRMLS_CC);
+					}
 					break;
 				case ZEND_FREE:
-					zendi_zval_dtor(T(brk_opline->op1.u.var).tmp_var);
+					if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
+						zendi_zval_dtor(T(brk_opline->op1.u.var).tmp_var);
+					}
 					break;
 			}
 		}
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_vm_def.h?r1=1.59.2.29.2.48.2.51&r2=1.59.2.29.2.48.2.52&diff_format=u
Index: ZendEngine2/zend_vm_def.h
diff -u ZendEngine2/zend_vm_def.h:1.59.2.29.2.48.2.51 ZendEngine2/zend_vm_def.h:1.59.2.29.2.48.2.52
--- ZendEngine2/zend_vm_def.h:1.59.2.29.2.48.2.51	Wed Apr 30 10:44:08 2008
+++ ZendEngine2/zend_vm_def.h	Mon May  5 11:03:32 2008
@@ -18,7 +18,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_vm_def.h,v 1.59.2.29.2.48.2.51 2008/04/30 10:44:08 dmitry Exp $ */
+/* $Id: zend_vm_def.h,v 1.59.2.29.2.48.2.52 2008/05/05 11:03:32 dmitry Exp $ */
 
 /* If you change this file, please regenerate the zend_vm_execute.h and
  * zend_vm_opcodes.h files by running:
@@ -2642,10 +2642,14 @@
 
 	switch (brk_opline->opcode) {
 		case ZEND_SWITCH_FREE:
-			zend_switch_free(&EX_T(brk_opline->op1.u.var), brk_opline->op1.op_type, brk_opline->extended_value TSRMLS_CC);
+			if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
+				zend_switch_free(&EX_T(brk_opline->op1.u.var), brk_opline->extended_value TSRMLS_CC);
+			}
 			break;
 		case ZEND_FREE:
-			zendi_zval_dtor(EX_T(brk_opline->op1.u.var).tmp_var);
+			if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
+				zendi_zval_dtor(EX_T(brk_opline->op1.u.var).tmp_var);
+			}
 			break;
 	}
 	ZEND_VM_JMP(opline->op1.u.jmp_addr);
@@ -2683,11 +2687,11 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
-ZEND_VM_HANDLER(49, ZEND_SWITCH_FREE, TMP|VAR, ANY)
+ZEND_VM_HANDLER(49, ZEND_SWITCH_FREE, VAR, ANY)
 {
 	zend_op *opline = EX(opline);
 
-	zend_switch_free(&EX_T(opline->op1.u.var), OP1_TYPE, opline->extended_value TSRMLS_CC);
+	zend_switch_free(&EX_T(opline->op1.u.var), opline->extended_value TSRMLS_CC);
 	ZEND_VM_NEXT_OPCODE();
 }
 
@@ -4123,10 +4127,14 @@
 
 				switch (brk_opline->opcode) {
 					case ZEND_SWITCH_FREE:
-						zend_switch_free(&EX_T(brk_opline->op1.u.var), brk_opline->op1.op_type, brk_opline->extended_value TSRMLS_CC);
+						if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
+							zend_switch_free(&EX_T(brk_opline->op1.u.var), brk_opline->extended_value TSRMLS_CC);
+						}
 						break;
 					case ZEND_FREE:
-						zendi_zval_dtor(EX_T(brk_opline->op1.u.var).tmp_var);
+						if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
+							zendi_zval_dtor(EX_T(brk_opline->op1.u.var).tmp_var);
+						}
 						break;
 				}
 			}
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_vm_execute.h?r1=1.62.2.30.2.49.2.50&r2=1.62.2.30.2.49.2.51&diff_format=u
Index: ZendEngine2/zend_vm_execute.h
diff -u ZendEngine2/zend_vm_execute.h:1.62.2.30.2.49.2.50 ZendEngine2/zend_vm_execute.h:1.62.2.30.2.49.2.51
--- ZendEngine2/zend_vm_execute.h:1.62.2.30.2.49.2.50	Wed Apr 30 10:44:08 2008
+++ ZendEngine2/zend_vm_execute.h	Mon May  5 11:03:33 2008
@@ -515,7 +515,7 @@
 
 				switch (brk_opline->opcode) {
 					case ZEND_SWITCH_FREE:
-						zend_switch_free(&EX_T(brk_opline->op1.u.var), brk_opline->op1.op_type, brk_opline->extended_value TSRMLS_CC);
+						zend_switch_free(&EX_T(brk_opline->op1.u.var), brk_opline->extended_value TSRMLS_CC);
 						break;
 					case ZEND_FREE:
 						zendi_zval_dtor(EX_T(brk_opline->op1.u.var).tmp_var);
@@ -724,7 +724,7 @@
 
 	switch (brk_opline->opcode) {
 		case ZEND_SWITCH_FREE:
-			zend_switch_free(&EX_T(brk_opline->op1.u.var), brk_opline->op1.op_type, brk_opline->extended_value TSRMLS_CC);
+			zend_switch_free(&EX_T(brk_opline->op1.u.var), brk_opline->extended_value TSRMLS_CC);
 			break;
 		case ZEND_FREE:
 			zendi_zval_dtor(EX_T(brk_opline->op1.u.var).tmp_var);
@@ -4735,14 +4735,6 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
-static int ZEND_SWITCH_FREE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
-	zend_op *opline = EX(opline);
-
-	zend_switch_free(&EX_T(opline->op1.u.var), IS_TMP_VAR, opline->extended_value TSRMLS_CC);
-	ZEND_VM_NEXT_OPCODE();
-}
-
 static int ZEND_CLONE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	zend_op *opline = EX(opline);
@@ -7990,7 +7982,7 @@
 {
 	zend_op *opline = EX(opline);
 
-	zend_switch_free(&EX_T(opline->op1.u.var), IS_VAR, opline->extended_value TSRMLS_CC);
+	zend_switch_free(&EX_T(opline->op1.u.var), opline->extended_value TSRMLS_CC);
 	ZEND_VM_NEXT_OPCODE();
 }
 
@@ -30747,11 +30739,11 @@
   	ZEND_NULL_HANDLER,
   	ZEND_NULL_HANDLER,
   	ZEND_NULL_HANDLER,
-  	ZEND_SWITCH_FREE_SPEC_TMP_HANDLER,
-  	ZEND_SWITCH_FREE_SPEC_TMP_HANDLER,
-  	ZEND_SWITCH_FREE_SPEC_TMP_HANDLER,
-  	ZEND_SWITCH_FREE_SPEC_TMP_HANDLER,
-  	ZEND_SWITCH_FREE_SPEC_TMP_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
   	ZEND_SWITCH_FREE_SPEC_VAR_HANDLER,
   	ZEND_SWITCH_FREE_SPEC_VAR_HANDLER,
   	ZEND_SWITCH_FREE_SPEC_VAR_HANDLER,

http://cvs.php.net/viewvc.cgi/ZendEngine2/tests/bug44913.phpt?view=markup&rev=1.1
Index: ZendEngine2/tests/bug44913.phpt
+++ ZendEngine2/tests/bug44913.phpt
--TEST--
Bug #44913 (Segfault when using return in combination with nested loops and continue 2)
--FILE--
<?php
function something() {
        foreach(array(1, 2) as $value) {
                for($i = 0; $i < 1; $i++) {
                        continue 2;
                }
                return;
        }
}
something();
echo "ok\n";
?>
--EXPECT--
ok
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.