summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinchen Hui <laruence@gmail.com>2016-05-17 15:32:43 +0800
committerXinchen Hui <laruence@gmail.com>2016-05-17 15:32:43 +0800
commit5037ebf058bdc94e4426240a6d35fcf427d2eee2 (patch)
tree021a39b798faf237d99905a382a50a7b791d85cd
parent8f7b1a3248e29469b78eab645be3aea1a62f0adc (diff)
downloadphp-git-5037ebf058bdc94e4426240a6d35fcf427d2eee2.tar.gz
Fixed Bug #72213 (Finally leaks on nested exceptions)
-rw-r--r--Zend/tests/try/bug72213.phpt25
-rw-r--r--Zend/zend_vm_def.h12
-rw-r--r--Zend/zend_vm_execute.h12
3 files changed, 43 insertions, 6 deletions
diff --git a/Zend/tests/try/bug72213.phpt b/Zend/tests/try/bug72213.phpt
new file mode 100644
index 0000000000..624050295e
--- /dev/null
+++ b/Zend/tests/try/bug72213.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Bug #72213 (Finally leaks on nested exceptions)
+--FILE--
+<?php
+function test() {
+ try {
+ throw new Exception('a');
+ } finally {
+ try {
+ throw new Exception('b');
+ } finally {
+ }
+ }
+}
+
+try {
+ test();
+} catch (Exception $e) {
+ var_dump($e->getMessage());
+ var_dump($e->getPrevious()->getMessage());
+}
+?>
+--EXPECT--
+string(1) "b"
+string(1) "a"
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index c02b27a953..cb568faa43 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -7087,7 +7087,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
{
uint32_t op_num = EG(opline_before_exception) - EX(func)->op_array.opcodes;
int i;
- uint32_t catch_op_num = 0, finally_op_num = 0, finally_op_end = 0;
+ uint32_t catch_op_num = 0, finally_op_num = 0, finally_op_end = 0, prev_finally_op_end = 0;
int in_finally = 0;
{
@@ -7118,6 +7118,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
if (op_num >= EX(func)->op_array.try_catch_array[i].finally_op &&
op_num < EX(func)->op_array.try_catch_array[i].finally_end) {
finally_op_end = EX(func)->op_array.try_catch_array[i].finally_end;
+ prev_finally_op_end = finally_op_end;
in_finally = 1;
}
}
@@ -7128,8 +7129,13 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var);
cleanup_live_vars(execute_data, op_num, finally_op_num);
- if (in_finally && Z_OBJ_P(fast_call)) {
- zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call));
+ if (prev_finally_op_end) {
+ zval *prev_fast_call = EX_VAR(EX(func)->op_array.opcodes[prev_finally_op_end].op1.var);
+
+ if (Z_OBJ_P(prev_fast_call)) {
+ zend_exception_set_previous(EG(exception), Z_OBJ_P(prev_fast_call));
+ Z_OBJ_P(prev_fast_call) = NULL;
+ }
}
Z_OBJ_P(fast_call) = EG(exception);
EG(exception) = NULL;
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 8572451a29..3518508c35 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -1693,7 +1693,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(
{
uint32_t op_num = EG(opline_before_exception) - EX(func)->op_array.opcodes;
int i;
- uint32_t catch_op_num = 0, finally_op_num = 0, finally_op_end = 0;
+ uint32_t catch_op_num = 0, finally_op_num = 0, finally_op_end = 0, prev_finally_op_end = 0;
int in_finally = 0;
{
@@ -1724,6 +1724,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(
if (op_num >= EX(func)->op_array.try_catch_array[i].finally_op &&
op_num < EX(func)->op_array.try_catch_array[i].finally_end) {
finally_op_end = EX(func)->op_array.try_catch_array[i].finally_end;
+ prev_finally_op_end = finally_op_end;
in_finally = 1;
}
}
@@ -1734,8 +1735,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(
zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var);
cleanup_live_vars(execute_data, op_num, finally_op_num);
- if (in_finally && Z_OBJ_P(fast_call)) {
- zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call));
+ if (prev_finally_op_end) {
+ zval *prev_fast_call = EX_VAR(EX(func)->op_array.opcodes[prev_finally_op_end].op1.var);
+
+ if (Z_OBJ_P(prev_fast_call)) {
+ zend_exception_set_previous(EG(exception), Z_OBJ_P(prev_fast_call));
+ Z_OBJ_P(prev_fast_call) = NULL;
+ }
}
Z_OBJ_P(fast_call) = EG(exception);
EG(exception) = NULL;