From: Dmitry Stogov Date: Thu, 9 Jul 2015 20:20:50 +0000 (+0300) Subject: Fixed exception catching on break/continue X-Git-Tag: php-7.1.1RC1~35^2~43 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8c3f701eebfa92d761bb368cfa8c2d1ccf821b9d;p=php Fixed exception catching on break/continue Fixed "finaly" handling on exception in "return" statement --- diff --git a/Zend/tests/return_types/031.phpt b/Zend/tests/return_types/031.phpt new file mode 100644 index 0000000000..7240274804 --- /dev/null +++ b/Zend/tests/return_types/031.phpt @@ -0,0 +1,43 @@ +--TEST-- +Excepton on return types mismutch shouldn't execute "catch" code but should execute "finally" code. +--FILE-- + +--EXPECT-- +finally1 +OK +finally2 +OK diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 4f21769e12..4ae27e5a3f 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3482,7 +3482,7 @@ void zend_compile_return(zend_ast *ast) /* {{{ */ zend_emit_return_type_check(expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1); } - zend_free_foreach_and_switch_variables(ZEND_FREE_ON_JUMP); + zend_free_foreach_and_switch_variables(ZEND_FREE_ON_RETURN); if (CG(context).in_finally) { opline = zend_emit_op(NULL, ZEND_DISCARD_EXCEPTION, NULL, NULL); @@ -3567,7 +3567,7 @@ void zend_compile_break_continue(zend_ast *ast) /* {{{ */ } if (nest_level > 1) { - generate_free_loop_var_ex(&CG(context).brk_cont_array[array_offset].loop_var, ZEND_FREE_ON_JUMP); + generate_free_loop_var_ex(&CG(context).brk_cont_array[array_offset].loop_var, ZEND_FREE_ON_BREAK); } array_offset = CG(context).brk_cont_array[array_offset].parent; @@ -3637,7 +3637,7 @@ void zend_resolve_goto_label(zend_op_array *op_array, znode *label_node, zend_op if (pass2_opline) { free_vars++; } else { - generate_free_loop_var_ex(&CG(context).brk_cont_array[current].loop_var, ZEND_FREE_ON_JUMP); + generate_free_loop_var_ex(&CG(context).brk_cont_array[current].loop_var, ZEND_FREE_ON_BREAK); } } current = CG(context).brk_cont_array[current].parent; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 5560b7e86d..52456a79e9 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -882,7 +882,8 @@ ZEND_API void zend_assert_valid_class_name(const zend_string *const_name); #define ZEND_FETCH_ARG_MASK 0x000fffff -#define ZEND_FREE_ON_JUMP (1<<0) +#define ZEND_FREE_ON_RETURN (1<<0) +#define ZEND_FREE_ON_BREAK (1<<1) #define ZEND_MEMBER_FUNC_CALL (1<<0) diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 6a89a54712..5fe5ae7f33 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -994,8 +994,8 @@ static zend_always_inline uint32_t *generate_var_liveliness_info_ex(zend_op_arra && opline->opcode != ZEND_FE_FETCH_RW /* the following opcodes are parts of "return" statement */ && opline->opcode != ZEND_VERIFY_RETURN_TYPE - && (opline->opcode != ZEND_FREE || !(opline->extended_value & ZEND_FREE_ON_JUMP)) - && (opline->opcode != ZEND_FE_FREE || !(opline->extended_value & ZEND_FREE_ON_JUMP)) + && (opline->opcode != ZEND_FREE || !(opline->extended_value & (ZEND_FREE_ON_RETURN|ZEND_FREE_ON_BREAK))) + && (opline->opcode != ZEND_FE_FREE || !(opline->extended_value & (ZEND_FREE_ON_RETURN|ZEND_FREE_ON_BREAK))) ) { op_live_total += liveliness_kill_var(op_array, opline, var, Tstart, opTs); } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 57c8a94867..98f6be671a 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7082,12 +7082,12 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) } } - if (catch_op_num || finally_op_num) { + if (catch_op_num) { if (EX(func)->op_array.opcodes[op_num].opcode == ZEND_VERIFY_RETURN_TYPE - || (EX(func)->op_array.opcodes[op_num].opcode == ZEND_FREE && (EX(func)->op_array.opcodes[op_num].extended_value & ZEND_FREE_ON_JUMP)) - || (EX(func)->op_array.opcodes[op_num].opcode == ZEND_FE_FREE && (EX(func)->op_array.opcodes[op_num].extended_value & ZEND_FREE_ON_JUMP)) + || (EX(func)->op_array.opcodes[op_num].opcode == ZEND_FREE && (EX(func)->op_array.opcodes[op_num].extended_value & ZEND_FREE_ON_RETURN)) + || (EX(func)->op_array.opcodes[op_num].opcode == ZEND_FE_FREE && (EX(func)->op_array.opcodes[op_num].extended_value & ZEND_FREE_ON_RETURN)) ) { - catch_op_num = finally_op_num = 0; + catch_op_num = 0; } } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index bdfce50cf1..95c1b5dfaa 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1500,12 +1500,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER( } } - if (catch_op_num || finally_op_num) { + if (catch_op_num) { if (EX(func)->op_array.opcodes[op_num].opcode == ZEND_VERIFY_RETURN_TYPE - || (EX(func)->op_array.opcodes[op_num].opcode == ZEND_FREE && (EX(func)->op_array.opcodes[op_num].extended_value & ZEND_FREE_ON_JUMP)) - || (EX(func)->op_array.opcodes[op_num].opcode == ZEND_FE_FREE && (EX(func)->op_array.opcodes[op_num].extended_value & ZEND_FREE_ON_JUMP)) + || (EX(func)->op_array.opcodes[op_num].opcode == ZEND_FREE && (EX(func)->op_array.opcodes[op_num].extended_value & ZEND_FREE_ON_RETURN)) + || (EX(func)->op_array.opcodes[op_num].opcode == ZEND_FE_FREE && (EX(func)->op_array.opcodes[op_num].extended_value & ZEND_FREE_ON_RETURN)) ) { - catch_op_num = finally_op_num = 0; + catch_op_num = 0; } }