diff options
author | Xinchen Hui <laruence@gmail.com> | 2016-05-17 15:32:43 +0800 |
---|---|---|
committer | Xinchen Hui <laruence@gmail.com> | 2016-05-17 15:32:43 +0800 |
commit | 5037ebf058bdc94e4426240a6d35fcf427d2eee2 (patch) | |
tree | 021a39b798faf237d99905a382a50a7b791d85cd | |
parent | 8f7b1a3248e29469b78eab645be3aea1a62f0adc (diff) | |
download | php-git-5037ebf058bdc94e4426240a6d35fcf427d2eee2.tar.gz |
Fixed Bug #72213 (Finally leaks on nested exceptions)
-rw-r--r-- | Zend/tests/try/bug72213.phpt | 25 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 12 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 12 |
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; |