Skip to content

Add get_gc handler for iterators #5787

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions Zend/tests/generators/iterator_wrapper_leak.phpt
Original file line number Diff line number Diff line change
@@ -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
11 changes: 10 additions & 1 deletion Zend/zend_generators.c
Original file line number Diff line number Diff line change
Expand Up @@ -1087,14 +1087,23 @@ 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,
zend_generator_iterator_get_data,
zend_generator_iterator_get_key,
zend_generator_iterator_move_forward,
zend_generator_iterator_rewind,
NULL
NULL,
zend_generator_iterator_get_gc,
};

zend_object_iterator *zend_generator_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */
Expand Down
3 changes: 2 additions & 1 deletion Zend/zend_interfaces.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ static const zend_object_iterator_funcs zend_interface_iterator_funcs_iterator =
zend_user_it_get_current_key,
zend_user_it_move_forward,
zend_user_it_rewind,
zend_user_it_invalidate_current
zend_user_it_invalidate_current,
NULL, /* get_gc */
};

/* {{{ zend_user_it_get_iterator */
Expand Down
6 changes: 5 additions & 1 deletion Zend/zend_iterators.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,11 @@ static void iter_wrapper_dtor(zend_object *object)
}

static HashTable *iter_wrapper_get_gc(zend_object *object, zval **table, int *n) {
/* TODO: We need a get_gc iterator handler */
zend_object_iterator *iter = (zend_object_iterator*)object;
if (iter->funcs->get_gc) {
return iter->funcs->get_gc(iter, table, n);
}

*table = NULL;
*n = 0;
return NULL;
Expand Down
4 changes: 4 additions & 0 deletions Zend/zend_iterators.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ typedef struct _zend_object_iterator_funcs {

/* invalidate current value/key (optional, may be NULL) */
void (*invalidate_current)(zend_object_iterator *iter);

/* Expose owned values to GC.
* This has the same semantics as the corresponding object handler. */
HashTable *(*get_gc)(zend_object_iterator *iter, zval **table, int *n);
} zend_object_iterator_funcs;

struct _zend_object_iterator {
Expand Down
3 changes: 2 additions & 1 deletion Zend/zend_weakrefs.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,8 @@ static const zend_object_iterator_funcs zend_weakmap_iterator_funcs = {
zend_weakmap_iterator_get_current_key,
zend_weakmap_iterator_move_forward,
zend_weakmap_iterator_rewind,
NULL
NULL,
NULL, /* get_gc */
};

static zend_object_iterator *zend_weakmap_get_iterator(
Expand Down
3 changes: 2 additions & 1 deletion ext/com_dotnet/com_iterator.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ static const zend_object_iterator_funcs com_iter_funcs = {
com_iter_get_data,
com_iter_get_key,
com_iter_move_forwards,
NULL
NULL,
NULL, /* get_gc */
};

zend_object_iterator *php_com_iter_get(zend_class_entry *ce, zval *object, int by_ref)
Expand Down
3 changes: 2 additions & 1 deletion ext/com_dotnet/com_saproxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,8 @@ static const zend_object_iterator_funcs saproxy_iter_funcs = {
saproxy_iter_get_data,
saproxy_iter_get_key,
saproxy_iter_move_forwards,
NULL
NULL,
NULL, /* get_gc */
};


Expand Down
3 changes: 2 additions & 1 deletion ext/date/php_date.c
Original file line number Diff line number Diff line change
Expand Up @@ -1526,7 +1526,8 @@ static const zend_object_iterator_funcs date_period_it_funcs = {
date_period_it_current_key,
date_period_it_move_forward,
date_period_it_rewind,
date_period_it_invalidate_current
date_period_it_invalidate_current,
NULL, /* get_gc */
};

zend_object_iterator *date_object_period_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */
Expand Down
3 changes: 2 additions & 1 deletion ext/dom/dom_iterators.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,8 @@ static const zend_object_iterator_funcs php_dom_iterator_funcs = {
php_dom_iterator_current_key,
php_dom_iterator_move_forward,
NULL,
NULL
NULL,
NULL, /* get_gc */
};

zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */
Expand Down
3 changes: 2 additions & 1 deletion ext/ffi/ffi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1874,7 +1874,8 @@ static const zend_object_iterator_funcs zend_ffi_cdata_it_funcs = {
zend_ffi_cdata_it_get_current_key,
zend_ffi_cdata_it_move_forward,
zend_ffi_cdata_it_rewind,
NULL
NULL,
NULL, /* get_gc */
};

static zend_object_iterator *zend_ffi_cdata_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */
Expand Down
3 changes: 2 additions & 1 deletion ext/intl/resourcebundle/resourcebundle_iterator.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ static const zend_object_iterator_funcs resourcebundle_iterator_funcs = {
resourcebundle_iterator_key,
resourcebundle_iterator_step,
resourcebundle_iterator_reset,
resourcebundle_iterator_invalidate
resourcebundle_iterator_invalidate,
NULL, /* get_gc */
};
/* }}} */

Expand Down
3 changes: 2 additions & 1 deletion ext/mysqli/mysqli_result_iterator.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ const zend_object_iterator_funcs php_mysqli_result_iterator_funcs = {
php_mysqli_result_iterator_current_key,
php_mysqli_result_iterator_move_forward,
php_mysqli_result_iterator_rewind,
NULL
NULL,
NULL, /* get_gc */
};
/* }}} */
3 changes: 2 additions & 1 deletion ext/pdo/pdo_stmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -2304,7 +2304,8 @@ static const zend_object_iterator_funcs pdo_stmt_iter_funcs = {
pdo_stmt_iter_get_key,
pdo_stmt_iter_move_forwards,
NULL,
NULL
NULL,
NULL, /* get_gc */
};

zend_object_iterator *pdo_stmt_iter_get(zend_class_entry *ce, zval *object, int by_ref)
Expand Down
3 changes: 2 additions & 1 deletion ext/simplexml/simplexml.c
Original file line number Diff line number Diff line change
Expand Up @@ -2470,7 +2470,8 @@ static const zend_object_iterator_funcs php_sxe_iterator_funcs = { /* {{{ */
php_sxe_iterator_current_key,
php_sxe_iterator_move_forward,
php_sxe_iterator_rewind,
NULL
NULL,
NULL, /* get_gc */
};
/* }}} */

Expand Down
3 changes: 2 additions & 1 deletion ext/spl/spl_array.c
Original file line number Diff line number Diff line change
Expand Up @@ -1154,7 +1154,8 @@ static const zend_object_iterator_funcs spl_array_it_funcs = {
spl_array_it_get_current_key,
spl_array_it_move_forward,
spl_array_it_rewind,
NULL
NULL,
NULL, /* get_gc */
};

zend_object_iterator *spl_array_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */
Expand Down
6 changes: 4 additions & 2 deletions ext/spl/spl_directory.c
Original file line number Diff line number Diff line change
Expand Up @@ -1628,7 +1628,8 @@ static const zend_object_iterator_funcs spl_filesystem_dir_it_funcs = {
spl_filesystem_dir_it_current_key,
spl_filesystem_dir_it_move_forward,
spl_filesystem_dir_it_rewind,
NULL
NULL,
NULL, /* get_gc */
};
/* }}} */

Expand Down Expand Up @@ -1828,7 +1829,8 @@ static const zend_object_iterator_funcs spl_filesystem_tree_it_funcs = {
spl_filesystem_tree_it_current_key,
spl_filesystem_tree_it_move_forward,
spl_filesystem_tree_it_rewind,
NULL
NULL,
NULL, /* get_gc */
};
/* }}} */

Expand Down
3 changes: 2 additions & 1 deletion ext/spl/spl_dllist.c
Original file line number Diff line number Diff line change
Expand Up @@ -1334,7 +1334,8 @@ static const zend_object_iterator_funcs spl_dllist_it_funcs = {
spl_dllist_it_get_current_key,
spl_dllist_it_move_forward,
spl_dllist_it_rewind,
NULL
NULL,
NULL, /* get_gc */
}; /* }}} */

zend_object_iterator *spl_dllist_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */
Expand Down
3 changes: 2 additions & 1 deletion ext/spl/spl_fixedarray.c
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,8 @@ static const zend_object_iterator_funcs spl_fixedarray_it_funcs = {
spl_fixedarray_it_get_current_key,
spl_fixedarray_it_move_forward,
spl_fixedarray_it_rewind,
NULL
NULL,
NULL, /* get_gc */
};

zend_object_iterator *spl_fixedarray_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */
Expand Down
6 changes: 4 additions & 2 deletions ext/spl/spl_heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1068,7 +1068,8 @@ static const zend_object_iterator_funcs spl_heap_it_funcs = {
spl_heap_it_get_current_key,
spl_heap_it_move_forward,
spl_heap_it_rewind,
NULL
NULL,
NULL, /* get_gc */
};

static const zend_object_iterator_funcs spl_pqueue_it_funcs = {
Expand All @@ -1078,7 +1079,8 @@ static const zend_object_iterator_funcs spl_pqueue_it_funcs = {
spl_heap_it_get_current_key,
spl_heap_it_move_forward,
spl_heap_it_rewind,
NULL
NULL,
NULL, /* get_gc */
};

zend_object_iterator *spl_heap_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */
Expand Down
3 changes: 2 additions & 1 deletion ext/spl/spl_iterators.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,8 @@ static const zend_object_iterator_funcs spl_recursive_it_iterator_funcs = {
spl_recursive_it_get_current_key,
spl_recursive_it_move_forward,
spl_recursive_it_rewind,
NULL
NULL,
NULL, /* get_gc */
};

static zend_object_iterator *spl_recursive_it_get_iterator(zend_class_entry *ce, zval *zobject, int by_ref)
Expand Down