diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2020-07-01 12:03:13 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2020-07-01 15:17:26 +0200 |
commit | 271bc689ea9211821363e289accb23bb965aa5eb (patch) | |
tree | a3180532e6e6992ea6b15ca3bce0f0b992087c5f /Zend | |
parent | 312201dce4daca2770fd507af4a9a541bfe83fc0 (diff) | |
download | php-git-271bc689ea9211821363e289accb23bb965aa5eb.tar.gz |
Add iterator get_gc function for generators
Closes GH-5787.
Diffstat (limited to 'Zend')
-rw-r--r-- | Zend/tests/generators/iterator_wrapper_leak.phpt | 33 | ||||
-rw-r--r-- | Zend/zend_generators.c | 10 |
2 files changed, 42 insertions, 1 deletions
diff --git a/Zend/tests/generators/iterator_wrapper_leak.phpt b/Zend/tests/generators/iterator_wrapper_leak.phpt new file mode 100644 index 0000000000..bc0f34e9c8 --- /dev/null +++ b/Zend/tests/generators/iterator_wrapper_leak.phpt @@ -0,0 +1,33 @@ +--TEST-- +A generator iterator wrapper involved in a cycle should not leak +--FILE-- +<?php + +class Test { + public function method() { + $this->gen1 = (function () { + yield 1; + yield 2; + yield 3; + })(); + $gen2 = function() { + foreach ($this->gen1 as $x) { + echo "$x\n"; + yield $x; + } + }; + $this->gen2 = $gen2(); + foreach ($this->gen2 as $x) { + if ($x == 2) { + break; + } + } + } +} +(new Test)->method(); +gc_collect_cycles(); + +?> +--EXPECT-- +1 +2 diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index b1abbd7f9b..fe7066c0c8 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -1087,6 +1087,14 @@ static void zend_generator_iterator_rewind(zend_object_iterator *iterator) /* {{ } /* }}} */ +static HashTable *zend_generator_iterator_get_gc( + zend_object_iterator *iterator, zval **table, int *n) +{ + *table = &iterator->data; + *n = 1; + return NULL; +} + static const zend_object_iterator_funcs zend_generator_iterator_functions = { zend_generator_iterator_dtor, zend_generator_iterator_valid, @@ -1095,7 +1103,7 @@ static const zend_object_iterator_funcs zend_generator_iterator_functions = { zend_generator_iterator_move_forward, zend_generator_iterator_rewind, NULL, - NULL, /* get_gc */ + zend_generator_iterator_get_gc, }; zend_object_iterator *zend_generator_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */ |