]> granicus.if.org Git - php/commitdiff
Fixed bug #70012 (Exception lost with nested finally block)
authorXinchen Hui <laruence@php.net>
Wed, 8 Jul 2015 09:15:09 +0000 (17:15 +0800)
committerXinchen Hui <laruence@php.net>
Wed, 8 Jul 2015 09:15:09 +0000 (17:15 +0800)
NEWS
Zend/tests/bug70012.phpt [new file with mode: 0644]
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
ext/opcache/Optimizer/optimize_temp_vars_5.c

diff --git a/NEWS b/NEWS
index b5a4e4441274dff3502e0244d1b376f47a4fb174..53828b0e817e8597f0452150d359012c06529adc 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,9 @@
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 23 Jul 2015, PHP 7.0.0 Beta 2
 
+- Core:
+  . Fixed bug #70012 (Exception lost with nested finally block). (Laruence)
+
 09 Jul 2015, PHP 7.0.0 Beta 1
 
 - Core:
diff --git a/Zend/tests/bug70012.phpt b/Zend/tests/bug70012.phpt
new file mode 100644 (file)
index 0000000..5337649
--- /dev/null
@@ -0,0 +1,32 @@
+--TEST--
+Bug #70012 (Exception lost with nested finally block)
+--FILE--
+<?php
+try {
+       echo "Outer try\n";
+       try {
+               echo "  Middle try\n";
+               throw new Exception();
+       } finally {
+               echo "  Middle finally\n";
+               try {
+                       echo "    Inner try\n";
+               } finally {
+                       echo "    Inner finally\n";
+               }
+       }
+       echo "Outer shouldnt get here\n";
+} catch (Exception $e) {
+       echo "Outer catch\n";
+} finally {
+       echo "Outer finally\n";
+}
+?>
+--EXPECT--
+Outer try
+  Middle try
+  Middle finally
+    Inner try
+    Inner finally
+Outer catch
+Outer finally
index cff901164ef010bbf50cff83c2df315dd0d1727e..db746a647c1090e03d6e1654967470d052c33507 100644 (file)
@@ -7596,9 +7596,12 @@ ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY)
                ZEND_VM_CONTINUE();
        }
        /* set no delayed exception */
-       Z_OBJ_P(fast_call) = NULL;
-       /* set return address */
-       fast_call->u2.lineno = opline - EX(func)->op_array.opcodes;
+       if (UNEXPECTED(Z_OBJ_P(fast_call) != NULL)) {
+               fast_call->u2.lineno = (uint32_t)-1;
+       } else {
+               /* set return address */
+               fast_call->u2.lineno = opline - EX(func)->op_array.opcodes;
+       }
        ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op1));
        ZEND_VM_CONTINUE();
 }
index 720af1acd458ddf923eecd09f021e2e3ef6263a6..832692d1db2968f7cb4116565a309db997bace22 100644 (file)
@@ -1608,9 +1608,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OP
                ZEND_VM_CONTINUE();
        }
        /* set no delayed exception */
-       Z_OBJ_P(fast_call) = NULL;
-       /* set return address */
-       fast_call->u2.lineno = opline - EX(func)->op_array.opcodes;
+       if (UNEXPECTED(Z_OBJ_P(fast_call) != NULL)) {
+               fast_call->u2.lineno = (uint32_t)-1;
+       } else {
+               /* set return address */
+               fast_call->u2.lineno = opline - EX(func)->op_array.opcodes;
+       }
        ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op1));
        ZEND_VM_CONTINUE();
 }
index 77b4d66f94402dfce3376da620429fc121b19060..de170d2295e228f40243f5921273fc2dc3fd2268 100644 (file)
@@ -77,7 +77,6 @@ void optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *c
 
     while (opline >= end) {
                if ((ZEND_OP1_TYPE(opline) & (IS_VAR | IS_TMP_VAR))) {
-
                        currT = VAR_NUM(ZEND_OP1(opline).var) - offset;
                        if (opline->opcode == ZEND_ROPE_END) {
                                int num = (((opline->extended_value + 1) * sizeof(zend_string*)) + (sizeof(zval) - 1)) / sizeof(zval);
@@ -153,7 +152,9 @@ void optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *c
                        currT = VAR_NUM(ZEND_RESULT(opline).var) - offset;
                        if (valid_T[currT]) {
                                if (start_of_T[currT] == opline) {
-                                       taken_T[map_T[currT]] = 0;
+                                       if (opline->opcode != ZEND_FAST_CALL) {
+                                               taken_T[map_T[currT]] = 0;
+                                       }
                                }
                                ZEND_RESULT(opline).var = NUM_VAR(map_T[currT] + offset);
                                if (opline->opcode == ZEND_ROPE_INIT) {