]> granicus.if.org Git - php/commitdiff
Fix arginfo leak when using disabled_classes
authorNikita Popov <nikita.ppv@gmail.com>
Fri, 23 Aug 2019 14:58:34 +0000 (16:58 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Fri, 23 Aug 2019 15:00:59 +0000 (17:00 +0200)
Also remove the hack where scope is set to NULL in order to make
free_internal_arg_info work. Instead explicitly call it for class
methods.

This fixes the asan build for Zend/tests/bug77494.phpt.

Zend/zend_API.c
Zend/zend_opcode.c

index 177a5d5b03535de1ef6761b205ee22a2a3ee7e3f..89e9c9d8490e11ce816f51f8e241fdf0c8d9e3e4 100644 (file)
@@ -2856,6 +2856,7 @@ ZEND_API int zend_disable_class(char *class_name, size_t class_name_length) /* {
 {
        zend_class_entry *disabled_class;
        zend_string *key;
+       zend_function *fn;
 
        key = zend_string_alloc(class_name_length, 0);
        zend_str_tolower_copy(ZSTR_VAL(key), class_name, class_name_length);
@@ -2864,8 +2865,16 @@ ZEND_API int zend_disable_class(char *class_name, size_t class_name_length) /* {
        if (!disabled_class) {
                return FAILURE;
        }
+
        INIT_CLASS_ENTRY_INIT_METHODS((*disabled_class), disabled_class_new);
        disabled_class->create_object = display_disabled_class;
+
+       ZEND_HASH_FOREACH_PTR(&disabled_class->function_table, fn) {
+               if ((fn->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) &&
+                       fn->common.scope == disabled_class) {
+                       zend_free_internal_arg_info(&fn->internal_function);
+               }
+       } ZEND_HASH_FOREACH_END();
        zend_hash_clean(&disabled_class->function_table);
        return SUCCESS;
 }
index a62d3db4770f51824790caa3c9081445ed2d2938..ff6bcfd9c417e07a38da370179dec1fcfd2d0e0e 100644 (file)
@@ -104,7 +104,7 @@ ZEND_API void destroy_zend_function(zend_function *function)
 
 void zend_free_internal_arg_info(zend_internal_function *function) {
        if ((function->fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) &&
-               !function->scope && function->arg_info) {
+               function->arg_info) {
 
                uint32_t i;
                uint32_t num_args = function->num_args + 1;
@@ -135,7 +135,10 @@ ZEND_API void zend_function_dtor(zval *zv)
                ZEND_ASSERT(function->common.function_name);
                zend_string_release_ex(function->common.function_name, 1);
 
-               zend_free_internal_arg_info(&function->internal_function);
+               /* For methods this will be called explicitly. */
+               if (!function->common.scope) {
+                       zend_free_internal_arg_info(&function->internal_function);
+               }
 
                if (!(function->common.fn_flags & ZEND_ACC_ARENA_ALLOCATED)) {
                        pefree(function, 1);
@@ -352,8 +355,7 @@ ZEND_API void destroy_zend_class(zval *zv)
                        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_free_internal_arg_info(&fn->internal_function);
                                }
                        } ZEND_HASH_FOREACH_END();