Skip to content

Commit 0adbf9c

Browse files
authored
Fix memory leak in fiber constructor by throwing an error (#9098)
1 parent 9dcb0bd commit 0adbf9c

File tree

3 files changed

+59
-2
lines changed

3 files changed

+59
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Multiple calls to constructor are prevented after fiber terminated
3+
--FILE--
4+
<?php
5+
6+
$fiber = new Fiber(function () {
7+
return 123;
8+
});
9+
10+
var_dump($fiber->start());
11+
var_dump($fiber->getReturn());
12+
13+
$fiber->__construct(function () {
14+
return 321;
15+
});
16+
17+
?>
18+
--EXPECTF--
19+
NULL
20+
int(123)
21+
22+
Fatal error: Uncaught FiberError: Cannot call constructor twice in %scall-to-ctor-of-terminated-fiber.php:%d
23+
Stack trace:
24+
#0 %scall-to-ctor-of-terminated-fiber.php(%d): Fiber->__construct(Object(Closure))
25+
#1 {main}
26+
thrown in %scall-to-ctor-of-terminated-fiber.php on line %d
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Multiple calls to constructor are prevented
3+
--FILE--
4+
<?php
5+
6+
$fiber = new Fiber(function () {
7+
return 123;
8+
});
9+
10+
$fiber->__construct(function () {
11+
return 321;
12+
});
13+
14+
?>
15+
--EXPECTF--
16+
Fatal error: Uncaught FiberError: Cannot call constructor twice in %smultiple-calls-to-ctor.php:%d
17+
Stack trace:
18+
#0 %smultiple-calls-to-ctor.php(%d): Fiber->__construct(Object(Closure))
19+
#1 {main}
20+
thrown in %smultiple-calls-to-ctor.php on line %d

Zend/zend_fibers.c

+13-2
Original file line numberDiff line numberDiff line change
@@ -647,12 +647,23 @@ static HashTable *zend_fiber_object_gc(zend_object *object, zval **table, int *n
647647

648648
ZEND_METHOD(Fiber, __construct)
649649
{
650-
zend_fiber *fiber = (zend_fiber *) Z_OBJ_P(ZEND_THIS);
650+
zend_fcall_info fci;
651+
zend_fcall_info_cache fcc;
651652

652653
ZEND_PARSE_PARAMETERS_START(1, 1)
653-
Z_PARAM_FUNC(fiber->fci, fiber->fci_cache)
654+
Z_PARAM_FUNC(fci, fcc)
654655
ZEND_PARSE_PARAMETERS_END();
655656

657+
zend_fiber *fiber = (zend_fiber *) Z_OBJ_P(ZEND_THIS);
658+
659+
if (UNEXPECTED(fiber->context.status != ZEND_FIBER_STATUS_INIT || Z_TYPE(fiber->fci.function_name) != IS_UNDEF)) {
660+
zend_throw_error(zend_ce_fiber_error, "Cannot call constructor twice");
661+
RETURN_THROWS();
662+
}
663+
664+
fiber->fci = fci;
665+
fiber->fci_cache = fcc;
666+
656667
// Keep a reference to closures or callable objects while the fiber is running.
657668
Z_TRY_ADDREF(fiber->fci.function_name);
658669
}

0 commit comments

Comments
 (0)