cvs: ZendEngine2 / zend_compile.c zend_compile.h zend_execute.c zend_vm_def.h zend_vm_execute.h /tests bug44913.phpt

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

  Added files:                 
    /ZendEngine2/tests	bug44913.phpt 

  Modified files:              
    /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-20080505110246.txt (text/plain, 11.6 KB)
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_compile.c?r1=1.821&r2=1.822&diff_format=u
Index: ZendEngine2/zend_compile.c
diff -u ZendEngine2/zend_compile.c:1.821 ZendEngine2/zend_compile.c:1.822
--- ZendEngine2/zend_compile.c:1.821	Mon May  5 09:44:07 2008
+++ ZendEngine2/zend_compile.c	Mon May  5 11:02:45 2008
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_compile.c,v 1.821 2008/05/05 09:44:07 dmitry Exp $ */
+/* $Id: zend_compile.c,v 1.822 2008/05/05 11:02:45 dmitry Exp $ */
 
 #include <zend_language_parser.h>
 #include "zend.h"
@@ -2129,7 +2129,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;
@@ -2148,7 +2148,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;
@@ -2156,7 +2156,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;
@@ -2169,6 +2169,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)) {
@@ -2178,6 +2179,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);
@@ -2186,6 +2189,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;
@@ -3225,7 +3234,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.378&r2=1.379&diff_format=u
Index: ZendEngine2/zend_compile.h
diff -u ZendEngine2/zend_compile.h:1.378 ZendEngine2/zend_compile.h:1.379
--- ZendEngine2/zend_compile.h:1.378	Wed Mar 26 14:23:01 2008
+++ ZendEngine2/zend_compile.h	Mon May  5 11:02:45 2008
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_compile.h,v 1.378 2008/03/26 14:23:01 scottmac Exp $ */
+/* $Id: zend_compile.h,v 1.379 2008/05/05 11:02:45 dmitry Exp $ */
 
 #ifndef ZEND_COMPILE_H
 #define ZEND_COMPILE_H
@@ -324,7 +324,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.794&r2=1.795&diff_format=u
Index: ZendEngine2/zend_execute.c
diff -u ZendEngine2/zend_execute.c:1.794 ZendEngine2/zend_execute.c:1.795
--- ZendEngine2/zend_execute.c:1.794	Tue Apr 29 08:15:48 2008
+++ ZendEngine2/zend_execute.c	Mon May  5 11:02:45 2008
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_execute.c,v 1.794 2008/04/29 08:15:48 dmitry Exp $ */
+/* $Id: zend_execute.c,v 1.795 2008/05/05 11:02:45 dmitry Exp $ */
 
 #define ZEND_INTENSIVE_DEBUGGING 0
 
@@ -412,22 +412,18 @@
 }
 /* }}} */
 
-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);
 	}
 }
 /* }}} */
@@ -1347,10 +1343,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.227&r2=1.228&diff_format=u
Index: ZendEngine2/zend_vm_def.h
diff -u ZendEngine2/zend_vm_def.h:1.227 ZendEngine2/zend_vm_def.h:1.228
--- ZendEngine2/zend_vm_def.h:1.227	Wed Apr 30 10:44:24 2008
+++ ZendEngine2/zend_vm_def.h	Mon May  5 11:02:45 2008
@@ -18,7 +18,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_vm_def.h,v 1.227 2008/04/30 10:44:24 dmitry Exp $ */
+/* $Id: zend_vm_def.h,v 1.228 2008/05/05 11:02:45 dmitry Exp $ */
 
 /* If you change this file, please regenerate the zend_vm_execute.h and
  * zend_vm_opcodes.h files by running:
@@ -2702,10 +2702,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);
@@ -2743,11 +2747,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();
 }
 
@@ -4287,10 +4291,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.231&r2=1.232&diff_format=u
Index: ZendEngine2/zend_vm_execute.h
diff -u ZendEngine2/zend_vm_execute.h:1.231 ZendEngine2/zend_vm_execute.h:1.232
--- ZendEngine2/zend_vm_execute.h:1.231	Wed Apr 30 10:44:24 2008
+++ ZendEngine2/zend_vm_execute.h	Mon May  5 11:02:45 2008
@@ -523,10 +523,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;
 				}
 			}
@@ -733,10 +737,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);
@@ -4868,14 +4876,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);
@@ -8266,7 +8266,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();
 }
 
@@ -31948,11 +31948,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.