diff options
author | Dmitry Stogov <dmitry@zend.com> | 2016-05-13 14:38:43 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2016-05-13 14:38:43 +0300 |
commit | be071702b30e9ba9bf9f9c9831f3301af039b1d5 (patch) | |
tree | 0c55550a9cc926c5b409b2c01bf22521265c5bf6 | |
parent | e9c3f9fcde1013cc1c9bdead7e16478a108d7907 (diff) | |
download | php-git-be071702b30e9ba9bf9f9c9831f3301af039b1d5.tar.gz |
Fixed bug #72188 (Nested try/finally blocks losing return value)
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | Zend/tests/bug72188.phpt | 27 | ||||
-rw-r--r-- | Zend/zend_compile.c | 5 | ||||
-rw-r--r-- | Zend/zend_opcode.c | 1 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 9 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 7 | ||||
-rw-r--r-- | Zend/zend_vm_opcodes.c | 2 | ||||
-rw-r--r-- | sapi/phpdbg/tests/stepping_001.phpt | 2 |
8 files changed, 43 insertions, 11 deletions
@@ -14,6 +14,7 @@ PHP NEWS null byte). (Francois) . Fixed bug #71897 (ASCII 0x7F Delete control character permitted in identifiers). (Andrea) + . Fixed bug #72188 (Nested try/finally blocks losing return value). (Dmitry) . Implemented the RFC `Support Class Constant Visibility`. (Sean DuBois, Reeze Xia, Dmitry) . Added void return type. (Andrea) diff --git a/Zend/tests/bug72188.phpt b/Zend/tests/bug72188.phpt new file mode 100644 index 0000000000..0deab6b81b --- /dev/null +++ b/Zend/tests/bug72188.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #72188 (Nested try/finally blocks losing return value) +--FILE-- +<?php +function test() { + try { + return 5; + } finally { + try { + echo 1; + } finally { + echo 2; + } + } +} + + + +$a = test(); +if($a !== 5) { + echo "FAILED: expected 5, received ", var_export($a), PHP_EOL; +} else { + echo "Passed", PHP_EOL; +} +?> +--EXPECT-- +12Passed diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index c534088b58..7ae54da5bb 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4532,6 +4532,7 @@ void zend_compile_try(zend_ast *ast) /* {{{ */ zend_op *opline; uint32_t try_catch_offset; uint32_t *jmp_opnums = safe_emalloc(sizeof(uint32_t), catches->children, 0); + uint32_t orig_fast_call_var = CG(context).fast_call_var; if (catches->children == 0 && !finally_ast) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use try without catch or finally"); @@ -4554,8 +4555,8 @@ void zend_compile_try(zend_ast *ast) /* {{{ */ zend_loop_var fast_call; if (!(CG(active_op_array)->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) { CG(active_op_array)->fn_flags |= ZEND_ACC_HAS_FINALLY_BLOCK; - CG(context).fast_call_var = get_temporary_variable(CG(active_op_array)); } + CG(context).fast_call_var = get_temporary_variable(CG(active_op_array)); /* Push FAST_CALL on unwind stack */ fast_call.opcode = ZEND_FAST_CALL; @@ -4665,6 +4666,8 @@ void zend_compile_try(zend_ast *ast) /* {{{ */ opline->op1.var = CG(context).fast_call_var; zend_update_jump_target_to_next(opnum_jmp); + + CG(context).fast_call_var = orig_fast_call_var; } efree(jmp_opnums); diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 27c04e3a76..34e060fa4a 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -550,7 +550,6 @@ static void zend_resolve_fast_call(zend_op_array *op_array, uint32_t op_num) /* Must be ZEND_FAST_CALL */ ZEND_ASSERT(op_array->opcodes[op_array->try_catch_array[finally_num].finally_op - 2].opcode == ZEND_FAST_CALL); op_array->opcodes[op_num].extended_value = ZEND_FAST_CALL_FROM_FINALLY; - op_array->opcodes[op_num].op2.num = finally_num; } } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index b65075830c..2750d8e60a 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7531,7 +7531,7 @@ ZEND_VM_HANDLER(159, ZEND_DISCARD_EXCEPTION, ANY, ANY) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(162, ZEND_FAST_CALL, JMP_ADDR, TRY_CATCH, FAST_CALL) +ZEND_VM_HANDLER(162, ZEND_FAST_CALL, JMP_ADDR, ANY, FAST_CALL) { USE_OPLINE zval *fast_call = EX_VAR(opline->result.var); @@ -7554,9 +7554,6 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, TRY_CATCH, FAST_RET) if (fast_call->u2.lineno != (uint32_t)-1) { const zend_op *fast_ret = EX(func)->op_array.opcodes + fast_call->u2.lineno; - if (fast_ret->extended_value & ZEND_FAST_CALL_FROM_FINALLY) { - fast_call->u2.lineno = EX(func)->op_array.try_catch_array[fast_ret->op2.num].finally_op - 2; - } ZEND_VM_SET_OPCODE(fast_ret + 1); ZEND_VM_CONTINUE(); } else { @@ -7565,7 +7562,11 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, TRY_CATCH, FAST_RET) if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) { uint32_t finally_op = EX(func)->op_array.try_catch_array[opline->op2.num].finally_op; + uint32_t finally_end = EX(func)->op_array.try_catch_array[opline->op2.num].finally_end; + zval *next_fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_end].op1.var); + Z_OBJ_P(next_fast_call) = Z_OBJ_P(fast_call); + next_fast_call->u2.lineno = (uint32_t)-1; cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, finally_op); ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[finally_op]); ZEND_VM_CONTINUE(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 9eaff4624d..5b09255f30 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1845,9 +1845,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPC if (fast_call->u2.lineno != (uint32_t)-1) { const zend_op *fast_ret = EX(func)->op_array.opcodes + fast_call->u2.lineno; - if (fast_ret->extended_value & ZEND_FAST_CALL_FROM_FINALLY) { - fast_call->u2.lineno = EX(func)->op_array.try_catch_array[fast_ret->op2.num].finally_op - 2; - } ZEND_VM_SET_OPCODE(fast_ret + 1); ZEND_VM_CONTINUE(); } else { @@ -1856,7 +1853,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPC if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) { uint32_t finally_op = EX(func)->op_array.try_catch_array[opline->op2.num].finally_op; + uint32_t finally_end = EX(func)->op_array.try_catch_array[opline->op2.num].finally_end; + zval *next_fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_end].op1.var); + Z_OBJ_P(next_fast_call) = Z_OBJ_P(fast_call); + next_fast_call->u2.lineno = (uint32_t)-1; cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, finally_op); ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[finally_op]); ZEND_VM_CONTINUE(); diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index 3edde60853..180b745fb2 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -371,7 +371,7 @@ static uint32_t zend_vm_opcodes_flags[184] = { 0x00000000, 0x0b000303, 0x00000003, - 0x09003020, + 0x09000020, 0x0a003000, 0x00000010, 0x00000000, diff --git a/sapi/phpdbg/tests/stepping_001.phpt b/sapi/phpdbg/tests/stepping_001.phpt index ec9def278f..9366550f56 100644 --- a/sapi/phpdbg/tests/stepping_001.phpt +++ b/sapi/phpdbg/tests/stepping_001.phpt @@ -34,7 +34,7 @@ prompt> [L10 %s ECHO "ok" 00011: } finally { 00012: echo " ... ok"; prompt> ok -[L11 %s FAST_CALL J8 try-catch(0) ~%d %s] +[L11 %s FAST_CALL J8 ~%d %s] >00011: } finally { 00012: echo " ... ok"; 00013: } |