Skip to content

Commit 18f1587

Browse files
committed
Merge branch 'PHP-8.1'
* PHP-8.1: Fix GH-7958: Nested CallbackFilterIterator is leaking memory
2 parents 7d8e3da + fb70460 commit 18f1587

File tree

3 files changed

+53
-1
lines changed

3 files changed

+53
-1
lines changed

Zend/tests/gh7958.phpt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
--TEST--
2+
GH-7958 (Nested CallbackFilterIterator is leaking memory)
3+
--FILE--
4+
<?php
5+
class Action
6+
{
7+
public \Iterator $iterator;
8+
9+
public function __construct(array $data)
10+
{
11+
$this->iterator = new ArrayIterator($data);
12+
echo '-- c ' . spl_object_id($this) . "\n";
13+
}
14+
15+
public function __destruct()
16+
{
17+
echo '-- d ' . spl_object_id($this) . "\n";
18+
}
19+
20+
public function filter()
21+
{
22+
$this->iterator = new \CallbackFilterIterator($this->iterator, fn() => true);
23+
$this->iterator->rewind();
24+
}
25+
}
26+
27+
$action = new Action(['a', 'b']);
28+
$action->filter();
29+
$action->filter();
30+
print_r(iterator_to_array($action->iterator));
31+
$action = null;
32+
gc_collect_cycles();
33+
echo "==DONE==\n";
34+
?>
35+
--EXPECT--
36+
-- c 1
37+
Array
38+
(
39+
[0] => a
40+
[1] => b
41+
)
42+
-- d 1
43+
==DONE==

Zend/zend_interfaces.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ ZEND_API void zend_user_it_rewind(zend_object_iterator *_iter)
181181
}
182182
/* }}} */
183183

184+
ZEND_API HashTable *zend_user_it_get_gc(zend_object_iterator *_iter, zval **table, int *n)
185+
{
186+
zend_user_iterator *iter = (zend_user_iterator*)_iter;
187+
*table = &iter->it.data;
188+
*n = 1;
189+
return NULL;
190+
}
191+
184192
static const zend_object_iterator_funcs zend_interface_iterator_funcs_iterator = {
185193
zend_user_it_dtor,
186194
zend_user_it_valid,
@@ -189,7 +197,7 @@ static const zend_object_iterator_funcs zend_interface_iterator_funcs_iterator =
189197
zend_user_it_move_forward,
190198
zend_user_it_rewind,
191199
zend_user_it_invalidate_current,
192-
NULL, /* get_gc */
200+
zend_user_it_get_gc,
193201
};
194202

195203
/* {{{ zend_user_it_get_iterator */

Zend/zend_interfaces.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ ZEND_API void zend_user_it_get_current_key(zend_object_iterator *_iter, zval *ke
5555
ZEND_API zval *zend_user_it_get_current_data(zend_object_iterator *_iter);
5656
ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter);
5757
ZEND_API void zend_user_it_invalidate_current(zend_object_iterator *_iter);
58+
ZEND_API HashTable *zend_user_it_get_gc(zend_object_iterator *_iter, zval **table, int *n);
5859

5960
ZEND_API void zend_user_it_new_iterator(zend_class_entry *ce, zval *object, zval *iterator);
6061
ZEND_API zend_object_iterator *zend_user_it_get_new_iterator(zend_class_entry *ce, zval *object, int by_ref);

0 commit comments

Comments
 (0)