From 909cecb7faa5befa621d9446ed44187c1543b576 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 16 Oct 2024 19:43:49 +0200 Subject: [PATCH] Fix GH-16414: zend_test.observer.observe_function_names may segfault Unless `zend_test.observer.enabled` is on, we must not add observer handlers, so we let the INI modify handler fail early. We also need to ensure that the functions to observe have already been called, so that their begin and end handlers are properly initialized. Otherwise we will not observe the function execution, but a segfault. Co-authored-by: Bob Weinand Closes GH-16438. --- ext/zend_test/observer.c | 7 +++++-- ext/zend_test/tests/gh16414.phpt | 13 +++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 ext/zend_test/tests/gh16414.phpt diff --git a/ext/zend_test/observer.c b/ext/zend_test/observer.c index d413450bf9d..ff3b444b610 100644 --- a/ext/zend_test/observer.c +++ b/ext/zend_test/observer.c @@ -304,9 +304,12 @@ static ZEND_INI_MH(zend_test_observer_OnUpdateCommaList) zend_array **p = (zend_array **) ZEND_INI_GET_ADDR(); zend_string *funcname; zend_function *func; + if (!ZT_G(observer_enabled)) { + return FAILURE; + } if (stage != PHP_INI_STAGE_STARTUP && stage != PHP_INI_STAGE_ACTIVATE && stage != PHP_INI_STAGE_DEACTIVATE && stage != PHP_INI_STAGE_SHUTDOWN) { ZEND_HASH_FOREACH_STR_KEY(*p, funcname) { - if ((func = zend_hash_find_ptr(EG(function_table), funcname))) { + if ((func = zend_hash_find_ptr(EG(function_table), funcname)) && ZEND_OBSERVER_DATA(func) != NULL) { void *old_handler; zend_observer_remove_begin_handler(func, observer_begin, (zend_observer_fcall_begin_handler *)&old_handler); zend_observer_remove_end_handler(func, observer_end, (zend_observer_fcall_end_handler *)&old_handler); @@ -329,7 +332,7 @@ static ZEND_INI_MH(zend_test_observer_OnUpdateCommaList) zend_string_release(str); if (stage != PHP_INI_STAGE_STARTUP && stage != PHP_INI_STAGE_ACTIVATE && stage != PHP_INI_STAGE_DEACTIVATE && stage != PHP_INI_STAGE_SHUTDOWN) { ZEND_HASH_FOREACH_STR_KEY(*p, funcname) { - if ((func = zend_hash_find_ptr(EG(function_table), funcname))) { + if ((func = zend_hash_find_ptr(EG(function_table), funcname)) && ZEND_OBSERVER_DATA(func) != NULL) { zend_observer_add_begin_handler(func, observer_begin); zend_observer_add_end_handler(func, observer_end); } diff --git a/ext/zend_test/tests/gh16414.phpt b/ext/zend_test/tests/gh16414.phpt new file mode 100644 index 00000000000..ee1f406ebc0 --- /dev/null +++ b/ext/zend_test/tests/gh16414.phpt @@ -0,0 +1,13 @@ +--TEST-- +GH-16414 (zend_test.observer.observe_function_names may segfault) +--EXTENSIONS-- +zend_test +--INI-- +zend_test.observer.enabled=0 +--FILE-- + +--EXPECT-- +bool(false)