Skip to content

Commit ac31e2e

Browse files
committed
Fix memory_leak in zend_test
Properly use globals init/shutdown to allocate the observer_observe_function_names hashtable instead of attempting to do everything in the ini changed handler
1 parent 1c9a49e commit ac31e2e

File tree

3 files changed

+28
-29
lines changed

3 files changed

+28
-29
lines changed

ext/zend_test/observer.c

+18-28
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ static zend_observer_fcall_handlers observer_fcall_init(zend_execute_data *execu
184184
} else if (fbc->common.function_name) {
185185
if (ZT_G(observer_observe_functions)) {
186186
return (zend_observer_fcall_handlers){observer_begin, observer_end};
187-
} else if (ZT_G(observer_observe_function_names) && zend_hash_exists(ZT_G(observer_observe_function_names), fbc->common.function_name)) {
187+
} else if (zend_hash_exists(ZT_G(observer_observe_function_names), fbc->common.function_name)) {
188188
return (zend_observer_fcall_handlers){observer_begin, observer_end};
189189
}
190190
} else {
@@ -259,40 +259,25 @@ static void fiber_suspend_observer(zend_fiber_context *from, zend_fiber_context
259259
static ZEND_INI_MH(zend_test_observer_OnUpdateCommaList)
260260
{
261261
zend_array **p = (zend_array **) ZEND_INI_GET_ADDR();
262-
if (stage != PHP_INI_STAGE_STARTUP && stage != PHP_INI_STAGE_SHUTDOWN && (ZT_G(observer_observe_all) || !*p)) {
263-
return FAILURE;
264-
}
265-
266262
zend_string *funcname;
267263
zend_function *func;
268-
if (*p) {
269-
if (EG(function_table)) {
270-
ZEND_HASH_FOREACH_STR_KEY(*p, funcname) {
271-
if ((func = zend_hash_find_ptr(EG(function_table), funcname))) {
272-
zend_observer_remove_begin_handler(&func->op_array, observer_begin);
273-
zend_observer_remove_end_handler(&func->op_array, observer_end);
274-
}
275-
} ZEND_HASH_FOREACH_END();
276-
}
277-
if (stage == PHP_INI_STAGE_STARTUP || stage == PHP_INI_STAGE_SHUTDOWN) {
278-
zend_hash_release(*p);
279-
*p = NULL;
280-
} else {
281-
zend_hash_clean(*p);
282-
}
264+
if (stage != PHP_INI_STAGE_STARTUP && stage != PHP_INI_STAGE_ACTIVATE && stage != PHP_INI_STAGE_DEACTIVATE && stage != PHP_INI_STAGE_SHUTDOWN) {
265+
ZEND_HASH_FOREACH_STR_KEY(*p, funcname) {
266+
if ((func = zend_hash_find_ptr(EG(function_table), funcname))) {
267+
zend_observer_remove_begin_handler(&func->op_array, observer_begin);
268+
zend_observer_remove_end_handler(&func->op_array, observer_end);
269+
}
270+
} ZEND_HASH_FOREACH_END();
283271
}
272+
zend_hash_clean(*p);
284273
if (new_value && ZSTR_LEN(new_value)) {
285-
if (!*p) {
286-
*p = malloc(sizeof(HashTable));
287-
}
288-
_zend_hash_init(*p, 8, ZVAL_PTR_DTOR, 1);
289274
const char *start = ZSTR_VAL(new_value), *ptr;
290275
while ((ptr = strchr(start, ','))) {
291276
zend_hash_str_add_empty_element(*p, start, ptr - start);
292277
start = ptr + 1;
293278
}
294279
zend_hash_str_add_empty_element(*p, start, ZSTR_VAL(new_value) + ZSTR_LEN(new_value) - start);
295-
if (EG(function_table)) {
280+
if (stage != PHP_INI_STAGE_STARTUP && stage != PHP_INI_STAGE_ACTIVATE && stage != PHP_INI_STAGE_DEACTIVATE && stage != PHP_INI_STAGE_SHUTDOWN) {
296281
ZEND_HASH_FOREACH_STR_KEY(*p, funcname) {
297282
if ((func = zend_hash_find_ptr(EG(function_table), funcname))) {
298283
zend_observer_add_begin_handler(&func->op_array, observer_begin);
@@ -351,8 +336,13 @@ void zend_test_observer_shutdown(SHUTDOWN_FUNC_ARGS)
351336
if (type != MODULE_TEMPORARY) {
352337
UNREGISTER_INI_ENTRIES();
353338
}
339+
}
354340

355-
if (ZT_G(observer_observe_function_names)) {
356-
zend_hash_release(ZT_G(observer_observe_function_names));
357-
}
341+
void zend_test_observer_ginit(zend_zend_test_globals *zend_test_globals) {
342+
zend_test_globals->observer_observe_function_names = malloc(sizeof(HashTable));
343+
_zend_hash_init(zend_test_globals->observer_observe_function_names, 8, ZVAL_PTR_DTOR, 1);
344+
}
345+
346+
void zend_test_observer_gshutdown(zend_zend_test_globals *zend_test_globals) {
347+
zend_hash_release(zend_test_globals->observer_observe_function_names);
358348
}

ext/zend_test/observer.h

+2
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,7 @@
1919

2020
void zend_test_observer_init(INIT_FUNC_ARGS);
2121
void zend_test_observer_shutdown(SHUTDOWN_FUNC_ARGS);
22+
void zend_test_observer_ginit(zend_zend_test_globals *zend_test_globals);
23+
void zend_test_observer_gshutdown(zend_zend_test_globals *zend_test_globals);
2224

2325
#endif

ext/zend_test/test.c

+8-1
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,13 @@ static PHP_GINIT_FUNCTION(zend_test)
775775
ZEND_TSRMLS_CACHE_UPDATE();
776776
#endif
777777
memset(zend_test_globals, 0, sizeof(*zend_test_globals));
778+
779+
zend_test_observer_ginit(zend_test_globals);
780+
}
781+
782+
static PHP_GSHUTDOWN_FUNCTION(zend_test)
783+
{
784+
zend_test_observer_gshutdown(zend_test_globals);
778785
}
779786

780787
PHP_MINFO_FUNCTION(zend_test)
@@ -798,7 +805,7 @@ zend_module_entry zend_test_module_entry = {
798805
PHP_ZEND_TEST_VERSION,
799806
PHP_MODULE_GLOBALS(zend_test),
800807
PHP_GINIT(zend_test),
801-
NULL,
808+
PHP_GSHUTDOWN(zend_test),
802809
NULL,
803810
STANDARD_MODULE_PROPERTIES_EX
804811
};

0 commit comments

Comments
 (0)