mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Expose inner dual_it iterator to GC
Moving the zend_iterator_dtor from dual_it_dtor to dual_it_free_storage exposed this GC leak in an existing test. Forward the result of the iterator get_gc to the dual_it get_gc.
This commit is contained in:
parent
64865c6092
commit
15fafcd664
3 changed files with 30 additions and 4 deletions
|
@ -1637,6 +1637,12 @@ ZEND_API void zend_get_gc_buffer_grow(zend_get_gc_buffer *gc_buffer) {
|
||||||
gc_buffer->cur = gc_buffer->start + old_capacity;
|
gc_buffer->cur = gc_buffer->start + old_capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZEND_API void zend_get_gc_buffer_add_zvals(zend_get_gc_buffer *gc_buffer, zval *zvs, size_t n) {
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
zend_get_gc_buffer_add_zval(gc_buffer, &zvs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void zend_get_gc_buffer_release() {
|
static void zend_get_gc_buffer_release() {
|
||||||
zend_get_gc_buffer *gc_buffer = &EG(get_gc_buffer);
|
zend_get_gc_buffer *gc_buffer = &EG(get_gc_buffer);
|
||||||
efree(gc_buffer->start);
|
efree(gc_buffer->start);
|
||||||
|
|
|
@ -93,6 +93,7 @@ typedef struct {
|
||||||
|
|
||||||
ZEND_API zend_get_gc_buffer *zend_get_gc_buffer_create(void);
|
ZEND_API zend_get_gc_buffer *zend_get_gc_buffer_create(void);
|
||||||
ZEND_API void zend_get_gc_buffer_grow(zend_get_gc_buffer *gc_buffer);
|
ZEND_API void zend_get_gc_buffer_grow(zend_get_gc_buffer *gc_buffer);
|
||||||
|
ZEND_API void zend_get_gc_buffer_add_zvals(zend_get_gc_buffer *gc_buffer, zval *zvs, size_t n);
|
||||||
|
|
||||||
static zend_always_inline void zend_get_gc_buffer_add_zval(
|
static zend_always_inline void zend_get_gc_buffer_add_zval(
|
||||||
zend_get_gc_buffer *gc_buffer, zval *zv) {
|
zend_get_gc_buffer *gc_buffer, zval *zv) {
|
||||||
|
@ -114,6 +115,15 @@ static zend_always_inline void zend_get_gc_buffer_add_obj(
|
||||||
gc_buffer->cur++;
|
gc_buffer->cur++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static zend_always_inline void zend_get_gc_buffer_add_ht(
|
||||||
|
zend_get_gc_buffer *gc_buffer, HashTable *ht) {
|
||||||
|
if (UNEXPECTED(gc_buffer->cur == gc_buffer->end)) {
|
||||||
|
zend_get_gc_buffer_grow(gc_buffer);
|
||||||
|
}
|
||||||
|
ZVAL_ARR(gc_buffer->cur, ht);
|
||||||
|
gc_buffer->cur++;
|
||||||
|
}
|
||||||
|
|
||||||
static zend_always_inline void zend_get_gc_buffer_use(
|
static zend_always_inline void zend_get_gc_buffer_use(
|
||||||
zend_get_gc_buffer *gc_buffer, zval **table, int *n) {
|
zend_get_gc_buffer *gc_buffer, zval **table, int *n) {
|
||||||
*table = gc_buffer->start;
|
*table = gc_buffer->start;
|
||||||
|
|
|
@ -2079,10 +2079,6 @@ static void spl_dual_it_dtor(zend_object *_object)
|
||||||
zend_objects_destroy_object(_object);
|
zend_objects_destroy_object(_object);
|
||||||
|
|
||||||
spl_dual_it_free(object);
|
spl_dual_it_free(object);
|
||||||
|
|
||||||
if (object->inner.iterator) {
|
|
||||||
zend_iterator_dtor(object->inner.iterator);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
@ -2091,6 +2087,9 @@ static void spl_dual_it_free_storage(zend_object *_object)
|
||||||
{
|
{
|
||||||
spl_dual_it_object *object = spl_dual_it_from_obj(_object);
|
spl_dual_it_object *object = spl_dual_it_from_obj(_object);
|
||||||
|
|
||||||
|
if (object->inner.iterator) {
|
||||||
|
zend_iterator_dtor(object->inner.iterator);
|
||||||
|
}
|
||||||
|
|
||||||
if (!Z_ISUNDEF(object->inner.zobject)) {
|
if (!Z_ISUNDEF(object->inner.zobject)) {
|
||||||
zval_ptr_dtor(&object->inner.zobject);
|
zval_ptr_dtor(&object->inner.zobject);
|
||||||
|
@ -2137,6 +2136,17 @@ static HashTable *spl_dual_it_get_gc(zend_object *obj, zval **table, int *n)
|
||||||
spl_dual_it_object *object = spl_dual_it_from_obj(obj);
|
spl_dual_it_object *object = spl_dual_it_from_obj(obj);
|
||||||
zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create();
|
zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create();
|
||||||
|
|
||||||
|
if (object->inner.iterator && object->inner.iterator->funcs->get_gc) {
|
||||||
|
zval *inner_table;
|
||||||
|
int inner_n;
|
||||||
|
HashTable *inner_ht = object->inner.iterator->funcs->get_gc(
|
||||||
|
object->inner.iterator, &inner_table, &inner_n);
|
||||||
|
zend_get_gc_buffer_add_zvals(gc_buffer, inner_table, inner_n);
|
||||||
|
if (inner_ht) {
|
||||||
|
zend_get_gc_buffer_add_ht(gc_buffer, inner_ht);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!Z_ISUNDEF(object->inner.zobject)) {
|
if (!Z_ISUNDEF(object->inner.zobject)) {
|
||||||
zend_get_gc_buffer_add_zval(gc_buffer, &object->inner.zobject);
|
zend_get_gc_buffer_add_zval(gc_buffer, &object->inner.zobject);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue