Skip to content

Commit 5085352

Browse files
committed
Fix generator being a cycle to itself
1 parent ea1f300 commit 5085352

File tree

2 files changed

+49
-4
lines changed

2 files changed

+49
-4
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
Verify yield from on generators being properly cycle collected
3+
--FILE--
4+
<?php
5+
6+
function root() {
7+
global $gens; // create cyclic reference to root
8+
try {
9+
yield 1;
10+
} finally {
11+
var_dump($gens);
12+
}
13+
}
14+
15+
function gen($x) {
16+
global $gens;
17+
yield from $gens[] = $x ? gen(--$x) : root();
18+
}
19+
20+
$gen = $gens[] = gen(2);
21+
var_dump($gen->current());
22+
unset($gen, $gens);
23+
print "collect\n";
24+
gc_collect_cycles();
25+
print "end\n";
26+
27+
?>
28+
--EXPECT--
29+
int(1)
30+
collect
31+
array(4) {
32+
[0]=>
33+
object(Generator)#1 (0) {
34+
}
35+
[1]=>
36+
object(Generator)#2 (0) {
37+
}
38+
[2]=>
39+
object(Generator)#3 (0) {
40+
}
41+
[3]=>
42+
object(Generator)#4 (0) {
43+
}
44+
}
45+
end

Zend/zend_generators.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,10 @@ static uint32_t calc_gc_buffer_size(zend_generator *generator) /* {{{ */
220220

221221
/* Yield from root references */
222222
if (generator->node.children == 0) {
223-
zend_generator *root = generator->node.ptr.root;
224-
while (root != generator) {
223+
zend_generator *child = generator, *root = generator->node.ptr.root;
224+
while (root != child) {
225+
child = child->node.parent;
225226
size++;
226-
root = zend_generator_get_child(&root->node, generator);
227227
}
228228
}
229229
}
@@ -287,8 +287,8 @@ static HashTable *zend_generator_get_gc(zval *object, zval **table, int *n) /* {
287287
if (generator->node.children == 0) {
288288
zend_generator *child = generator, *root = generator->node.ptr.root;
289289
while (root != child) {
290-
ZVAL_OBJ(gc_buffer++, &child->std);
291290
child = child->node.parent;
291+
ZVAL_OBJ(gc_buffer++, &child->std);
292292
}
293293
}
294294

0 commit comments

Comments
 (0)