diff --git a/NEWS b/NEWS index 062265576af7b..74816c94a2906 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,9 @@ PHP NEWS . It is now possible to use reference assign on WeakMap without the key needing to be present beforehand. (ndossche) . Added `clamp()`. (kylekatarnls, thinkverse) + . Fix OSS-Fuzz #429429090 (Failed assertion on unset() with uninitialized + container). (ilutov) + . Fixed GH-20564 (Don't call autoloaders with pending exception). (ilutov) - Date: . Update timelib to 2022.16. (Derick) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 748549e085b88..2132006540c40 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -54,6 +54,8 @@ PHP 8.6 INTERNALS UPGRADE NOTES ZEND_ACC_USER_ARG_INFO flag was set. . Added zend_ast_call_get_args() to fetch the argument node from any call node. + . The zend_exception_save() and zend_exception_restore() functions were + removed. ======================== 2. Build system changes diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 54670c804d006..9b5561e7fbe23 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -3840,7 +3840,7 @@ static zend_always_inline zend_result _zend_update_type_info( tmp &= ~MAY_BE_RC1; } if (opline->opcode == ZEND_FETCH_STATIC_PROP_IS) { - tmp |= MAY_BE_UNDEF; + tmp |= MAY_BE_NULL; } } UPDATE_SSA_TYPE(tmp, ssa_op->result_def); diff --git a/Zend/tests/gh20564.phpt b/Zend/tests/gh20564.phpt new file mode 100644 index 0000000000000..53311d952de71 --- /dev/null +++ b/Zend/tests/gh20564.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-20564: Don't call autoloaders with pending exception +--CREDITS-- +Viet Hoang Luu (@vi3tL0u1s) +--FILE-- +test(); +} catch (Throwable $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +array_map(): Argument #1 ($callback) must be a valid callback or null, class "B" not found diff --git a/Zend/tests/oss-fuzz-471486164-001.phpt b/Zend/tests/oss-fuzz-471486164-001.phpt new file mode 100644 index 0000000000000..a48a56398c1e1 --- /dev/null +++ b/Zend/tests/oss-fuzz-471486164-001.phpt @@ -0,0 +1,22 @@ +--TEST-- +OSS-Fuzz #471486164: get_property_ptr_ptr() on uninitialized hooked property +--FILE-- + $this->a; + set { $this->a = &$value; } + } + public $x = 1; +} + +$proxy = (new ReflectionClass(C::class))->newLazyProxy(function ($proxy) { + $proxy->a = 1; + return new C; +}); +var_dump($proxy->x); + +?> +--EXPECT-- +int(1) diff --git a/Zend/tests/oss-fuzz-471486164-002.phpt b/Zend/tests/oss-fuzz-471486164-002.phpt new file mode 100644 index 0000000000000..688dd76122018 --- /dev/null +++ b/Zend/tests/oss-fuzz-471486164-002.phpt @@ -0,0 +1,26 @@ +--TEST-- +OSS-Fuzz #471486164: get_property_ptr_ptr() on uninitialized hooked property +--FILE-- + $this->a; + set { + global $ref; + $this->a = &$ref; + } + } +} + +$ref = 1; +$proxy = new C; +$proxy->a = 1; +var_dump($proxy->a); +$ref++; +var_dump($proxy->a); + +?> +--EXPECT-- +int(1) +int(2) diff --git a/Zend/tests/oss_fuzz_429429090.phpt b/Zend/tests/oss_fuzz_429429090.phpt new file mode 100644 index 0000000000000..d5279c2806ac6 --- /dev/null +++ b/Zend/tests/oss_fuzz_429429090.phpt @@ -0,0 +1,20 @@ +--TEST-- +OSS-Fuzz #429429090: FETCH_OBJ_UNSET IS_UNDEF result +--FILE-- +x[0]->prop); +unset($c->x[0]->prop); +isset(C::$y[0]->prop); +unset(C::$y[0]->prop); + +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/oss_fuzz_438780145.phpt b/Zend/tests/oss_fuzz_438780145.phpt new file mode 100644 index 0000000000000..4c6936a69a019 --- /dev/null +++ b/Zend/tests/oss_fuzz_438780145.phpt @@ -0,0 +1,27 @@ +--TEST-- +OSS-Fuzz #438780145: Nested finally with repeated return type check may uaf +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught TypeError: test(): Return value must be of type int, string returned in %s:%d +Stack trace: +#0 %s(%d): test() +#1 {main} + thrown in %s on line %d diff --git a/Zend/zend.c b/Zend/zend.c index c46c8e9ada86c..d2be69a757690 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1082,7 +1082,6 @@ void zend_startup(zend_utility_functions *utility_functions) /* {{{ */ #endif zend_enum_startup(); - zend_closure_startup(); } /* }}} */ @@ -1979,7 +1978,6 @@ ZEND_API zend_result zend_execute_script(int type, zval *retval, zend_file_handl zend_result ret = SUCCESS; if (op_array) { zend_execute(op_array, retval); - zend_exception_restore(); if (UNEXPECTED(EG(exception))) { if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) { zend_user_exception_handler(); diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 05b6862044816..43eefbeff9dac 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -878,8 +878,6 @@ ZEND_API void zend_create_fake_closure(zval *res, zend_function *func, zend_clas } /* }}} */ -static zend_arg_info trampoline_arg_info[1]; - void zend_closure_from_frame(zval *return_value, const zend_execute_data *call) { /* {{{ */ zval instance; zend_internal_function trampoline; @@ -904,9 +902,7 @@ void zend_closure_from_frame(zval *return_value, const zend_execute_data *call) trampoline.function_name = mptr->common.function_name; trampoline.scope = mptr->common.scope; trampoline.doc_comment = NULL; - if (trampoline.fn_flags & ZEND_ACC_VARIADIC) { - trampoline.arg_info = trampoline_arg_info; - } + trampoline.arg_info = mptr->common.arg_info; trampoline.attributes = mptr->common.attributes; zend_free_trampoline(mptr); @@ -943,11 +939,3 @@ void zend_closure_bind_var_ex(zval *closure_zv, uint32_t offset, zval *val) /* { ZVAL_COPY_VALUE(var, val); } /* }}} */ - -void zend_closure_startup(void) -{ - /* __call and __callStatic name the arguments "$arguments" in the docs. */ - trampoline_arg_info[0].name = zend_string_init_interned("arguments", strlen("arguments"), true); - trampoline_arg_info[0].type = (zend_type)ZEND_TYPE_INIT_CODE(IS_MIXED, false, _ZEND_ARG_INFO_FLAGS(false, 1, 0)); - trampoline_arg_info[0].default_value = NULL; -} diff --git a/Zend/zend_closures.h b/Zend/zend_closures.h index a118044c6e248..8bea4ffb051e8 100644 --- a/Zend/zend_closures.h +++ b/Zend/zend_closures.h @@ -28,7 +28,6 @@ BEGIN_EXTERN_C() #define ZEND_CLOSURE_OBJECT(op_array) \ ((zend_object*)((char*)(op_array) - sizeof(zend_object))) -void zend_closure_startup(void); void zend_register_closure_ce(void); void zend_closure_bind_var(zval *closure_zv, zend_string *var_name, zval *var); void zend_closure_bind_var_ex(zval *closure_zv, uint32_t offset, zval *val); diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 191d8f7fe6aec..52e3ab0092540 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -145,31 +145,6 @@ void zend_exception_set_previous(zend_object *exception, zend_object *add_previo } /* }}} */ -void zend_exception_save(void) /* {{{ */ -{ - if (EG(prev_exception)) { - zend_exception_set_previous(EG(exception), EG(prev_exception)); - } - if (EG(exception)) { - EG(prev_exception) = EG(exception); - } - EG(exception) = NULL; -} -/* }}} */ - -void zend_exception_restore(void) /* {{{ */ -{ - if (EG(prev_exception)) { - if (EG(exception)) { - zend_exception_set_previous(EG(exception), EG(prev_exception)); - } else { - EG(exception) = EG(prev_exception); - } - EG(prev_exception) = NULL; - } -} -/* }}} */ - static zend_always_inline bool is_handle_exception_set(void) { zend_execute_data *execute_data = EG(current_execute_data); return !execute_data @@ -241,10 +216,6 @@ ZEND_API ZEND_COLD void zend_throw_exception_internal(zend_object *exception) /* ZEND_API void zend_clear_exception(void) /* {{{ */ { zend_object *exception; - if (EG(prev_exception)) { - OBJ_RELEASE(EG(prev_exception)); - EG(prev_exception) = NULL; - } if (!EG(exception)) { return; } diff --git a/Zend/zend_exceptions.h b/Zend/zend_exceptions.h index 24d9f4efd80a3..e5a6be2f32feb 100644 --- a/Zend/zend_exceptions.h +++ b/Zend/zend_exceptions.h @@ -41,8 +41,6 @@ extern ZEND_API zend_class_entry *zend_ce_unhandled_match_error; extern ZEND_API zend_class_entry *zend_ce_request_parse_body_exception; ZEND_API void zend_exception_set_previous(zend_object *exception, zend_object *add_previous); -ZEND_API void zend_exception_save(void); -ZEND_API void zend_exception_restore(void); ZEND_API ZEND_COLD void zend_throw_exception_internal(zend_object *exception); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 570aac4a8dbfb..e95931276ef51 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1315,6 +1315,7 @@ ZEND_API bool zend_internal_call_should_throw(const zend_function *fbc, zend_exe if ((fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) && !zend_verify_internal_arg_types(fbc, call)) { + zend_clear_exception(); return 1; } @@ -3626,6 +3627,9 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c } else if (UNEXPECTED(Z_ISERROR_P(ptr))) { ZVAL_ERROR(result); goto end; + } else if (type == BP_VAR_UNSET && UNEXPECTED(Z_TYPE_P(ptr) == IS_UNDEF)) { + ZVAL_NULL(result); + goto end; } ZVAL_INDIRECT(result, ptr); @@ -3777,6 +3781,11 @@ static zend_never_inline zval* zend_fetch_static_property_address_ex(zend_proper return NULL; } + if (UNEXPECTED(Z_TYPE_P(result) == IS_UNDEF) + && (fetch_type == BP_VAR_IS || fetch_type == BP_VAR_UNSET)) { + return NULL; + } + *prop_info = property_info; if (EXPECTED(op1_type == IS_CONST) diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index e134d3d496b6d..69337e27fd530 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -176,7 +176,6 @@ void init_executor(void) /* {{{ */ ZEND_ATOMIC_BOOL_INIT(&EG(timed_out), false); EG(exception) = NULL; - EG(prev_exception) = NULL; EG(fake_scope) = NULL; EG(trampoline).common.function_name = NULL; @@ -1268,9 +1267,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string * zend_long previous_lineno = EG(lineno_override); EG(filename_override) = NULL; EG(lineno_override) = -1; - zend_exception_save(); ce = zend_autoload(autoload_name, lc_name); - zend_exception_restore(); EG(filename_override) = previous_filename; EG(lineno_override) = previous_lineno; diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index ef81ae5faaf25..f09b81acb315b 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -255,7 +255,7 @@ struct _zend_executor_globals { zend_objects_store objects_store; zend_lazy_objects_store lazy_objects_store; - zend_object *exception, *prev_exception; + zend_object *exception; const zend_op *opline_before_exception; zend_op exception_op[3]; diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index 1e26ddbd99199..5a8a78cc3bd7b 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -2765,7 +2765,8 @@ skip_escape_conversion: zend_ptr_stack_reverse_apply(¤t_state.heredoc_label_stack, copy_heredoc_label_stack); - zend_exception_save(); + zend_object *prev_exception = EG(exception); + EG(exception) = NULL; while (heredoc_nesting_level) { zval zv; int retval; @@ -2794,7 +2795,7 @@ skip_escape_conversion: heredoc_nesting_level = 0; } } - zend_exception_restore(); + EG(exception) = prev_exception; if ( (first_token == T_VARIABLE diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 88b7b1112d7b1..07ff4de9244a4 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1398,6 +1398,7 @@ ZEND_API zval *zend_std_get_property_ptr_ptr(zend_object *zobj, zend_string *nam property_offset = zend_get_property_offset(zobj->ce, name, (zobj->ce->__get != NULL), cache_slot, &prop_info); if (EXPECTED(IS_VALID_PROPERTY_OFFSET(property_offset))) { +try_again: retval = OBJ_PROP(zobj, property_offset); if (UNEXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) { if (EXPECTED(!zobj->ce->__get) || @@ -1477,7 +1478,15 @@ ZEND_API zval *zend_std_get_property_ptr_ptr(zend_object *zobj, zend_string *nam } retval = zend_hash_add(zobj->properties, name, &EG(uninitialized_zval)); } - } else if (!IS_HOOKED_PROPERTY_OFFSET(property_offset) && zobj->ce->__get == NULL) { + } else if (IS_HOOKED_PROPERTY_OFFSET(property_offset)) { + if (!(prop_info->flags & ZEND_ACC_VIRTUAL) && !zend_should_call_hook(prop_info, zobj)) { + property_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto try_again; + } + } else if (zobj->ce->__get == NULL) { retval = &EG(error_zval); } @@ -1685,7 +1694,6 @@ ZEND_API ZEND_ATTRIBUTE_NONNULL zend_function *zend_get_call_trampoline_func( * The low bit must be zero, to not be interpreted as a MAP_PTR offset. */ static const void *dummy = (void*)(intptr_t)2; - static const zend_arg_info arg_info[1] = {{0}}; if (EXPECTED(EG(trampoline).common.function_name == NULL)) { func = &EG(trampoline).op_array; @@ -1732,7 +1740,7 @@ ZEND_API ZEND_ATTRIBUTE_NONNULL zend_function *zend_get_call_trampoline_func( func->prop_info = NULL; func->num_args = 0; func->required_num_args = 0; - func->arg_info = (zend_arg_info *) arg_info; + func->arg_info = zend_call_trampoline_arginfo; return (zend_function*)func; } @@ -2576,6 +2584,7 @@ ZEND_API const zend_object_handlers std_object_handlers = { }; void zend_object_handlers_startup(void) { - zend_call_trampoline_arginfo[0].name = ZSTR_KNOWN(ZEND_STR_ARGS); + zend_call_trampoline_arginfo[0].name = ZSTR_KNOWN(ZEND_STR_ARGUMENTS); + zend_call_trampoline_arginfo[0].type = (zend_type)ZEND_TYPE_INIT_CODE(IS_MIXED, false, _ZEND_ARG_INFO_FLAGS(false, 1, 0)); zend_property_hook_arginfo[0].name = ZSTR_KNOWN(ZEND_STR_VALUE); } diff --git a/Zend/zend_string.h b/Zend/zend_string.h index fc7705ff78650..97386ea6bad64 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -563,6 +563,7 @@ EMPTY_SWITCH_DEFAULT_CASE() _(ZEND_STR_OBJECT_OPERATOR, "->") \ _(ZEND_STR_PAAMAYIM_NEKUDOTAYIM, "::") \ _(ZEND_STR_ARGS, "args") \ + _(ZEND_STR_ARGUMENTS, "arguments") \ _(ZEND_STR_UNKNOWN, "unknown") \ _(ZEND_STR_UNKNOWN_CAPITALIZED, "Unknown") \ _(ZEND_STR_EXIT, "exit") \ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index de8a34678c83a..9840bf2804072 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1866,7 +1866,7 @@ ZEND_VM_INLINE_HELPER(zend_fetch_static_prop_helper, ANY, ANY, int type) &prop_info, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, type == BP_VAR_W ? opline->extended_value : 0 OPLINE_CC EXECUTE_DATA_CC); if (UNEXPECTED(!prop)) { - ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS)); + ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS) || (type == BP_VAR_UNSET)); prop = &EG(uninitialized_zval); } else if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) && (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) @@ -4797,10 +4797,8 @@ ZEND_VM_COLD_CONST_HANDLER(108, ZEND_THROW, CONST|TMPVAR|CV, ANY) } } while (0); - zend_exception_save(); Z_TRY_ADDREF_P(value); zend_throw_exception_object(value); - zend_exception_restore(); FREE_OP1(); HANDLE_EXCEPTION(); } @@ -4813,7 +4811,6 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, JMP_ADDR, LAST_CATCH|CACHE_SLOT) SAVE_OPLINE(); /* Check whether an exception has been thrown, if not, jump over code */ - zend_exception_restore(); if (EG(exception) == NULL) { ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } @@ -8624,6 +8621,10 @@ ZEND_VM_HANDLER(159, ZEND_DISCARD_EXCEPTION, ANY, ANY) zval *return_value = EX_VAR(EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2.var); zval_ptr_dtor(return_value); + /* Clear return value in case we hit both DISCARD_EXCEPTION and + * zend_dispatch_try_catch_finally_helper, which will free the return + * value again. See OSS-Fuzz #438780145. */ + ZVAL_NULL(return_value); } /* cleanup delayed exception */ diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 9105f18ff544a..7aa0296aa4265 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -895,7 +895,7 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET zend_fetch_static_prop_helper_ &prop_info, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, type == BP_VAR_W ? opline->extended_value : 0 OPLINE_CC EXECUTE_DATA_CC); if (UNEXPECTED(!prop)) { - ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS)); + ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS) || (type == BP_VAR_UNSET)); prop = &EG(uninitialized_zval); } else if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) && (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) @@ -3498,6 +3498,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DISCARD_EXCEP zval *return_value = EX_VAR(EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2.var); zval_ptr_dtor(return_value); + /* Clear return value in case we hit both DISCARD_EXCEPTION and + * zend_dispatch_try_catch_finally_helper, which will free the return + * value again. See OSS-Fuzz #438780145. */ + ZVAL_NULL(return_value); } /* cleanup delayed exception */ @@ -5121,10 +5125,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ } } while (0); - zend_exception_save(); Z_TRY_ADDREF_P(value); zend_throw_exception_object(value); - zend_exception_restore(); HANDLE_EXCEPTION(); @@ -5138,7 +5140,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CATCH_SPEC_CO SAVE_OPLINE(); /* Check whether an exception has been thrown, if not, jump over code */ - zend_exception_restore(); if (EG(exception) == NULL) { ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } @@ -15716,10 +15717,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_THROW_SPEC_TM } } while (0); - zend_exception_save(); Z_TRY_ADDREF_P(value); zend_throw_exception_object(value); - zend_exception_restore(); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } @@ -41897,10 +41896,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_THROW_SPEC_CV } } while (0); - zend_exception_save(); Z_TRY_ADDREF_P(value); zend_throw_exception_object(value); - zend_exception_restore(); HANDLE_EXCEPTION(); @@ -59153,6 +59150,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DISCARD_EXCEPTION_ zval *return_value = EX_VAR(EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2.var); zval_ptr_dtor(return_value); + /* Clear return value in case we hit both DISCARD_EXCEPTION and + * zend_dispatch_try_catch_finally_helper, which will free the return + * value again. See OSS-Fuzz #438780145. */ + ZVAL_NULL(return_value); } /* cleanup delayed exception */ @@ -60776,10 +60777,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_THROW } } while (0); - zend_exception_save(); Z_TRY_ADDREF_P(value); zend_throw_exception_object(value); - zend_exception_restore(); HANDLE_EXCEPTION(); @@ -60793,7 +60792,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CATCH_SPEC_CONST_T SAVE_OPLINE(); /* Check whether an exception has been thrown, if not, jump over code */ - zend_exception_restore(); if (EG(exception) == NULL) { ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } @@ -71269,10 +71267,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_THROW_SPEC_TMPVAR_ } } while (0); - zend_exception_save(); Z_TRY_ADDREF_P(value); zend_throw_exception_object(value); - zend_exception_restore(); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } @@ -97350,10 +97346,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_THROW_SPEC_CV_TAIL } } while (0); - zend_exception_save(); Z_TRY_ADDREF_P(value); zend_throw_exception_object(value); - zend_exception_restore(); HANDLE_EXCEPTION(); @@ -112155,7 +112149,7 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET zend_fetch_static_prop_helper_ &prop_info, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, type == BP_VAR_W ? opline->extended_value : 0 OPLINE_CC EXECUTE_DATA_CC); if (UNEXPECTED(!prop)) { - ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS)); + ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS) || (type == BP_VAR_UNSET)); prop = &EG(uninitialized_zval); } else if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) && (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 7acb14b778f8d..f4134212bc4eb 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -4663,7 +4663,6 @@ static zend_result accel_preload(const char *config, bool in_child) zend_destroy_file_handle(&file_handle); if (op_array) { zend_execute(op_array, NULL); - zend_exception_restore(); if (UNEXPECTED(EG(exception))) { if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) { zend_user_exception_handler(); diff --git a/ext/standard/tests/general_functions/gh20840.phpt b/ext/standard/tests/general_functions/gh20840.phpt index 839b4728be189..ac0440a3bcdfb 100644 --- a/ext/standard/tests/general_functions/gh20840.phpt +++ b/ext/standard/tests/general_functions/gh20840.phpt @@ -28,11 +28,20 @@ for ($i = 0; $i < 50000; $i++) { $node = $newNode; } +$buffer = ''; +ob_start(function ($chunk) use (&$buffer) { + $buffer .= $chunk; + $buffer = preg_replace('(\s*object\(Node\)#\d+ \(\d+\) \{\s*)', '', $buffer); + $buffer = preg_replace('(\s*\["next"\]=>\s*)', '', $buffer); + $buffer = preg_replace('(\s*\}\s*)', '', $buffer); +}); var_dump($firstNode); +ob_end_flush(); +echo $buffer; while ($next = $firstNode->next) { $firstNode->next = $next->next; } ?> ---EXPECTREGEX-- -^object\(Node\)#\d+ \(\d+\).*(nesting level too deep|["\s}]*)$ +--EXPECT-- +nesting level too deep diff --git a/sapi/fuzzer/fuzzer-execute-common.h b/sapi/fuzzer/fuzzer-execute-common.h index 338c771e551a3..ef2ff4ee79bab 100644 --- a/sapi/fuzzer/fuzzer-execute-common.h +++ b/sapi/fuzzer/fuzzer-execute-common.h @@ -134,7 +134,6 @@ ZEND_ATTRIBUTE_UNUSED static void create_file(void) { ZEND_ATTRIBUTE_UNUSED static void opcache_invalidate(void) { steps_left = MAX_STEPS; - zend_exception_save(); zval retval, args[2]; zend_function *fn = zend_hash_str_find_ptr(CG(function_table), ZEND_STRL("opcache_invalidate")); ZEND_ASSERT(fn != NULL); @@ -145,5 +144,4 @@ ZEND_ATTRIBUTE_UNUSED static void opcache_invalidate(void) { ZEND_ASSERT(Z_TYPE(retval) == IS_TRUE); zval_ptr_dtor(&args[0]); zval_ptr_dtor(&retval); - zend_exception_restore(); } diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 7215888cb25ec..9566c1abd4eec 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -716,10 +716,6 @@ static inline void phpdbg_handle_exception(void) /* {{{ */ phpdbg_writeln("%s", ZSTR_VAL(msg)); zend_string_release(msg); - if (EG(prev_exception)) { - OBJ_RELEASE(EG(prev_exception)); - EG(prev_exception) = 0; - } OBJ_RELEASE(ex); EG(opline_before_exception) = NULL; @@ -876,7 +872,6 @@ PHPDBG_COMMAND(run) /* {{{ */ } zend_end_try(); if (restore) { - zend_exception_restore(); zend_try { zend_try_exception_handler(); PHPDBG_G(in_execution) = 1;