diff options
| author | Anatol Belski <ab@php.net> | 2014-11-27 15:59:43 +0100 |
|---|---|---|
| committer | Anatol Belski <ab@php.net> | 2014-11-27 15:59:43 +0100 |
| commit | 864cd82acef03b75b994f3fd98d9b4a51a99204a (patch) | |
| tree | 4edfbcc6ce5d2f6fa6da9908503119c70ad868b5 /Zend | |
| parent | 81a24f054b934ccb1be77049dd9c244283efcba7 (diff) | |
| parent | 4dcc8a63715b1bb42518e9c217ea493007016932 (diff) | |
| download | php-git-864cd82acef03b75b994f3fd98d9b4a51a99204a.tar.gz | |
Merge remote-tracking branch 'origin/master' into native-tls
* origin/master:
updated NEWS
refactored the mbstring config.w32
Update NEWS
Fixed compilation warnings
Fixed bug #68504 --with-libmbfl configure option not present on Windows
Changed "finally" handling. Removed EX(fast_ret) and EX(delayed_exception). Allocate and use additional IS_TMP_VAR slot on VM stack instead.
the darwin specific test fails for me with the same output which is the expected for the original test I couldn't find anybody who managed to see this test passing, but I found a bunch of other reports on qa.php.net/reports and on google which do see this test failing on mac. if this change causes you to have this test failing on Mac, please drop me a mail so we can improve the current test so it passes for everybody.
#68446 is fixed
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.
remove the NEWS entries for the reverted stuff
typo fix
go back with phpdbg to the state of 5.6.3, reverting the controversial commits(remote debugging/xml protocol)
5.5.21 now
New label length test
Fix ext/filter/tests/033.phpt
Fix filter_list test
FILTER_VALIDATE_DOMAIN and RFC conformance for FILTER_VALIDATE_URL
Conflicts:
ext/mbstring/config.w32
Diffstat (limited to 'Zend')
| -rw-r--r-- | Zend/zend_alloc.c | 13 | ||||
| -rw-r--r-- | Zend/zend_compile.c | 54 | ||||
| -rw-r--r-- | Zend/zend_compile.h | 5 | ||||
| -rw-r--r-- | Zend/zend_execute.c | 30 | ||||
| -rw-r--r-- | Zend/zend_gc.c | 2 | ||||
| -rw-r--r-- | Zend/zend_generators.c | 8 | ||||
| -rw-r--r-- | Zend/zend_indent.c | 2 | ||||
| -rw-r--r-- | Zend/zend_opcode.c | 11 | ||||
| -rw-r--r-- | Zend/zend_vm_def.h | 80 | ||||
| -rw-r--r-- | Zend/zend_vm_execute.h | 80 |
10 files changed, 174 insertions, 111 deletions
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 3041857dc6..1614690414 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -2130,6 +2130,7 @@ ZEND_API void* ZEND_FASTCALL _emalloc_huge(size_t size) return zend_mm_alloc_huge(AG(mm_heap), size); } +#if ZEND_DEBUG # define _ZEND_BIN_FREE(_num, _size, _elements, _pages, x, y) \ ZEND_API void ZEND_FASTCALL _efree_ ## _size(void *ptr) { \ TSRMLS_FETCH(); \ @@ -2144,6 +2145,18 @@ ZEND_API void* ZEND_FASTCALL _emalloc_huge(size_t size) zend_mm_free_small(AG(mm_heap), ptr, _num); \ } \ } +#else +# define _ZEND_BIN_FREE(_num, _size, _elements, _pages, x, y) \ + ZEND_API void ZEND_FASTCALL _efree_ ## _size(void *ptr) { \ + TSRMLS_FETCH(); \ + ZEND_MM_CUSTOM_DEALLOCATOR(ptr); \ + { \ + zend_mm_chunk *chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(ptr, ZEND_MM_CHUNK_SIZE); \ + ZEND_MM_CHECK(chunk->heap == AG(mm_heap), "zend_mm_heap corrupted"); \ + zend_mm_free_small(AG(mm_heap), ptr, _num); \ + } \ + } +#endif ZEND_MM_BINS_INFO(_ZEND_BIN_FREE, x, y) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 55be6176bf..5d409c7518 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -159,6 +159,7 @@ void zend_init_compiler_context(TSRMLS_D) /* {{{ */ CG(context).current_brk_cont = -1; CG(context).backpatch_count = 0; CG(context).in_finally = 0; + CG(context).fast_call_var = -1; CG(context).labels = NULL; } /* }}} */ @@ -1810,7 +1811,7 @@ static inline uint32_t zend_delayed_compile_begin(TSRMLS_D) /* {{{ */ static zend_op *zend_delayed_compile_end(uint32_t offset TSRMLS_DC) /* {{{ */ { - zend_op *opline, *oplines = zend_stack_base(&CG(delayed_oplines_stack)); + zend_op *opline = NULL, *oplines = zend_stack_base(&CG(delayed_oplines_stack)); uint32_t i, count = zend_stack_count(&CG(delayed_oplines_stack)); ZEND_ASSERT(count > offset); @@ -3126,7 +3127,9 @@ void zend_compile_return(zend_ast *ast TSRMLS_DC) /* {{{ */ zend_free_foreach_and_switch_variables(TSRMLS_C); if (CG(context).in_finally) { - zend_emit_op(NULL, ZEND_DISCARD_EXCEPTION, NULL, NULL TSRMLS_CC); + opline = zend_emit_op(NULL, ZEND_DISCARD_EXCEPTION, NULL, NULL TSRMLS_CC); + opline->op1_type = IS_TMP_VAR; + opline->op1.var = CG(context).fast_call_var; } opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN, @@ -3431,7 +3434,7 @@ void zend_compile_if(zend_ast *ast TSRMLS_DC) /* {{{ */ { zend_ast_list *list = zend_ast_get_list(ast); uint32_t i; - uint32_t *jmp_opnums; + uint32_t *jmp_opnums = NULL; if (list->children > 1) { jmp_opnums = safe_emalloc(sizeof(uint32_t), list->children - 1, 0); @@ -3621,8 +3624,15 @@ void zend_compile_try(zend_ast *ast TSRMLS_DC) /* {{{ */ if (finally_ast) { uint32_t opnum_jmp = get_next_op_number(CG(active_op_array)) + 1; + 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)); + } + opline = zend_emit_op(NULL, ZEND_FAST_CALL, NULL, NULL TSRMLS_CC); opline->op1.opline_num = opnum_jmp + 1; + opline->result_type = IS_TMP_VAR; + opline->result.var = CG(context).fast_call_var; zend_emit_op(NULL, ZEND_JMP, NULL, NULL TSRMLS_CC); @@ -3633,9 +3643,10 @@ void zend_compile_try(zend_ast *ast TSRMLS_DC) /* {{{ */ CG(active_op_array)->try_catch_array[try_catch_offset].finally_op = opnum_jmp + 1; CG(active_op_array)->try_catch_array[try_catch_offset].finally_end = get_next_op_number(CG(active_op_array)); - CG(active_op_array)->fn_flags |= ZEND_ACC_HAS_FINALLY_BLOCK; - zend_emit_op(NULL, ZEND_FAST_RET, NULL, NULL TSRMLS_CC); + opline = zend_emit_op(NULL, ZEND_FAST_RET, NULL, NULL TSRMLS_CC); + opline->op1_type = IS_TMP_VAR; + opline->op1.var = CG(context).fast_call_var; zend_update_jump_target_to_next(opnum_jmp TSRMLS_CC); } @@ -5524,13 +5535,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 +5549,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; } /* }}} */ @@ -5792,14 +5807,14 @@ void zend_compile_encaps_list(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ void zend_compile_magic_const(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ { - zend_class_entry *ce = CG(active_class_entry); - if (zend_try_ct_eval_magic_const(&result->u.constant, ast TSRMLS_CC)) { result->op_type = IS_CONST; return; } - ZEND_ASSERT(ast->attr == T_CLASS_C && ce && ZEND_CE_IS_TRAIT(ce)); + ZEND_ASSERT(ast->attr == T_CLASS_C && + CG(active_class_entry) && + ZEND_CE_IS_TRAIT(CG(active_class_entry))); { zend_ast *const_ast = zend_ast_create(ZEND_AST_CONST, @@ -5930,10 +5945,11 @@ void zend_compile_const_expr_resolve_class_name(zend_ast **ast_ptr TSRMLS_DC) /* void zend_compile_const_expr_magic_const(zend_ast **ast_ptr TSRMLS_DC) /* {{{ */ { zend_ast *ast = *ast_ptr; - zend_class_entry *ce = CG(active_class_entry); /* Other cases already resolved by constant folding */ - ZEND_ASSERT(ast->attr == T_CLASS_C && ce && ZEND_CE_IS_TRAIT(ce)); + ZEND_ASSERT(ast->attr == T_CLASS_C && + CG(active_class_entry) && + ZEND_CE_IS_TRAIT(CG(active_class_entry))); { zval const_zv; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index f9a66a37d8..4cf60c6181 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -52,6 +52,7 @@ typedef struct _zend_compiler_context { int current_brk_cont; int backpatch_count; int in_finally; + uint32_t fast_call_var; HashTable *labels; } zend_compiler_context; @@ -376,10 +377,6 @@ struct _zend_execute_data { zval *return_value; zend_class_entry *scope; /* function scope (self) */ 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..2fbd1d5011 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -558,20 +558,24 @@ ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uin fclass = ""; } - if (arg && zf->common.type == ZEND_USER_FUNCTION) { - ZVAL_COPY_VALUE(&old_arg, arg); - ZVAL_UNDEF(arg); - } + if (zf->common.type == ZEND_USER_FUNCTION) { + if (arg) { + ZVAL_COPY_VALUE(&old_arg, arg); + ZVAL_UNDEF(arg); + } - if (zf->common.type == ZEND_USER_FUNCTION && ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) { - zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind, ptr->func->op_array.filename->val, ptr->opline->lineno); + if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) { + zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind, ptr->func->op_array.filename->val, ptr->opline->lineno); + } else { + zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind); + } + + if (arg) { + ZVAL_COPY_VALUE(arg, &old_arg); + } } else { zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind); } - - if (arg && zf->common.type == ZEND_USER_FUNCTION) { - ZVAL_COPY_VALUE(arg, &old_arg); - } } static int is_null_constant(zval *default_value TSRMLS_DC) @@ -1485,8 +1489,6 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu EX(opline) = op_array->opcodes; 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; @@ -1552,8 +1554,6 @@ static zend_always_inline void i_init_code_execute_data(zend_execute_data *execu EX(call) = NULL; EX(return_value) = return_value; EX(scope) = EG(scope); - EX(delayed_exception) = NULL; - EX(silence_op_num) = -1; zend_attach_symbol_table(execute_data); @@ -1579,8 +1579,6 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da EX(call) = NULL; 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_gc.c b/Zend/zend_gc.c index e47b5350d4..f6aad866a7 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -641,7 +641,7 @@ static int gc_collect_roots(TSRMLS_D) static void gc_remove_nested_data_from_buffer(zend_refcounted *ref TSRMLS_DC) { - HashTable *ht; + HashTable *ht = NULL; uint idx; Bucket *p; diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index b38657f7b7..ef0b520eb0 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -133,7 +133,7 @@ static void zend_generator_dtor_storage(zend_object *object TSRMLS_DC) /* {{{ */ { zend_generator *generator = (zend_generator*) object; zend_execute_data *ex = generator->execute_data; - uint32_t op_num, finally_op_num; + uint32_t op_num, finally_op_num, finally_op_end; int i; if (!ex || !(ex->func->op_array.fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) { @@ -146,6 +146,7 @@ static void zend_generator_dtor_storage(zend_object *object TSRMLS_DC) /* {{{ */ /* Find next finally block */ finally_op_num = 0; + finally_op_end = 0; for (i = 0; i < ex->func->op_array.last_try_catch; i++) { zend_try_catch_element *try_catch = &ex->func->op_array.try_catch_array[i]; @@ -155,14 +156,17 @@ static void zend_generator_dtor_storage(zend_object *object TSRMLS_DC) /* {{{ */ if (op_num < try_catch->finally_op) { finally_op_num = try_catch->finally_op; + finally_op_end = try_catch->finally_end; } } /* If a finally block was found we jump directly to it and * resume the generator. */ if (finally_op_num) { + zval *fast_call = EX_VAR_2(ex, ex->func->op_array.opcodes[finally_op_end].op1.var); + + fast_call->u2.lineno = (uint32_t)-1; ex->opline = &ex->func->op_array.opcodes[finally_op_num]; - ex->fast_ret = NULL; generator->flags |= ZEND_GENERATOR_FORCED_CLOSE; zend_generator_resume(generator TSRMLS_CC); } diff --git a/Zend/zend_indent.c b/Zend/zend_indent.c index 93c10108f8..b5884c72c0 100644 --- a/Zend/zend_indent.c +++ b/Zend/zend_indent.c @@ -31,7 +31,7 @@ #define zendleng LANG_SCNG(yy_leng) -static void handle_whitespace(int *emit_whitespace) +static void handle_whitespace(unsigned int *emit_whitespace) { unsigned char c; int i; diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 5902abd4c5..1bbd35f40f 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -532,12 +532,19 @@ static void zend_resolve_finally_call(zend_op_array *op_array, uint32_t op_num, (dst_num < op_array->try_catch_array[i].try_op || dst_num > op_array->try_catch_array[i].finally_end)) { /* we have a jump out of try block that needs executing finally */ + uint32_t fast_call_var; + + /* Must be ZEND_FAST_RET */ + ZEND_ASSERT(op_array->opcodes[op_array->try_catch_array[i].finally_end].opcode == ZEND_FAST_RET); + fast_call_var = op_array->opcodes[op_array->try_catch_array[i].finally_end].op1.var; /* generate a FAST_CALL to finally block */ start_op = get_next_op_number(op_array); opline = get_next_op(op_array TSRMLS_CC); opline->opcode = ZEND_FAST_CALL; + opline->result_type = IS_TMP_VAR; + opline->result.var = fast_call_var; SET_UNUSED(opline->op1); SET_UNUSED(opline->op2); zend_adjust_fast_call(op_array, start_op, @@ -550,6 +557,8 @@ static void zend_resolve_finally_call(zend_op_array *op_array, uint32_t op_num, /* generate a FAST_CALL to hole CALL_FROM_FINALLY */ opline = get_next_op(op_array TSRMLS_CC); opline->opcode = ZEND_FAST_CALL; + opline->result_type = IS_TMP_VAR; + opline->result.var = fast_call_var; SET_UNUSED(opline->op1); SET_UNUSED(opline->op2); zend_resolve_fast_call(op_array, start_op + 1, op_array->try_catch_array[i].finally_op - 2 TSRMLS_CC); @@ -569,6 +578,8 @@ static void zend_resolve_finally_call(zend_op_array *op_array, uint32_t op_num, opline = get_next_op(op_array TSRMLS_CC); opline->opcode = ZEND_FAST_CALL; + opline->result_type = IS_TMP_VAR; + opline->result.var = fast_call_var; SET_UNUSED(opline->op1); SET_UNUSED(opline->op2); opline->op1.opline_num = op_array->try_catch_array[i].finally_op; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 223f43dda7..760f5f99f7 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(); } @@ -5476,6 +5469,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) } if (op_num < EX(func)->op_array.try_catch_array[i].finally_op) { finally_op_num = EX(func)->op_array.try_catch_array[i].finally_op; + finally_op_end = EX(func)->op_array.try_catch_array[i].finally_end; } if (op_num >= EX(func)->op_array.try_catch_array[i].finally_op && op_num < EX(func)->op_array.try_catch_array[i].finally_end) { @@ -5522,40 +5516,47 @@ 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); + zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var); + + if (Z_OBJ_P(fast_call)) { + zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call) TSRMLS_CC); } - EX(delayed_exception) = EG(exception); + Z_OBJ_P(fast_call) = EG(exception); EG(exception) = NULL; - EX(fast_ret) = NULL; + fast_call->u2.lineno = (uint32_t)-1; ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[finally_op_num]); ZEND_VM_CONTINUE(); } else if (catch_op_num) { if (finally_op_end && catch_op_num > finally_op_end) { /* we are going out of current finally scope */ - if (EX(delayed_exception)) { - zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC); - EX(delayed_exception) = NULL; + zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var); + + if (Z_OBJ_P(fast_call)) { + zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call) TSRMLS_CC); + Z_OBJ_P(fast_call) = NULL; } } ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op_num]); ZEND_VM_CONTINUE(); } else { - if (EX(delayed_exception)) { - zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC); - EX(delayed_exception) = NULL; + if (finally_op_end) { + zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var); + + if (Z_OBJ_P(fast_call)) { + zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call) TSRMLS_CC); + Z_OBJ_P(fast_call) = NULL; + } } if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) { ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN); @@ -5815,10 +5816,14 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE ZEND_VM_HANDLER(159, ZEND_DISCARD_EXCEPTION, ANY, ANY) { - if (EX(delayed_exception) != NULL) { + USE_OPLINE + zval *fast_call = EX_VAR(opline->op1.var); + + /* check for delayed exception */ + if (Z_OBJ_P(fast_call) != NULL) { /* discard the previously thrown exception */ - OBJ_RELEASE(EX(delayed_exception)); - EX(delayed_exception) = NULL; + OBJ_RELEASE(Z_OBJ_P(fast_call)); + Z_OBJ_P(fast_call) = NULL; } ZEND_VM_NEXT_OPCODE(); @@ -5827,6 +5832,7 @@ ZEND_VM_HANDLER(159, ZEND_DISCARD_EXCEPTION, ANY, ANY) ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY) { USE_OPLINE + zval *fast_call = EX_VAR(opline->result.var); if ((opline->extended_value & ZEND_FAST_CALL_FROM_CATCH) && UNEXPECTED(EG(prev_exception) != NULL)) { @@ -5834,18 +5840,24 @@ ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY) ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]); ZEND_VM_CONTINUE(); } - EX(fast_ret) = opline; - EX(delayed_exception) = NULL; + /* set no delayed exception */ + Z_OBJ_P(fast_call) = NULL; + /* set return address */ + fast_call->u2.lineno = opline - EX(func)->op_array.opcodes; ZEND_VM_SET_OPCODE(opline->op1.jmp_addr); ZEND_VM_CONTINUE(); } ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY) { - if (EX(fast_ret)) { - ZEND_VM_SET_OPCODE(EX(fast_ret) + 1); - if ((EX(fast_ret)->extended_value & ZEND_FAST_CALL_FROM_FINALLY)) { - EX(fast_ret) = &EX(func)->op_array.opcodes[EX(fast_ret)->op2.opline_num]; + USE_OPLINE + zval *fast_call = EX_VAR(opline->op1.var); + + if (fast_call->u2.lineno != (uint32_t)-1) { + const zend_op *fast_ret = EX(func)->op_array.opcodes + fast_call->u2.lineno; + ZEND_VM_SET_OPCODE(fast_ret + 1); + if (fast_ret->extended_value & ZEND_FAST_CALL_FROM_FINALLY) { + fast_call->u2.lineno = fast_ret->op2.opline_num; } ZEND_VM_CONTINUE(); } else { @@ -5856,8 +5868,8 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY) ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]); ZEND_VM_CONTINUE(); } else { - EG(exception) = EX(delayed_exception); - EX(delayed_exception) = NULL; + EG(exception) = Z_OBJ_P(fast_call); + Z_OBJ_P(fast_call) = NULL; if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) { ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]); ZEND_VM_CONTINUE(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 5210484370..dc3ee25c52 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 { @@ -1218,6 +1214,7 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER } if (op_num < EX(func)->op_array.try_catch_array[i].finally_op) { finally_op_num = EX(func)->op_array.try_catch_array[i].finally_op; + finally_op_end = EX(func)->op_array.try_catch_array[i].finally_end; } if (op_num >= EX(func)->op_array.try_catch_array[i].finally_op && op_num < EX(func)->op_array.try_catch_array[i].finally_end) { @@ -1264,40 +1261,47 @@ 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); + zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var); + + if (Z_OBJ_P(fast_call)) { + zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call) TSRMLS_CC); } - EX(delayed_exception) = EG(exception); + Z_OBJ_P(fast_call) = EG(exception); EG(exception) = NULL; - EX(fast_ret) = NULL; + fast_call->u2.lineno = (uint32_t)-1; ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[finally_op_num]); ZEND_VM_CONTINUE(); } else if (catch_op_num) { if (finally_op_end && catch_op_num > finally_op_end) { /* we are going out of current finally scope */ - if (EX(delayed_exception)) { - zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC); - EX(delayed_exception) = NULL; + zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var); + + if (Z_OBJ_P(fast_call)) { + zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call) TSRMLS_CC); + Z_OBJ_P(fast_call) = NULL; } } ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op_num]); ZEND_VM_CONTINUE(); } else { - if (EX(delayed_exception)) { - zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC); - EX(delayed_exception) = NULL; + if (finally_op_end) { + zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var); + + if (Z_OBJ_P(fast_call)) { + zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call) TSRMLS_CC); + Z_OBJ_P(fast_call) = NULL; + } } if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) { return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -1348,10 +1352,14 @@ static int ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS static int ZEND_FASTCALL ZEND_DISCARD_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - if (EX(delayed_exception) != NULL) { + USE_OPLINE + zval *fast_call = EX_VAR(opline->op1.var); + + /* check for delayed exception */ + if (Z_OBJ_P(fast_call) != NULL) { /* discard the previously thrown exception */ - OBJ_RELEASE(EX(delayed_exception)); - EX(delayed_exception) = NULL; + OBJ_RELEASE(Z_OBJ_P(fast_call)); + Z_OBJ_P(fast_call) = NULL; } ZEND_VM_NEXT_OPCODE(); @@ -1360,6 +1368,7 @@ static int ZEND_FASTCALL ZEND_DISCARD_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLE static int ZEND_FASTCALL ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *fast_call = EX_VAR(opline->result.var); if ((opline->extended_value & ZEND_FAST_CALL_FROM_CATCH) && UNEXPECTED(EG(prev_exception) != NULL)) { @@ -1367,18 +1376,24 @@ static int ZEND_FASTCALL ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]); ZEND_VM_CONTINUE(); } - EX(fast_ret) = opline; - EX(delayed_exception) = NULL; + /* set no delayed exception */ + Z_OBJ_P(fast_call) = NULL; + /* set return address */ + fast_call->u2.lineno = opline - EX(func)->op_array.opcodes; ZEND_VM_SET_OPCODE(opline->op1.jmp_addr); ZEND_VM_CONTINUE(); } static int ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - if (EX(fast_ret)) { - ZEND_VM_SET_OPCODE(EX(fast_ret) + 1); - if ((EX(fast_ret)->extended_value & ZEND_FAST_CALL_FROM_FINALLY)) { - EX(fast_ret) = &EX(func)->op_array.opcodes[EX(fast_ret)->op2.opline_num]; + USE_OPLINE + zval *fast_call = EX_VAR(opline->op1.var); + + if (fast_call->u2.lineno != (uint32_t)-1) { + const zend_op *fast_ret = EX(func)->op_array.opcodes + fast_call->u2.lineno; + ZEND_VM_SET_OPCODE(fast_ret + 1); + if (fast_ret->extended_value & ZEND_FAST_CALL_FROM_FINALLY) { + fast_call->u2.lineno = fast_ret->op2.opline_num; } ZEND_VM_CONTINUE(); } else { @@ -1389,8 +1404,8 @@ static int ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]); ZEND_VM_CONTINUE(); } else { - EG(exception) = EX(delayed_exception); - EX(delayed_exception) = NULL; + EG(exception) = Z_OBJ_P(fast_call); + Z_OBJ_P(fast_call) = NULL; if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) { ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]); ZEND_VM_CONTINUE(); @@ -10251,9 +10266,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(); } |
