diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2018-01-13 11:04:26 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2018-01-13 11:04:26 +0100 |
commit | 8c07170ddbe28d8cc31e71f0ceb94fc4ac329657 (patch) | |
tree | 72ca8d2ee9b51139aa0f8fc6b48b1e4cb9062a97 /Zend/zend_generators.c | |
parent | cab0a814bdbfc653754f74b42056c38bdf4fbadb (diff) | |
download | php-git-8c07170ddbe28d8cc31e71f0ceb94fc4ac329657.tar.gz |
Fix generator GC if yield from parent chain does not reach root
Parents may be unlinked while another generator sharing part of the
chain is running. As such, we cannot assume that the parent chain
goes all the way to the root. Instead walk backwards from root to
leaf, like we also do during destruction.
Diffstat (limited to 'Zend/zend_generators.c')
-rw-r--r-- | Zend/zend_generators.c | 14 |
1 files changed, 7 insertions, 7 deletions
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index a932f405e2..9242269906 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -276,9 +276,9 @@ static uint32_t calc_gc_buffer_size(zend_generator *generator) /* {{{ */ /* Yield from root references */ if (generator->node.children == 0) { - zend_generator *child = generator, *root = generator->node.ptr.root; - while (root != child) { - child = child->node.parent; + zend_generator *root = generator->node.ptr.root; + while (root != generator) { + root = zend_generator_get_child(&root->node, generator); size++; } } @@ -341,10 +341,10 @@ static HashTable *zend_generator_get_gc(zval *object, zval **table, int *n) /* { } if (generator->node.children == 0) { - zend_generator *child = generator, *root = generator->node.ptr.root; - while (root != child) { - child = child->node.parent; - ZVAL_OBJ(gc_buffer++, &child->std); + zend_generator *root = generator->node.ptr.root; + while (root != generator) { + ZVAL_OBJ(gc_buffer++, &root->std); + root = zend_generator_get_child(&root->node, generator); } } |