]> granicus.if.org Git - php/commitdiff
Fixed memry leaks (free arg_info of internal functions with type hints)
authorDmitry Stogov <dmitry@zend.com>
Tue, 12 Sep 2017 22:44:19 +0000 (01:44 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 12 Sep 2017 22:44:19 +0000 (01:44 +0300)
Zend/zend_opcode.c

index 394b610aa995e508b32a00ecb3c9c6196fe2abb3..aac18b94484e05f5b468d618330e35a454a5c0cd 100644 (file)
@@ -142,6 +142,23 @@ ZEND_API void zend_function_dtor(zval *zv)
                ZEND_ASSERT(function->type == ZEND_INTERNAL_FUNCTION);
                ZEND_ASSERT(function->common.function_name);
                zend_string_release(function->common.function_name);
+               if ((function->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) &&
+                   !function->common.scope && function->common.arg_info) {
+
+                       uint32_t i;
+                       uint32_t num_args = function->common.num_args + 1;
+                       zend_arg_info *arg_info = function->common.arg_info - 1;
+
+                       if (function->common.fn_flags & ZEND_ACC_VARIADIC) {
+                               num_args++;
+                       }
+                       for (i = 0 ; i < num_args; i++) {
+                               if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) {
+                                       zend_string_release(ZEND_TYPE_NAME(arg_info[i].type));
+                               }
+                       }
+                       free(arg_info);
+               }
                if (!(function->common.fn_flags & ZEND_ACC_ARENA_ALLOCATED)) {
                        pefree(function, 1);
                }
@@ -227,6 +244,7 @@ ZEND_API void destroy_zend_class(zval *zv)
 {
        zend_property_info *prop_info;
        zend_class_entry *ce = Z_PTR_P(zv);
+       zend_function *fn;
 
        if (--ce->refcount > 0) {
                return;
@@ -310,6 +328,13 @@ ZEND_API void destroy_zend_class(zval *zv)
                        }
                        zend_hash_destroy(&ce->properties_info);
                        zend_string_release(ce->name);
+                       ZEND_HASH_FOREACH_PTR(&ce->function_table, fn) {
+                               if ((fn->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) &&
+                                   fn->common.scope == ce) {
+                                       /* reset function scope to allow arg_info removing */
+                                       fn->common.scope = NULL;
+                               }
+                       } ZEND_HASH_FOREACH_END();
                        zend_hash_destroy(&ce->function_table);
                        if (zend_hash_num_elements(&ce->constants_table)) {
                                zend_class_constant *c;