From d4ff572271b2baafd7625c9ef27f9e54cf21e7b6 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Mon, 9 Oct 2023 11:46:55 +0300 Subject: [PATCH 1/2] Fix GH-11121: ReflectionFiber segfault --- Zend/zend_fibers.c | 4 ++ .../tests/ReflectionFiber_bug_gh11121_1.phpt | 62 ++++++++++++++++++ .../tests/ReflectionFiber_bug_gh11121_2.phpt | 63 +++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 ext/reflection/tests/ReflectionFiber_bug_gh11121_1.phpt create mode 100644 ext/reflection/tests/ReflectionFiber_bug_gh11121_2.phpt diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 59aa63ba21b43..3d0e55f436a68 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -388,6 +388,10 @@ ZEND_API void zend_fiber_switch_context(zend_fiber_transfer *transfer) zend_observer_fiber_switch_notify(from, to); + if (from->kind == zend_ce_fiber) { + zend_fiber_from_context(from)->execute_data = EG(current_execute_data); + } + zend_fiber_capture_vm_state(&state); to->status = ZEND_FIBER_STATUS_RUNNING; diff --git a/ext/reflection/tests/ReflectionFiber_bug_gh11121_1.phpt b/ext/reflection/tests/ReflectionFiber_bug_gh11121_1.phpt new file mode 100644 index 0000000000000..de0c9abec9ee5 --- /dev/null +++ b/ext/reflection/tests/ReflectionFiber_bug_gh11121_1.phpt @@ -0,0 +1,62 @@ +--TEST-- +GH-11121: Segfault when using ReflectionFiber +--FILE-- +getTrace()); + }))->start(); +} + +$f = new Fiber(function() { f(); max(...[1,2,3,4,5,6,7,8,9,10,11,12]); g(); }); +$f->start(); +$f->resume(); + +?> +--EXPECTF-- +array(3) { + [0]=> + array(7) { + ["file"]=> + string(%d) "%sReflectionFiber_bug_gh11121_1.php" + ["line"]=> + int(10) + ["function"]=> + string(5) "start" + ["class"]=> + string(5) "Fiber" + ["object"]=> + object(Fiber)#3 (0) { + } + ["type"]=> + string(2) "->" + ["args"]=> + array(0) { + } + } + [1]=> + array(4) { + ["file"]=> + string(%d) "%sReflectionFiber_bug_gh11121_1.php" + ["line"]=> + int(13) + ["function"]=> + string(1) "g" + ["args"]=> + array(0) { + } + } + [2]=> + array(2) { + ["function"]=> + string(9) "{closure}" + ["args"]=> + array(0) { + } + } +} diff --git a/ext/reflection/tests/ReflectionFiber_bug_gh11121_2.phpt b/ext/reflection/tests/ReflectionFiber_bug_gh11121_2.phpt new file mode 100644 index 0000000000000..b7affb2ca0b1c --- /dev/null +++ b/ext/reflection/tests/ReflectionFiber_bug_gh11121_2.phpt @@ -0,0 +1,63 @@ +--TEST-- +GH-11121: Segfault when using ReflectionFiber +--FILE-- +getTrace()); + }))->start(); +} + +$f = new Fiber(function() { f(); g(); }); +$f->start(); +$f->resume(); + +?> +--EXPECTF-- +array(3) { + [0]=> + array(7) { + ["file"]=> + string(%d) "%sReflectionFiber_bug_gh11121_2.php" + ["line"]=> + int(11) + ["function"]=> + string(5) "start" + ["class"]=> + string(5) "Fiber" + ["object"]=> + object(Fiber)#3 (0) { + } + ["type"]=> + string(2) "->" + ["args"]=> + array(0) { + } + } + [1]=> + array(4) { + ["file"]=> + string(%d) "%sReflectionFiber_bug_gh11121_2.php" + ["line"]=> + int(14) + ["function"]=> + string(1) "g" + ["args"]=> + array(0) { + } + } + [2]=> + array(2) { + ["function"]=> + string(9) "{closure}" + ["args"]=> + array(0) { + } + } +} From eb0ebae55d5aa9e9238d520eca485bc95f3544c6 Mon Sep 17 00:00:00 2001 From: Aaron Piotrowski Date: Tue, 10 Oct 2023 08:33:04 -0500 Subject: [PATCH 2/2] Move setting execute_data into static zend_fiber API --- Zend/zend_fibers.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 3d0e55f436a68..c80d65868d37e 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -388,10 +388,6 @@ ZEND_API void zend_fiber_switch_context(zend_fiber_transfer *transfer) zend_observer_fiber_switch_notify(from, to); - if (from->kind == zend_ce_fiber) { - zend_fiber_from_context(from)->execute_data = EG(current_execute_data); - } - zend_fiber_capture_vm_state(&state); to->status = ZEND_FIBER_STATUS_RUNNING; @@ -558,6 +554,10 @@ static zend_always_inline zend_fiber_transfer zend_fiber_resume(zend_fiber *fibe { zend_fiber *previous = EG(active_fiber); + if (previous) { + previous->execute_data = EG(current_execute_data); + } + fiber->caller = EG(current_fiber_context); EG(active_fiber) = fiber; @@ -575,6 +575,7 @@ static zend_always_inline zend_fiber_transfer zend_fiber_suspend(zend_fiber *fib zend_fiber_context *caller = fiber->caller; fiber->previous = EG(current_fiber_context); fiber->caller = NULL; + fiber->execute_data = EG(current_execute_data); return zend_fiber_switch_to(caller, value, false); } @@ -745,7 +746,6 @@ ZEND_METHOD(Fiber, suspend) ZEND_ASSERT(fiber->context.status == ZEND_FIBER_STATUS_RUNNING || fiber->context.status == ZEND_FIBER_STATUS_SUSPENDED); - fiber->execute_data = EG(current_execute_data); fiber->stack_bottom->prev_execute_data = NULL; zend_fiber_transfer transfer = zend_fiber_suspend(fiber, value);