From d3eeeb688204320c9825924bc300901470cdb87b Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 5 Jun 2020 10:29:49 +0200 Subject: [PATCH] Don't leak attributes on internal classes Also add zend_hash_release() API to complement zend_array_release(), because the latter is specific to non-persistent zval arrays. --- Zend/zend_hash.h | 12 ++++++++++++ Zend/zend_opcode.c | 13 ++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index d2b6ab2c71a..294a9c2c263 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -324,6 +324,7 @@ static zend_always_inline void zend_hash_iterators_update(HashTable *ht, HashPos } } +/* For regular arrays (non-persistent, storing zvals). */ static zend_always_inline void zend_array_release(zend_array *array) { if (!(GC_FLAGS(array) & IS_ARRAY_IMMUTABLE)) { @@ -333,6 +334,17 @@ static zend_always_inline void zend_array_release(zend_array *array) } } +/* For general hashes (possibly persistent, storing any kind of value). */ +static zend_always_inline void zend_hash_release(zend_array *array) +{ + if (!(GC_FLAGS(array) & IS_ARRAY_IMMUTABLE)) { + if (GC_DELREF(array) == 0) { + zend_hash_destroy(array); + pefree(array, GC_FLAGS(array) & IS_ARRAY_PERSISTENT); + } + } +} + END_EXTERN_C() #define ZEND_INIT_SYMTABLE(ht) \ diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 5c71d884474..b9337ad8974 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -319,7 +319,7 @@ ZEND_API void destroy_zend_class(zval *zv) zend_string_release_ex(prop_info->doc_comment, 0); } if (prop_info->attributes) { - zend_array_release(prop_info->attributes); + zend_hash_release(prop_info->attributes); } zend_type_release(prop_info->type, /* persistent */ 0); } @@ -337,7 +337,7 @@ ZEND_API void destroy_zend_class(zval *zv) zend_string_release_ex(c->doc_comment, 0); } if (c->attributes) { - zend_array_release(c->attributes); + zend_hash_release(c->attributes); } } } ZEND_HASH_FOREACH_END(); @@ -358,7 +358,7 @@ ZEND_API void destroy_zend_class(zval *zv) zend_string_release_ex(ce->info.user.doc_comment, 0); } if (ce->attributes) { - zend_array_release(ce->attributes); + zend_hash_release(ce->attributes); } if (ce->num_traits > 0) { @@ -412,7 +412,7 @@ ZEND_API void destroy_zend_class(zval *zv) zend_string_release_ex(c->doc_comment, 1); } if (c->attributes) { - zend_array_release(c->attributes); + zend_hash_release(c->attributes); } } free(c); @@ -428,6 +428,9 @@ ZEND_API void destroy_zend_class(zval *zv) if (ce->properties_info_table) { free(ce->properties_info_table); } + if (ce->attributes) { + zend_hash_release(ce->attributes); + } free(ce); break; } @@ -497,7 +500,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array) zend_string_release_ex(op_array->doc_comment, 0); } if (op_array->attributes) { - zend_array_release(op_array->attributes); + zend_hash_release(op_array->attributes); } if (op_array->live_range) { efree(op_array->live_range);