From 3941294ccffe0b93fcf72462a60f8a934f9b7ece Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 18 Jul 2025 13:29:22 +0200 Subject: [PATCH] Skip bailout for unwind and graceful exit in zend_throw_exception_internal() Fixes GH-18619 --- Zend/tests/bug62763.phpt | 8 +++++--- Zend/tests/gh18619.phpt | 20 ++++++++++++++++++++ Zend/zend_exceptions.c | 10 +++++++--- 3 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 Zend/tests/gh18619.phpt diff --git a/Zend/tests/bug62763.phpt b/Zend/tests/bug62763.phpt index e74438dca6a8d..452be725a302f 100644 --- a/Zend/tests/bug62763.phpt +++ b/Zend/tests/bug62763.phpt @@ -7,17 +7,19 @@ class test1 { register_shutdown_function(array($this, 'shutdown')); } public function shutdown() { - exit(__METHOD__); + exit(static::class . '::' . __FUNCTION__ . "\n"); } } class test2 extends test1 { public function __destruct() { - exit (__METHOD__); + exit(static::class . '::' . __FUNCTION__ . "\n"); } } new test1; new test2; ?> --EXPECT-- -test1::shutdowntest2::__destruct +test1::shutdown +test2::shutdown +test2::__destruct diff --git a/Zend/tests/gh18619.phpt b/Zend/tests/gh18619.phpt new file mode 100644 index 0000000000000..54d4e8590de97 --- /dev/null +++ b/Zend/tests/gh18619.phpt @@ -0,0 +1,20 @@ +--TEST-- +Gh-18619: exit() from error handler should not trigger bailout +--FILE-- + +--EXPECT-- +string(3) "foo" diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 99c4a48a9482f..df30ffb697ebc 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -210,9 +210,13 @@ ZEND_API ZEND_COLD void zend_throw_exception_internal(zend_object *exception) /* return; } if (EG(exception)) { - if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF - && !zend_is_unwind_exit(EG(exception)) - && !zend_is_graceful_exit(EG(exception))) { + if (zend_is_unwind_exit(EG(exception)) + || zend_is_graceful_exit(EG(exception))) { + /* Stack is fully unwound, clear the unwind exit. */ + zend_exception_error(EG(exception), E_ERROR); + return; + } + if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) { zend_user_exception_handler(); if (EG(exception)) { zend_exception_error(EG(exception), E_ERROR);