diff options
author | Xinchen Hui <laruence@php.net> | 2015-07-08 17:15:09 +0800 |
---|---|---|
committer | Xinchen Hui <laruence@php.net> | 2015-07-08 17:15:09 +0800 |
commit | c6037bd3af5cc9f42fe02eae2a2066185ba67a69 (patch) | |
tree | 09a26041aa289e949bcee21b894714638968b158 | |
parent | 6154fc77be8eff09736c2f15b350ae07bec72816 (diff) | |
download | php-git-c6037bd3af5cc9f42fe02eae2a2066185ba67a69.tar.gz |
Fixed bug #70012 (Exception lost with nested finally block)
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | Zend/tests/bug70012.phpt | 32 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 9 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 9 | ||||
-rw-r--r-- | ext/opcache/Optimizer/optimize_temp_vars_5.c | 5 |
5 files changed, 50 insertions, 8 deletions
@@ -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 index 0000000000..5337649d2d --- /dev/null +++ b/Zend/tests/bug70012.phpt @@ -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 diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index cff901164e..db746a647c 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -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(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 720af1acd4..832692d1db 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -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(); } diff --git a/ext/opcache/Optimizer/optimize_temp_vars_5.c b/ext/opcache/Optimizer/optimize_temp_vars_5.c index 77b4d66f94..de170d2295 100644 --- a/ext/opcache/Optimizer/optimize_temp_vars_5.c +++ b/ext/opcache/Optimizer/optimize_temp_vars_5.c @@ -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) { |