From 51f15da1f1c3d9c84b5ab6ff950d66d8067d541a Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 15 Nov 2025 15:14:25 +0000 Subject: [PATCH 1/3] Fix GH-20483: ASAN stack overflow with small fiber.stack_size INI value. --- Zend/zend.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Zend/zend.c b/Zend/zend.c index b4a084b1f95c7..be8c91c5c9c50 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -239,11 +239,29 @@ static ZEND_INI_MH(OnUpdateReservedStackSize) /* {{{ */ static ZEND_INI_MH(OnUpdateFiberStackSize) /* {{{ */ { if (new_value) { + // taken from zend_get_fiber_stack_size() + static size_t page_size = 0; + if (!page_size) { + page_size = zend_get_page_size(); + if (!page_size || (page_size & (page_size - 1))) { + page_size = 4096; + } + } + const zend_long minimum_fiber_stack_size = page_size + ZEND_FIBER_GUARD_PAGES * page_size +#ifdef __SANITIZE_ADDRESS__ + // necessary correction due to ASAN redzones + * 6 +#endif + ; zend_long tmp = zend_ini_parse_quantity_warn(new_value, entry->name); if (tmp < 0) { zend_error(E_WARNING, "fiber.stack_size must be a positive number"); return FAILURE; } + if (UNEXPECTED(tmp < minimum_fiber_stack_size)) { + php_error_docref(NULL, E_WARNING, "fiber.stack_size must be equal or greater than " ZEND_LONG_FMT, minimum_fiber_stack_size); + tmp = minimum_fiber_stack_size; + } EG(fiber_stack_size) = tmp; } else { EG(fiber_stack_size) = ZEND_FIBER_DEFAULT_C_STACK_SIZE; From b92286c40209dd55f83f6589bf9c7143aaf7d477 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 15 Nov 2025 15:48:59 +0000 Subject: [PATCH 2/3] feedback --- Zend/zend.c | 18 ------------------ Zend/zend_fibers.c | 7 ++++++- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/Zend/zend.c b/Zend/zend.c index be8c91c5c9c50..b4a084b1f95c7 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -239,29 +239,11 @@ static ZEND_INI_MH(OnUpdateReservedStackSize) /* {{{ */ static ZEND_INI_MH(OnUpdateFiberStackSize) /* {{{ */ { if (new_value) { - // taken from zend_get_fiber_stack_size() - static size_t page_size = 0; - if (!page_size) { - page_size = zend_get_page_size(); - if (!page_size || (page_size & (page_size - 1))) { - page_size = 4096; - } - } - const zend_long minimum_fiber_stack_size = page_size + ZEND_FIBER_GUARD_PAGES * page_size -#ifdef __SANITIZE_ADDRESS__ - // necessary correction due to ASAN redzones - * 6 -#endif - ; zend_long tmp = zend_ini_parse_quantity_warn(new_value, entry->name); if (tmp < 0) { zend_error(E_WARNING, "fiber.stack_size must be a positive number"); return FAILURE; } - if (UNEXPECTED(tmp < minimum_fiber_stack_size)) { - php_error_docref(NULL, E_WARNING, "fiber.stack_size must be equal or greater than " ZEND_LONG_FMT, minimum_fiber_stack_size); - tmp = minimum_fiber_stack_size; - } EG(fiber_stack_size) = tmp; } else { EG(fiber_stack_size) = ZEND_FIBER_DEFAULT_C_STACK_SIZE; diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 97b7cdcc911b7..d571a622e476b 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -207,7 +207,12 @@ static zend_fiber_stack *zend_fiber_stack_allocate(size_t size) { void *pointer; const size_t page_size = zend_fiber_get_page_size(); - const size_t minimum_stack_size = page_size + ZEND_FIBER_GUARD_PAGES * page_size; + const size_t minimum_stack_size = page_size + ZEND_FIBER_GUARD_PAGES * page_size +#ifdef __SANITIZE_ADDRESS__ + // necessary correction due to ASAN redzones + * 6 +#endif + ; if (size < minimum_stack_size) { zend_throw_exception_ex(NULL, 0, "Fiber stack size is too small, it needs to be at least %zu bytes", minimum_stack_size); From b24b903ba0f5ceadfd0fcacc8e4b14142b10abae Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 15 Nov 2025 15:52:30 +0000 Subject: [PATCH 3/3] add test --- Zend/tests/fibers/gh20483.phpt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 Zend/tests/fibers/gh20483.phpt diff --git a/Zend/tests/fibers/gh20483.phpt b/Zend/tests/fibers/gh20483.phpt new file mode 100644 index 0000000000000..e06cf87258ea1 --- /dev/null +++ b/Zend/tests/fibers/gh20483.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-20483 (ASAN stack overflow with small fiber.stack_size INI value) +--INI-- +fiber.stack_size=1024 +--FILE-- +start(); +} catch (Exception $e) { + echo $e->getMessage() . "\n"; +} +?> +--EXPECTF-- +Fiber stack size is too small, it needs to be at least %d bytes