summaryrefslogtreecommitdiff
path: root/Zend/zend_compile.c
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2016-05-25 01:25:12 +0300
committerDmitry Stogov <dmitry@zend.com>2016-05-25 01:25:12 +0300
commit2ae21abdf7b87ee95d76aca22e787408d7c766cf (patch)
tree26c8c6ba8f81f077c10cd5031b3d8b79ecdaa064 /Zend/zend_compile.c
parent91f5940329fede8a26b64e99d4d6d858fe8654cc (diff)
downloadphp-git-2ae21abdf7b87ee95d76aca22e787408d7c766cf.tar.gz
Fixed bug #72213 (Finally leaks on nested exceptions).
Squashed commit of the following: commit 8461b0407fc9eab0869d43b84e6a92ba2fe06997 Author: Dmitry Stogov <dmitry@zend.com> Date: Wed May 25 00:34:42 2016 +0300 Rmoved zend_try_catch_element.parent and walk through op_array.try_catch_array backward from the current try_cacth_offset. commit 0c71e249649bed178bfbef30bb3e63c57f07af05 Author: Dmitry Stogov <dmitry@zend.com> Date: Wed May 25 00:04:53 2016 +0300 Move SAVE_OPLINE() to its original place commit 111432a4df738fcd65878a42f23194dc3c4983a2 Author: Dmitry Stogov <dmitry@zend.com> Date: Wed May 25 00:01:10 2016 +0300 Separate the common part of ZEND_HANDLE_EXCEPTION and FAST_RET into zend_dispatch_try_catch_finally_helper. commit 4f21c06c2ec17819a708bc037f318784554a6ecd Author: Nikita Popov <nikic@php.net> Date: Tue May 24 14:55:27 2016 +0200 Improve finally fix commit da5c7274997b8308e682b5bf280124e3a1483086 Author: Dmitry Stogov <dmitry@zend.com> Date: Tue May 24 10:36:08 2016 +0300 Fixed Zend/tests/try/bug70228_3.phpt and Zend/tests/try/bug70228_4.phpt commit cfcedf2fb4f4fc1f7de9f7d53a3037fed7795f19 Author: Dmitry Stogov <dmitry@zend.com> Date: Tue May 24 02:59:27 2016 +0300 Added test commit 4c6aa93d43da941eb4fda15b48154bfb104bdc04 Author: Dmitry Stogov <dmitry@zend.com> Date: Tue May 24 00:38:20 2016 +0300 Added tests commit 8a8f4704b0eca2e460d42c1f253a363b0db8e510 Author: Dmitry Stogov <dmitry@zend.com> Date: Mon May 23 23:27:34 2016 +0300 Fixed bug #72213 (Finally leaks on nested exceptions)
Diffstat (limited to 'Zend/zend_compile.c')
-rw-r--r--Zend/zend_compile.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 0994681c20..c6da34732a 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -234,6 +234,7 @@ void zend_oparray_context_begin(zend_oparray_context *prev_context) /* {{{ */
CG(context).backpatch_count = 0;
CG(context).in_finally = 0;
CG(context).fast_call_var = -1;
+ CG(context).try_catch_offset = -1;
CG(context).current_brk_cont = -1;
CG(context).last_brk_cont = 0;
CG(context).brk_cont_array = NULL;
@@ -4008,6 +4009,12 @@ static int zend_handle_loops_and_finally_ex(zend_long depth) /* {{{ */
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
opline->op1.num = loop_var->u.try_catch_offset;
+ } else if (loop_var->opcode == ZEND_DISCARD_EXCEPTION) {
+ zend_op *opline = get_next_op(CG(active_op_array));
+ opline->opcode = ZEND_DISCARD_EXCEPTION;
+ opline->op1_type = IS_TMP_VAR;
+ opline->op1.var = loop_var->var_num;
+ SET_UNUSED(opline->op2);
} else if (loop_var->opcode == ZEND_RETURN) {
/* Stack separator */
break;
@@ -4057,12 +4064,6 @@ void zend_compile_return(zend_ast *ast) /* {{{ */
zend_compile_expr(&expr_node, expr_ast);
}
- if (CG(context).in_finally) {
- opline = zend_emit_op(NULL, ZEND_DISCARD_EXCEPTION, NULL, NULL);
- opline->op1_type = IS_TMP_VAR;
- opline->op1.var = CG(context).fast_call_var;
- }
-
/* Generator return types are handled separately */
if (!(CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) && CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
zend_emit_return_type_check(expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1);
@@ -4573,6 +4574,7 @@ void zend_compile_try(zend_ast *ast) /* {{{ */
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;
+ uint32_t orig_try_catch_offset = CG(context).try_catch_offset;
if (catches->children == 0 && !finally_ast) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use try without catch or finally");
@@ -4606,6 +4608,8 @@ void zend_compile_try(zend_ast *ast) /* {{{ */
zend_stack_push(&CG(loop_var_stack), &fast_call);
}
+ CG(context).try_catch_offset = try_catch_offset;
+
zend_compile_stmt(try_ast);
if (catches->children != 0) {
@@ -4679,11 +4683,18 @@ void zend_compile_try(zend_ast *ast) /* {{{ */
}
if (finally_ast) {
+ zend_loop_var discard_exception;
uint32_t opnum_jmp = get_next_op_number(CG(active_op_array)) + 1;
/* Pop FAST_CALL from unwind stack */
zend_stack_del_top(&CG(loop_var_stack));
+ /* Push DISCARD_EXCEPTION on unwind stack */
+ discard_exception.opcode = ZEND_DISCARD_EXCEPTION;
+ discard_exception.var_type = IS_TMP_VAR;
+ discard_exception.var_num = CG(context).fast_call_var;
+ zend_stack_push(&CG(loop_var_stack), &discard_exception);
+
CG(zend_lineno) = finally_ast->lineno;
opline = zend_emit_op(NULL, ZEND_FAST_CALL, NULL, NULL);
@@ -4704,12 +4715,18 @@ void zend_compile_try(zend_ast *ast) /* {{{ */
opline = zend_emit_op(NULL, ZEND_FAST_RET, NULL, NULL);
opline->op1_type = IS_TMP_VAR;
opline->op1.var = CG(context).fast_call_var;
+ opline->op2.num = orig_try_catch_offset;
zend_update_jump_target_to_next(opnum_jmp);
CG(context).fast_call_var = orig_fast_call_var;
+
+ /* Pop DISCARD_EXCEPTION from unwind stack */
+ zend_stack_del_top(&CG(loop_var_stack));
}
+ CG(context).try_catch_offset = orig_try_catch_offset;
+
efree(jmp_opnums);
}
/* }}} */