mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Fixed bug #72188 (Nested try/finally blocks losing return value)
This commit is contained in:
parent
e9c3f9fcde
commit
be071702b3
8 changed files with 43 additions and 11 deletions
1
NEWS
1
NEWS
|
@ -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)
|
||||
|
|
27
Zend/tests/bug72188.phpt
Normal file
27
Zend/tests/bug72188.phpt
Normal file
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -371,7 +371,7 @@ static uint32_t zend_vm_opcodes_flags[184] = {
|
|||
0x00000000,
|
||||
0x0b000303,
|
||||
0x00000003,
|
||||
0x09003020,
|
||||
0x09000020,
|
||||
0x0a003000,
|
||||
0x00000010,
|
||||
0x00000000,
|
||||
|
|
|
@ -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: }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue