From dec78c80de4aef980ea97fe1139856059438ed43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Schr=C3=B6der?= Date: Fri, 22 Jul 2022 13:33:16 +0200 Subject: [PATCH] Fix memory leak in fiber constructor by throwing an error --- .../call-to-ctor-of-terminated-fiber.phpt | 26 +++++++++++++++++++ Zend/tests/fibers/multiple-calls-to-ctor.phpt | 20 ++++++++++++++ Zend/zend_fibers.c | 15 +++++++++-- 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 Zend/tests/fibers/call-to-ctor-of-terminated-fiber.phpt create mode 100644 Zend/tests/fibers/multiple-calls-to-ctor.phpt diff --git a/Zend/tests/fibers/call-to-ctor-of-terminated-fiber.phpt b/Zend/tests/fibers/call-to-ctor-of-terminated-fiber.phpt new file mode 100644 index 0000000000000..183932cafe630 --- /dev/null +++ b/Zend/tests/fibers/call-to-ctor-of-terminated-fiber.phpt @@ -0,0 +1,26 @@ +--TEST-- +Multiple calls to constructor are prevented after fiber terminated +--FILE-- +start()); +var_dump($fiber->getReturn()); + +$fiber->__construct(function () { + return 321; +}); + +?> +--EXPECTF-- +NULL +int(123) + +Fatal error: Uncaught FiberError: Cannot call constructor twice in %scall-to-ctor-of-terminated-fiber.php:%d +Stack trace: +#0 %scall-to-ctor-of-terminated-fiber.php(%d): Fiber->__construct(Object(Closure)) +#1 {main} + thrown in %scall-to-ctor-of-terminated-fiber.php on line %d diff --git a/Zend/tests/fibers/multiple-calls-to-ctor.phpt b/Zend/tests/fibers/multiple-calls-to-ctor.phpt new file mode 100644 index 0000000000000..28df144019fd4 --- /dev/null +++ b/Zend/tests/fibers/multiple-calls-to-ctor.phpt @@ -0,0 +1,20 @@ +--TEST-- +Multiple calls to constructor are prevented +--FILE-- +__construct(function () { + return 321; +}); + +?> +--EXPECTF-- +Fatal error: Uncaught FiberError: Cannot call constructor twice in %smultiple-calls-to-ctor.php:%d +Stack trace: +#0 %smultiple-calls-to-ctor.php(%d): Fiber->__construct(Object(Closure)) +#1 {main} + thrown in %smultiple-calls-to-ctor.php on line %d diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 1fec85528fbb3..c786e4aae8f8a 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -644,12 +644,23 @@ static HashTable *zend_fiber_object_gc(zend_object *object, zval **table, int *n ZEND_METHOD(Fiber, __construct) { - zend_fiber *fiber = (zend_fiber *) Z_OBJ_P(ZEND_THIS); + zend_fcall_info fci; + zend_fcall_info_cache fcc; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_FUNC(fiber->fci, fiber->fci_cache) + Z_PARAM_FUNC(fci, fcc) ZEND_PARSE_PARAMETERS_END(); + zend_fiber *fiber = (zend_fiber *) Z_OBJ_P(ZEND_THIS); + + if (UNEXPECTED(fiber->context.status != ZEND_FIBER_STATUS_INIT || Z_TYPE(fiber->fci.function_name) != IS_UNDEF)) { + zend_throw_error(zend_ce_fiber_error, "Cannot call constructor twice"); + RETURN_THROWS(); + } + + fiber->fci = fci; + fiber->fci_cache = fcc; + // Keep a reference to closures or callable objects while the fiber is running. Z_TRY_ADDREF(fiber->fci.function_name); }