mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Add observer temporary to dl'ed functions
When observer is enabled, we normally add an extra temporary to all functions, to store the previously observed frame. However, this is done in zend_observer_post_startup() so it doesn't happen to dl'ed() functions. One possible fix would be to move that from zend_observer_post_startup() to zend_register_functions(), but this would be too early: Observer may not be enabled when zend_register_functions() is called, and may still be enabled later. However, when zend_register_functions() is called at run-time (during dl()), we know definitively whether observer is enabled. Here I update zend_register_functions() to add a temporary to dl'ed() functions when observer is enabled. Fixes: GH-17211 Closes: GH-17220
This commit is contained in:
3
NEWS
3
NEWS
@@ -2,6 +2,9 @@ PHP NEWS
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
?? ??? ????, PHP 8.2.28
|
||||
|
||||
- Core:
|
||||
. Fixed bug GH-17211 (observer segfault on function loaded with dl()).
|
||||
(Arnaud)
|
||||
|
||||
19 Dec 2024, PHP 8.2.27
|
||||
|
||||
|
||||
@@ -2718,7 +2718,14 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend
|
||||
}
|
||||
internal_function->type = ZEND_INTERNAL_FUNCTION;
|
||||
internal_function->module = EG(current_module);
|
||||
internal_function->T = 0;
|
||||
if (EG(active) && ZEND_OBSERVER_ENABLED) {
|
||||
/* Add an observer temporary to store previous observed frames. This is
|
||||
* normally handled by zend_observer_post_startup(), except for
|
||||
* functions registered at runtime (EG(active)). */
|
||||
internal_function->T = 1;
|
||||
} else {
|
||||
internal_function->T = 0;
|
||||
}
|
||||
memset(internal_function->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
|
||||
|
||||
while (ptr->fname) {
|
||||
|
||||
@@ -76,9 +76,27 @@ PHP_INI_BEGIN()
|
||||
PHP_INI_END()
|
||||
/* }}} */
|
||||
|
||||
PHP_METHOD(DlTest, test)
|
||||
{
|
||||
char *var = "World";
|
||||
size_t var_len = sizeof("World") - 1;
|
||||
zend_string *retval;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(0, 1)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_STRING(var, var_len)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
retval = strpprintf(0, "Hello %s", var);
|
||||
|
||||
RETURN_STR(retval);
|
||||
}
|
||||
|
||||
/* {{{ PHP_MINIT_FUNCTION */
|
||||
PHP_MINIT_FUNCTION(dl_test)
|
||||
{
|
||||
register_class_DlTest();
|
||||
|
||||
/* Test backwards compatibility */
|
||||
if (getenv("PHP_DL_TEST_USE_OLD_REGISTER_INI_ENTRIES")) {
|
||||
zend_register_ini_entries(ini_entries, module_number);
|
||||
|
||||
@@ -8,3 +8,7 @@
|
||||
function dl_test_test1(): void {}
|
||||
|
||||
function dl_test_test2(string $str = ""): string {}
|
||||
|
||||
class DlTest {
|
||||
public function test(string $str = ""): string {}
|
||||
}
|
||||
|
||||
21
ext/dl_test/dl_test_arginfo.h
generated
21
ext/dl_test/dl_test_arginfo.h
generated
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 547ddbc21e9aa853b491cb17e902bbbb9cc2df00 */
|
||||
* Stub hash: 2dbacf5282b0f8e53923ac70495c2da43c7237e3 */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_dl_test_test1, 0, 0, IS_VOID, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
@@ -8,9 +8,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_dl_test_test2, 0, 0, IS_STRING,
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, str, IS_STRING, 0, "\"\"")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_class_DlTest_test arginfo_dl_test_test2
|
||||
|
||||
|
||||
ZEND_FUNCTION(dl_test_test1);
|
||||
ZEND_FUNCTION(dl_test_test2);
|
||||
ZEND_METHOD(DlTest, test);
|
||||
|
||||
|
||||
static const zend_function_entry ext_functions[] = {
|
||||
@@ -18,3 +21,19 @@ static const zend_function_entry ext_functions[] = {
|
||||
ZEND_FE(dl_test_test2, arginfo_dl_test_test2)
|
||||
ZEND_FE_END
|
||||
};
|
||||
|
||||
|
||||
static const zend_function_entry class_DlTest_methods[] = {
|
||||
ZEND_ME(DlTest, test, arginfo_class_DlTest_test, ZEND_ACC_PUBLIC)
|
||||
ZEND_FE_END
|
||||
};
|
||||
|
||||
static zend_class_entry *register_class_DlTest(void)
|
||||
{
|
||||
zend_class_entry ce, *class_entry;
|
||||
|
||||
INIT_CLASS_ENTRY(ce, "DlTest", class_DlTest_methods);
|
||||
class_entry = zend_register_internal_class_ex(&ce, NULL);
|
||||
|
||||
return class_entry;
|
||||
}
|
||||
|
||||
42
ext/standard/tests/general_functions/gh17211.phpt
Normal file
42
ext/standard/tests/general_functions/gh17211.phpt
Normal file
@@ -0,0 +1,42 @@
|
||||
--TEST--
|
||||
dl() / observer segfault
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--SKIPIF--
|
||||
<?php include dirname(__DIR__, 3) . "/dl_test/tests/skip.inc"; ?>
|
||||
--INI--
|
||||
zend_test.observer.enabled=1
|
||||
zend_test.observer.observe_functions=1
|
||||
zend_test.observer.show_output=1
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
if (PHP_OS_FAMILY === 'Windows') {
|
||||
$loaded = dl('php_dl_test.dll');
|
||||
} else {
|
||||
$loaded = dl('dl_test.so');
|
||||
}
|
||||
|
||||
var_dump(dl_test_test2("World!"));
|
||||
|
||||
$test = new DlTest();
|
||||
var_dump($test->test("World!"));
|
||||
?>
|
||||
--EXPECTF--
|
||||
<!-- init '%sgh17211.php' -->
|
||||
<!-- init dl() -->
|
||||
<dl>
|
||||
</dl>
|
||||
<!-- init dl_test_test2() -->
|
||||
<dl_test_test2>
|
||||
</dl_test_test2>
|
||||
<!-- init var_dump() -->
|
||||
<var_dump>
|
||||
string(12) "Hello World!"
|
||||
</var_dump>
|
||||
<!-- init DlTest::test() -->
|
||||
<DlTest::test>
|
||||
</DlTest::test>
|
||||
<var_dump>
|
||||
string(12) "Hello World!"
|
||||
</var_dump>
|
||||
Reference in New Issue
Block a user