From 303d73ecd26db0f88dfd1630ae55557ca47caece Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 26 Nov 2014 22:44:58 +0300 Subject: [PATCH] Reimplemented silence operator (@) handling on exceptions. Now each silence region is stored in op_array->brk_cont_array. On exception ZEND_HANDLE_EXCEPTION handler traverse this array and restore original EG(error_reporting) if exception occured inside a "silence" region. --- Zend/zend_compile.c | 22 +++++++++++++--------- Zend/zend_compile.h | 2 -- Zend/zend_execute.c | 3 --- Zend/zend_vm_def.h | 18 +++++------------- Zend/zend_vm_execute.h | 18 +++++------------- ext/opcache/Optimizer/block_pass.c | 6 ++++-- 6 files changed, 27 insertions(+), 42 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 6caa294448..0905c3ce5f 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5524,13 +5524,11 @@ void zend_compile_silence(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ { zend_ast *expr_ast = ast->child[0]; znode silence_node; - uint32_t opline_num; - zend_op *begin_silence, *end_silence; + uint32_t begin_opline_num, end_opline_num; + zend_brk_cont_element *brk_cont_element; - opline_num = get_next_op_number(CG(active_op_array)); - begin_silence = zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL TSRMLS_CC); - /* pair BEGIN_SILENCE and END_SILENCE opcodes */ - begin_silence->op2.num = opline_num; + begin_opline_num = get_next_op_number(CG(active_op_array)); + zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL TSRMLS_CC); if (expr_ast->kind == ZEND_AST_VAR) { /* For @$var we need to force a FETCH instruction, otherwise the CV access will @@ -5540,9 +5538,15 @@ void zend_compile_silence(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ zend_compile_expr(result, expr_ast TSRMLS_CC); } - end_silence = zend_emit_op(NULL, ZEND_END_SILENCE, &silence_node, NULL TSRMLS_CC); - /* pair BEGIN_SILENCE and END_SILENCE opcodes */ - end_silence->op2.num = opline_num; + end_opline_num = get_next_op_number(CG(active_op_array)); + zend_emit_op(NULL, ZEND_END_SILENCE, &silence_node, NULL TSRMLS_CC); + + /* Store BEGIN_SILENCE/END_SILENCE pair to restore previous + * EG(error_reporting) value on exception */ + brk_cont_element = get_next_brk_cont_element(CG(active_op_array)); + brk_cont_element->start = begin_opline_num; + brk_cont_element->cont = brk_cont_element->brk = end_opline_num; + brk_cont_element->parent = -1; } /* }}} */ diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index f9a66a37d8..d6184c9dc3 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -378,8 +378,6 @@ struct _zend_execute_data { zend_array *symbol_table; const zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */ zend_object *delayed_exception; - uint32_t silence_op_num; - uint32_t old_error_reporting; }; #define VM_FRAME_KIND_MASK 0x000000ff diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 6c8ebca707..fc8cd57ced 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1486,7 +1486,6 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu EX(call) = NULL; EX(return_value) = return_value; EX(delayed_exception) = NULL; - EX(silence_op_num) = -1; /* Handle arguments */ first_extra_arg = op_array->num_args; @@ -1553,7 +1552,6 @@ static zend_always_inline void i_init_code_execute_data(zend_execute_data *execu EX(return_value) = return_value; EX(scope) = EG(scope); EX(delayed_exception) = NULL; - EX(silence_op_num) = -1; zend_attach_symbol_table(execute_data); @@ -1580,7 +1578,6 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da EX(return_value) = return_value; EX(scope) = EG(scope); EX(delayed_exception) = NULL; - EX(silence_op_num) = -1; if (UNEXPECTED(EX(symbol_table) != NULL)) { zend_attach_symbol_table(execute_data); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 223f43dda7..85342eaf43 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5113,10 +5113,6 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY) SAVE_OPLINE(); ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting)); - if (EX(silence_op_num) == -1) { - EX(silence_op_num) = opline->op2.num; - EX(old_error_reporting) = EG(error_reporting); - } if (EG(error_reporting)) { do { @@ -5154,9 +5150,6 @@ ZEND_VM_HANDLER(58, ZEND_END_SILENCE, TMP, ANY) if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(opline->op1.var)) != 0) { EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var)); } - if (EX(silence_op_num) == opline->op2.num) { - EX(silence_op_num) = -1; - } ZEND_VM_NEXT_OPCODE(); } @@ -5522,17 +5515,16 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var)); } + } else if (brk_opline->opcode == ZEND_END_SILENCE) { + /* restore previous error_reporting value */ + if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) { + EG(error_reporting) = Z_LVAL_P(EX_VAR(brk_opline->op1.var)); + } } } } } - /* restore previous error_reporting value */ - if (!EG(error_reporting) && EX(silence_op_num) != -1 && EX(old_error_reporting) != 0) { - EG(error_reporting) = EX(old_error_reporting); - } - EX(silence_op_num) = -1; - if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) { if (EX(delayed_exception)) { zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 5210484370..c80229f738 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1029,10 +1029,6 @@ static int ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting)); - if (EX(silence_op_num) == -1) { - EX(silence_op_num) = opline->op2.num; - EX(old_error_reporting) = EG(error_reporting); - } if (EG(error_reporting)) { do { @@ -1264,17 +1260,16 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var)); } + } else if (brk_opline->opcode == ZEND_END_SILENCE) { + /* restore previous error_reporting value */ + if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) { + EG(error_reporting) = Z_LVAL_P(EX_VAR(brk_opline->op1.var)); + } } } } } - /* restore previous error_reporting value */ - if (!EG(error_reporting) && EX(silence_op_num) != -1 && EX(old_error_reporting) != 0) { - EG(error_reporting) = EX(old_error_reporting); - } - EX(silence_op_num) = -1; - if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) { if (EX(delayed_exception)) { zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC); @@ -10251,9 +10246,6 @@ static int ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(opline->op1.var)) != 0) { EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var)); } - if (EX(silence_op_num) == opline->op2.num) { - EX(silence_op_num) = -1; - } ZEND_VM_NEXT_OPCODE(); } diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index 5c6880beea..6f3f1310a0 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -204,7 +204,8 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz j = 0; for (i = 0; i< op_array->last_brk_cont; i++) { if (op_array->brk_cont_array[i].start >= 0 && - op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FREE) { + (op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FREE || + op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_END_SILENCE)) { int parent = op_array->brk_cont_array[i].parent; while (parent >= 0 && @@ -223,7 +224,8 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz j = 0; for (i = 0; i< op_array->last_brk_cont; i++) { if (op_array->brk_cont_array[i].start >= 0 && - op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FREE) { + (op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FREE || + op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_END_SILENCE)) { if (i != j) { op_array->brk_cont_array[j] = op_array->brk_cont_array[i]; } -- 2.40.0