]> granicus.if.org Git - php/commitdiff
Fixed invalid live-range detection
authorDmitry Stogov <dmitry@zend.com>
Thu, 9 Jul 2015 14:38:29 +0000 (17:38 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 9 Jul 2015 14:38:29 +0000 (17:38 +0300)
Zend/tests/temporary_cleaning_007.phpt [new file with mode: 0644]
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_opcode.c

diff --git a/Zend/tests/temporary_cleaning_007.phpt b/Zend/tests/temporary_cleaning_007.phpt
new file mode 100644 (file)
index 0000000..0e29ed6
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+Exception inside a foreach loop with return
+--FILE--
+<?php
+class saboteurTestController {
+    public function isConsistent() { throw new \Exception(); }
+}
+
+$controllers = array(new saboteurTestController(),new saboteurTestController());
+foreach ($controllers as $controller) {        
+    try {
+        if ($controller->isConsistent()) {
+            return $controller;
+        }
+    } catch (\Exception $e) {
+        echo "Exception\n";
+    }
+}
+?>
+--EXPECT--
+Exception
+Exception
index 9e50dec7efdc95de4216eaf1d554994520199cdb..9cdb5ffd03cc1f8b10819a7c9abaae2db6a753a8 100644 (file)
@@ -872,7 +872,7 @@ static void str_dtor(zval *zv)  /* {{{ */ {
 
 static zend_bool zend_is_call(zend_ast *ast);
 
-static void generate_free_loop_var(znode *var) /* {{{ */
+static void generate_free_loop_var_ex(znode *var, uint32_t flags) /* {{{ */
 {
        if (var->op_type != IS_UNUSED) {
                zend_op *opline = get_next_op(CG(active_op_array));
@@ -880,10 +880,16 @@ static void generate_free_loop_var(znode *var) /* {{{ */
                opline->opcode = var->flag ? ZEND_FE_FREE : ZEND_FREE;
                SET_NODE(opline->op1, var);
                SET_UNUSED(opline->op2);
+               opline->extended_value = flags;
        }
 }
 /* }}} */
 
+static void generate_free_loop_var(znode *var) /* {{{ */
+{
+       generate_free_loop_var_ex(var, 0);
+}
+
 static uint32_t zend_add_try_element(uint32_t try_op) /* {{{ */
 {
        zend_op_array *op_array = CG(active_op_array);
@@ -3442,12 +3448,12 @@ void zend_compile_unset(zend_ast *ast) /* {{{ */
 }
 /* }}} */
 
-static void zend_free_foreach_and_switch_variables(void) /* {{{ */
+static void zend_free_foreach_and_switch_variables(uint32_t flags) /* {{{ */
 {
        int array_offset = CG(context).current_brk_cont;
        while (array_offset != -1) {
                zend_brk_cont_element *brk_cont = &CG(context).brk_cont_array[array_offset];
-               generate_free_loop_var(&brk_cont->loop_var);
+               generate_free_loop_var_ex(&brk_cont->loop_var, flags);
                array_offset = brk_cont->parent;
        }
 }
@@ -3471,7 +3477,12 @@ void zend_compile_return(zend_ast *ast) /* {{{ */
                zend_compile_expr(&expr_node, expr_ast);
        }
 
-       zend_free_foreach_and_switch_variables();
+       /* Generator return types are handled separately */
+       if (!(CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) && CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
+               zend_emit_return_type_check(expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1);
+       }
+
+       zend_free_foreach_and_switch_variables(ZEND_FREE_ON_RETURN);
 
        if (CG(context).in_finally) {
                opline = zend_emit_op(NULL, ZEND_DISCARD_EXCEPTION, NULL, NULL);
@@ -3479,10 +3490,6 @@ void zend_compile_return(zend_ast *ast) /* {{{ */
                opline->op1.var = CG(context).fast_call_var;
        }
 
-       /* Generator return types are handled separately */
-       if (!(CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) && CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
-               zend_emit_return_type_check(expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1);
-       }
        opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN,
                &expr_node, NULL);
 
index 3f9c0910615134026484996f5ae1f9e62a81df10..b07f70ea78cade7e3180b72aab8bd11dd8b2429b 100644 (file)
@@ -882,7 +882,9 @@ ZEND_API void zend_assert_valid_class_name(const zend_string *const_name);
 
 #define ZEND_FETCH_ARG_MASK         0x000fffff
 
-#define ZEND_MEMBER_FUNC_CALL  1<<0
+#define ZEND_FREE_ON_RETURN     (1<<0)
+
+#define ZEND_MEMBER_FUNC_CALL  (1<<0)
 
 #define ZEND_ARG_SEND_BY_REF (1<<0)
 #define ZEND_ARG_COMPILE_TIME_BOUND (1<<1)
index ae2b4bf3531bedcbd266c27bfe89176dd86011a7..64ba6562ffaac7e3205408c5013648fc31226cfd 100644 (file)
@@ -991,7 +991,11 @@ static zend_always_inline uint32_t *generate_var_liveliness_info_ex(zend_op_arra
                                && opline->opcode != ZEND_FETCH_LIST
                                && opline->opcode != ZEND_CASE
                                && opline->opcode != ZEND_FE_FETCH_R
-                               && opline->opcode != ZEND_FE_FETCH_RW) {
+                               && opline->opcode != ZEND_FE_FETCH_RW
+                               /* the following opcodes are not the "final" */
+                               && (opline->opcode != ZEND_FREE || !(opline->extended_value & ZEND_FREE_ON_RETURN))
+                               && (opline->opcode != ZEND_FE_FREE || !(opline->extended_value & ZEND_FREE_ON_RETURN))
+                       ) {
                                op_live_total += liveliness_kill_var(op_array, opline, var, Tstart, opTs);
                        }
                }
@@ -1007,7 +1011,7 @@ static zend_always_inline uint32_t *generate_var_liveliness_info_ex(zend_op_arra
                }
        } while (++opline != end);
 
-#if ZEND_DEBUG
+#if 0
        /* Check that all TMP variable live-ranges are closed */
        for (i = 0; i < op_array->T; i++) {
                ZEND_ASSERT(Tstart[i] == (uint32_t)-1);