From: Nikita Popov Date: Fri, 23 Aug 2019 14:58:34 +0000 (+0200) Subject: Fix arginfo leak when using disabled_classes X-Git-Tag: php-7.4.0RC1~52 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8807889ac280503d5cd1cd05804a6f278a40300e;p=php Fix arginfo leak when using disabled_classes 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. --- diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 177a5d5b03..89e9c9d849 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -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; } diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index a62d3db477..ff6bcfd9c4 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -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();