diff options
author | Dmitry Stogov <dmitry@zend.com> | 2015-07-09 23:20:50 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2015-07-09 23:20:50 +0300 |
commit | 8c3f701eebfa92d761bb368cfa8c2d1ccf821b9d (patch) | |
tree | 27b4b3a7e25b4f8785ff5205ea7c3c91ebe16330 | |
parent | 788c4c852d0b0523eb918039e4ac3247f5c8a6d0 (diff) | |
download | php-git-8c3f701eebfa92d761bb368cfa8c2d1ccf821b9d.tar.gz |
Fixed exception catching on break/continue
Fixed "finaly" handling on exception in "return" statement
-rw-r--r-- | Zend/tests/return_types/031.phpt | 43 | ||||
-rw-r--r-- | Zend/zend_compile.c | 6 | ||||
-rw-r--r-- | Zend/zend_compile.h | 3 | ||||
-rw-r--r-- | Zend/zend_opcode.c | 4 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 8 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 8 |
6 files changed, 58 insertions, 14 deletions
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-- +<?php + +function foo(): string { + $a = "OK\n"; + try { + return $a; // invalid return type + } catch (TypeError $e) { + echo "BAG!\n"; + return "ops!\n"; + } finally { + echo "finally1\n"; + } +} +function bar(): string { + $a = []; + try { + return $a; // invalid return type + } catch (TypeError $e) { + echo "BAG!\n"; + return "ops!\n"; + } finally { + echo "finally2\n"; + } +} +try { + echo foo(); +} catch (TypeError $e) { + echo "BAG\n"; +} +try { + echo bar(); +} catch (TypeError $e) { + echo "OK\n"; +} +?> +--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; } } |