Skip to content

Commit d15e9f7

Browse files
committed
Fix memory leak of function attribute hash table
==109253== 280 (56 direct, 224 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 4 ==109253== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==109253== by 0x6D9FA2: __zend_malloc (zend_alloc.c:3068) ==109253== by 0x745138: zend_add_attribute (zend_attributes.c:226) ==109253== by 0x6680D1: zend_add_parameter_attribute (zend_attributes.h:102) ==109253== by 0x66B787: zm_startup_zend_test (test.c:478) ==109253== by 0x7224CD: zend_startup_module_ex (zend_API.c:2202) ==109253== by 0x72252C: zend_startup_module_zval (zend_API.c:2217) ==109253== by 0x734288: zend_hash_apply (zend_hash.c:2011) ==109253== by 0x722C30: zend_startup_modules (zend_API.c:2328) ==109253== by 0x67409B: php_module_startup (main.c:2256) ==109253== by 0x88EDDE: php_cli_startup (php_cli.c:409) ==109253== by 0x890F61: main (php_cli.c:1334)
1 parent 8b1b6ae commit d15e9f7

File tree

5 files changed

+69
-1
lines changed

5 files changed

+69
-1
lines changed

Zend/zend_opcode.c

+6
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,12 @@ ZEND_API void zend_function_dtor(zval *zv)
153153
ZEND_ASSERT(function->common.function_name);
154154
zend_string_release_ex(function->common.function_name, 1);
155155

156+
if (function->common.attributes) {
157+
zend_hash_destroy(function->common.attributes);
158+
free(function->common.attributes);
159+
function->common.attributes = NULL;
160+
}
161+
156162
/* For methods this will be called explicitly. */
157163
if (!function->common.scope) {
158164
zend_free_internal_arg_info(&function->internal_function);

ext/zend_test/test.c

+22
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ static zend_class_entry *zend_test_class;
3737
static zend_class_entry *zend_test_child_class;
3838
static zend_class_entry *zend_test_trait;
3939
static zend_class_entry *zend_test_attribute;
40+
static zend_class_entry *zend_test_parameter_attribute;
4041
static zend_class_entry *zend_test_ns_foo_class;
4142
static zend_class_entry *zend_test_ns2_foo_class;
4243
static zend_class_entry *zend_test_ns2_ns_foo_class;
@@ -313,6 +314,17 @@ static ZEND_FUNCTION(namespaced_func)
313314
RETURN_TRUE;
314315
}
315316

317+
static ZEND_FUNCTION(zend_test_parameter_with_attribute)
318+
{
319+
zend_string *parameter;
320+
321+
ZEND_PARSE_PARAMETERS_START(1, 1)
322+
Z_PARAM_STR(parameter)
323+
ZEND_PARSE_PARAMETERS_END();
324+
325+
RETURN_TRUE;
326+
}
327+
316328
static zend_object *zend_test_class_new(zend_class_entry *class_type)
317329
{
318330
zend_object *obj = zend_objects_new(class_type);
@@ -460,6 +472,16 @@ PHP_MINIT_FUNCTION(zend_test)
460472
attr->validator = zend_attribute_validate_zendtestattribute;
461473
}
462474

475+
zend_test_parameter_attribute = register_class_ZendTestParameterAttribute();
476+
zend_internal_attribute_register(zend_test_parameter_attribute, ZEND_ATTRIBUTE_TARGET_PARAMETER);
477+
478+
zend_add_parameter_attribute(
479+
zend_hash_str_find_ptr(CG(function_table), "zend_test_parameter_with_attribute", sizeof("zend_test_parameter_with_attribute") - 1),
480+
0,
481+
zend_test_parameter_attribute->name,
482+
0
483+
);
484+
463485
zend_test_ns_foo_class = register_class_ZendTestNS_Foo();
464486
zend_test_ns2_foo_class = register_class_ZendTestNS2_Foo();
465487
zend_test_ns2_ns_foo_class = register_class_ZendTestNS2_ZendSubNS_Foo();

ext/zend_test/test.stub.php

+6
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ final class ZendTestAttribute {
4545

4646
}
4747

48+
final class ZendTestParameterAttribute {
49+
50+
}
51+
4852
enum ZendTestUnitEnum {
4953
case Foo;
5054
case Bar;
@@ -92,6 +96,8 @@ function zend_weakmap_remove(object $object): bool {}
9296
function zend_weakmap_dump(): array {}
9397

9498
function zend_get_unit_enum(): ZendTestUnitEnum {}
99+
100+
function zend_test_parameter_with_attribute(#[ZendTestParameterAttribute] string $parameter): bool {}
95101
}
96102

97103
namespace ZendTestNS {

ext/zend_test/test_arginfo.h

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: 7326163f8ce5340c12e74af72d47a8926eb39786 */
2+
* Stub hash: 1dd70fdfc8a3403a0cb6b0ef71b818cb17ec1602 */
33

44
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0)
55
ZEND_END_ARG_INFO()
@@ -71,6 +71,10 @@ ZEND_END_ARG_INFO()
7171
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_zend_get_unit_enum, 0, 0, ZendTestUnitEnum, 0)
7272
ZEND_END_ARG_INFO()
7373

74+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_parameter_with_attribute, 0, 1, _IS_BOOL, 0)
75+
ZEND_ARG_TYPE_INFO(0, parameter, IS_STRING, 0)
76+
ZEND_END_ARG_INFO()
77+
7478
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ZendTestNS2_ZendSubNS_namespaced_func, 0, 0, _IS_BOOL, 0)
7579
ZEND_END_ARG_INFO()
7680

@@ -116,6 +120,7 @@ static ZEND_FUNCTION(zend_weakmap_attach);
116120
static ZEND_FUNCTION(zend_weakmap_remove);
117121
static ZEND_FUNCTION(zend_weakmap_dump);
118122
static ZEND_FUNCTION(zend_get_unit_enum);
123+
static ZEND_FUNCTION(zend_test_parameter_with_attribute);
119124
static ZEND_FUNCTION(namespaced_func);
120125
static ZEND_METHOD(_ZendTestClass, is_object);
121126
static ZEND_METHOD(_ZendTestClass, __toString);
@@ -147,6 +152,7 @@ static const zend_function_entry ext_functions[] = {
147152
ZEND_FE(zend_weakmap_remove, arginfo_zend_weakmap_remove)
148153
ZEND_FE(zend_weakmap_dump, arginfo_zend_weakmap_dump)
149154
ZEND_FE(zend_get_unit_enum, arginfo_zend_get_unit_enum)
155+
ZEND_FE(zend_test_parameter_with_attribute, arginfo_zend_test_parameter_with_attribute)
150156
ZEND_NS_FE("ZendTestNS2\\ZendSubNS", namespaced_func, arginfo_ZendTestNS2_ZendSubNS_namespaced_func)
151157
ZEND_FE_END
152158
};
@@ -183,6 +189,11 @@ static const zend_function_entry class_ZendTestAttribute_methods[] = {
183189
};
184190

185191

192+
static const zend_function_entry class_ZendTestParameterAttribute_methods[] = {
193+
ZEND_FE_END
194+
};
195+
196+
186197
static const zend_function_entry class_ZendTestUnitEnum_methods[] = {
187198
ZEND_FE_END
188199
};
@@ -314,6 +325,17 @@ static zend_class_entry *register_class_ZendTestAttribute(void)
314325
return class_entry;
315326
}
316327

328+
static zend_class_entry *register_class_ZendTestParameterAttribute(void)
329+
{
330+
zend_class_entry ce, *class_entry;
331+
332+
INIT_CLASS_ENTRY(ce, "ZendTestParameterAttribute", class_ZendTestParameterAttribute_methods);
333+
class_entry = zend_register_internal_class_ex(&ce, NULL);
334+
class_entry->ce_flags |= ZEND_ACC_FINAL;
335+
336+
return class_entry;
337+
}
338+
317339
static zend_class_entry *register_class_ZendTestUnitEnum(void)
318340
{
319341
zend_class_entry *class_entry = zend_register_internal_enum("ZendTestUnitEnum", IS_UNDEF, class_ZendTestUnitEnum_methods);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
Verify that parameter attributes for native functions do not leak.
3+
--EXTENSIONS--
4+
zend_test
5+
--FILE--
6+
<?php
7+
8+
var_dump(zend_test_parameter_with_attribute("foo"));
9+
10+
?>
11+
--EXPECT--
12+
bool(true)

0 commit comments

Comments
 (0)