File tree Expand file tree Collapse file tree 3 files changed +79
-0
lines changed
Expand file tree Collapse file tree 3 files changed +79
-0
lines changed Original file line number Diff line number Diff line change 1+ --TEST--
2+ OSS-Fuzz #471533782: Infinite loop in GC destructor fiber
3+ --FILE--
4+ <?php
5+
6+ class Cycle {
7+ public $ self ;
8+ public function __construct () {
9+ $ this ->self = $ this ;
10+ }
11+ public function __destruct () {
12+ try {
13+ Fiber::suspend ();
14+ } finally {
15+ throw new Exception ();
16+ }
17+ }
18+ }
19+
20+ $ f = new Fiber (function () {
21+ new Cycle ();
22+ gc_collect_cycles ();
23+ });
24+ $ f ->start ();
25+
26+ ?>
27+ --EXPECTF--
28+ Fatal error: Uncaught Exception in %s:%d
29+ Stack trace:
30+ #0 [internal function]: Cycle->__destruct()
31+ #1 [internal function]: gc_destructor_fiber()
32+ #2 {main}
33+ thrown in %s on line %d
Original file line number Diff line number Diff line change 1+ --TEST--
2+ OSS-Fuzz #471533782: Infinite loop in GC destructor fiber
3+ --FILE--
4+ <?php
5+
6+ class Cycle {
7+ public $ self ;
8+ public function __construct () {
9+ $ this ->self = $ this ;
10+ }
11+ public function __destruct () {
12+ try {
13+ Fiber::suspend ();
14+ } finally {
15+ Fiber::suspend ();
16+ }
17+ }
18+ }
19+
20+ $ f = new Fiber (function () {
21+ new Cycle ();
22+ gc_collect_cycles ();
23+ });
24+ $ f ->start ();
25+
26+ ?>
27+ --EXPECTF--
28+ Fatal error: Uncaught FiberError: Cannot suspend in a force-closed fiber in %s:%d
29+ Stack trace:
30+ #0 %s(%d): Fiber::suspend()
31+ #1 [internal function]: Cycle->__destruct()
32+ #2 [internal function]: gc_destructor_fiber()
33+ #3 {main}
34+ thrown in %s on line %d
Original file line number Diff line number Diff line change 7676#include "zend_types.h"
7777#include "zend_weakrefs.h"
7878#include "zend_string.h"
79+ #include "zend_exceptions.h"
7980
8081#ifndef GC_BENCH
8182# define GC_BENCH 0
@@ -1887,6 +1888,8 @@ static zend_never_inline void gc_call_destructors_in_fiber(uint32_t end)
18871888 zend_fiber_resume (fiber , NULL , NULL );
18881889 }
18891890
1891+ zend_object * exception = NULL ;
1892+
18901893 for (;;) {
18911894 /* At this point, fiber has executed until suspension */
18921895 GC_TRACE ("resumed from destructor fiber" );
@@ -1900,6 +1903,13 @@ static zend_never_inline void gc_call_destructors_in_fiber(uint32_t end)
19001903 /* We do not own the fiber anymore. It may be collected if the
19011904 * application does not reference it. */
19021905 zend_object_release (& fiber -> std );
1906+ if (EG (exception )) {
1907+ if (exception ) {
1908+ zend_exception_set_previous (EG (exception ), exception );
1909+ }
1910+ exception = EG (exception );
1911+ EG (exception ) = NULL ;
1912+ }
19031913 fiber = gc_create_destructor_fiber ();
19041914 continue ;
19051915 } else {
@@ -1908,6 +1918,8 @@ static zend_never_inline void gc_call_destructors_in_fiber(uint32_t end)
19081918 break ;
19091919 }
19101920 }
1921+
1922+ EG (exception ) = exception ;
19111923}
19121924
19131925ZEND_API int zend_gc_collect_cycles (void )
You can’t perform that action at this time.
0 commit comments