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.
This commit is contained in:
Nikita Popov 2020-06-05 10:29:49 +02:00
parent 8a7756c1b7
commit d3eeeb6882
2 changed files with 20 additions and 5 deletions

View File

@ -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) static zend_always_inline void zend_array_release(zend_array *array)
{ {
if (!(GC_FLAGS(array) & IS_ARRAY_IMMUTABLE)) { 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() END_EXTERN_C()
#define ZEND_INIT_SYMTABLE(ht) \ #define ZEND_INIT_SYMTABLE(ht) \

View File

@ -319,7 +319,7 @@ ZEND_API void destroy_zend_class(zval *zv)
zend_string_release_ex(prop_info->doc_comment, 0); zend_string_release_ex(prop_info->doc_comment, 0);
} }
if (prop_info->attributes) { if (prop_info->attributes) {
zend_array_release(prop_info->attributes); zend_hash_release(prop_info->attributes);
} }
zend_type_release(prop_info->type, /* persistent */ 0); 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); zend_string_release_ex(c->doc_comment, 0);
} }
if (c->attributes) { if (c->attributes) {
zend_array_release(c->attributes); zend_hash_release(c->attributes);
} }
} }
} ZEND_HASH_FOREACH_END(); } 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); zend_string_release_ex(ce->info.user.doc_comment, 0);
} }
if (ce->attributes) { if (ce->attributes) {
zend_array_release(ce->attributes); zend_hash_release(ce->attributes);
} }
if (ce->num_traits > 0) { 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); zend_string_release_ex(c->doc_comment, 1);
} }
if (c->attributes) { if (c->attributes) {
zend_array_release(c->attributes); zend_hash_release(c->attributes);
} }
} }
free(c); free(c);
@ -428,6 +428,9 @@ ZEND_API void destroy_zend_class(zval *zv)
if (ce->properties_info_table) { if (ce->properties_info_table) {
free(ce->properties_info_table); free(ce->properties_info_table);
} }
if (ce->attributes) {
zend_hash_release(ce->attributes);
}
free(ce); free(ce);
break; 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); zend_string_release_ex(op_array->doc_comment, 0);
} }
if (op_array->attributes) { if (op_array->attributes) {
zend_array_release(op_array->attributes); zend_hash_release(op_array->attributes);
} }
if (op_array->live_range) { if (op_array->live_range) {
efree(op_array->live_range); efree(op_array->live_range);