]> granicus.if.org Git - php/commitdiff
Don't leak attributes on internal classes
authorNikita Popov <nikita.ppv@gmail.com>
Fri, 5 Jun 2020 08:29:49 +0000 (10:29 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Fri, 5 Jun 2020 08:29:49 +0000 (10:29 +0200)
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
Zend/zend_opcode.c

index d2b6ab2c71a15a5250ef34f829a0329e66387b05..294a9c2c263894edc93642c8a1472905730ed4c8 100644 (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)
 {
        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)                                                         \
index 5c71d884474b86a4e875c3457cdd33c711fe3fc0..b9337ad89743d259e9b52cb213fb1ac18dcda4ef 100644 (file)
@@ -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);