diff --git a/NEWS b/NEWS index 6726c114374..7ebec401c6e 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,9 @@ PHP NEWS - Core: . Fixed bug GH-8176 (Enum values in property initializers leak). (Bob) + . Fixed freeing of internal attribute arguments. (Bob) + . Fixed bug GH-8070 (memory leak of internal function attribute hash). + (Tim Düsterhus) - Intl: . Fixed bug GH-8115 (Can't catch arg type deprecation when instantiating Intl diff --git a/Zend/zend.c b/Zend/zend.c index f0b653a915d..ca6844dd09c 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -665,6 +665,22 @@ static void function_copy_ctor(zval *zv) /* {{{ */ } func->common.arg_info = new_arg_info + 1; } + if (old_func->common.attributes) { + zend_attribute *old_attr; + + func->common.attributes = NULL; + + ZEND_HASH_PACKED_FOREACH_PTR(old_func->common.attributes, old_attr) { + uint32_t i; + zend_attribute *attr; + + attr = zend_add_attribute(&func->common.attributes, old_attr->name, old_attr->argc, old_attr->flags, old_attr->offset, old_attr->lineno); + + for (i = 0 ; i < old_attr->argc; i++) { + ZVAL_DUP(&attr->args[i].value, &old_attr->args[i].value); + } + } ZEND_HASH_FOREACH_END(); + } } /* }}} */ diff --git a/Zend/zend_attributes.c b/Zend/zend_attributes.c index a9bf3811b37..a78434a4d24 100644 --- a/Zend/zend_attributes.c +++ b/Zend/zend_attributes.c @@ -187,6 +187,7 @@ ZEND_API bool zend_is_attribute_repeated(HashTable *attributes, zend_attribute * static void attr_free(zval *v) { zend_attribute *attr = Z_PTR_P(v); + bool persistent = attr->flags & ZEND_ATTRIBUTE_PERSISTENT; zend_string_release(attr->name); zend_string_release(attr->lcname); @@ -195,10 +196,14 @@ static void attr_free(zval *v) if (attr->args[i].name) { zend_string_release(attr->args[i].name); } - zval_ptr_dtor(&attr->args[i].value); + if (persistent) { + zval_internal_ptr_dtor(&attr->args[i].value); + } else { + zval_ptr_dtor(&attr->args[i].value); + } } - pefree(attr, attr->flags & ZEND_ATTRIBUTE_PERSISTENT); + pefree(attr, persistent); } ZEND_API zend_attribute *zend_add_attribute(HashTable **attributes, zend_string *name, uint32_t argc, uint32_t flags, uint32_t offset, uint32_t lineno) diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 9f97570fe2d..87fd7db5c08 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -156,6 +156,11 @@ ZEND_API void zend_function_dtor(zval *zv) /* For methods this will be called explicitly. */ if (!function->common.scope) { zend_free_internal_arg_info(&function->internal_function); + + if (function->common.attributes) { + zend_hash_release(function->common.attributes); + function->common.attributes = NULL; + } } if (!(function->common.fn_flags & ZEND_ACC_ARENA_ALLOCATED)) { @@ -433,11 +438,17 @@ ZEND_API void destroy_zend_class(zval *zv) zend_hash_destroy(&ce->properties_info); zend_string_release_ex(ce->name, 1); - /* TODO: eliminate this loop for classes without functions with arg_info */ + /* TODO: eliminate this loop for classes without functions with arg_info / attributes */ 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) { - zend_free_internal_arg_info(&fn->internal_function); + if (fn->common.scope == ce) { + if (fn->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) { + zend_free_internal_arg_info(&fn->internal_function); + } + + if (fn->common.attributes) { + zend_hash_release(fn->common.attributes); + fn->common.attributes = NULL; + } } } ZEND_HASH_FOREACH_END();