summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-06-05 10:29:49 +0200
committerNikita Popov <nikita.ppv@gmail.com>2020-06-05 10:29:49 +0200
commitd3eeeb688204320c9825924bc300901470cdb87b (patch)
treeb9f92efa4c09470ec8ad115319525c72d13dd4ed
parent8a7756c1b7bba138c881b6e9802a2e9f31efcd91 (diff)
downloadphp-git-d3eeeb688204320c9825924bc300901470cdb87b.tar.gz
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.
-rw-r--r--Zend/zend_hash.h12
-rw-r--r--Zend/zend_opcode.c13
2 files changed, 20 insertions, 5 deletions
diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
index d2b6ab2c71..294a9c2c26 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 5c71d88447..b9337ad897 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);