Skip to content

Commit 6f57993

Browse files
committed
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
1 parent fa64a1d commit 6f57993

File tree

6 files changed

+95
-2
lines changed

6 files changed

+95
-2
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 8.2.28
44

5+
- Core:
6+
. Fixed bug GH-17211 (observer segfault on function loaded with dl()).
7+
(Arnaud)
58

69
19 Dec 2024, PHP 8.2.27
710

Zend/zend_API.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2718,7 +2718,14 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend
27182718
}
27192719
internal_function->type = ZEND_INTERNAL_FUNCTION;
27202720
internal_function->module = EG(current_module);
2721-
internal_function->T = 0;
2721+
if (EG(active) && ZEND_OBSERVER_ENABLED) {
2722+
/* Add an observer temporary to store previous observed frames. This is
2723+
* normally handled by zend_observer_post_startup(), except for
2724+
* functions registered at runtime (EG(active)). */
2725+
internal_function->T = 1;
2726+
} else {
2727+
internal_function->T = 0;
2728+
}
27222729
memset(internal_function->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
27232730

27242731
while (ptr->fname) {

ext/dl_test/dl_test.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,27 @@ PHP_INI_BEGIN()
7676
PHP_INI_END()
7777
/* }}} */
7878

79+
PHP_METHOD(DlTest, test)
80+
{
81+
char *var = "World";
82+
size_t var_len = sizeof("World") - 1;
83+
zend_string *retval;
84+
85+
ZEND_PARSE_PARAMETERS_START(0, 1)
86+
Z_PARAM_OPTIONAL
87+
Z_PARAM_STRING(var, var_len)
88+
ZEND_PARSE_PARAMETERS_END();
89+
90+
retval = strpprintf(0, "Hello %s", var);
91+
92+
RETURN_STR(retval);
93+
}
94+
7995
/* {{{ PHP_MINIT_FUNCTION */
8096
PHP_MINIT_FUNCTION(dl_test)
8197
{
98+
register_class_DlTest();
99+
82100
/* Test backwards compatibility */
83101
if (getenv("PHP_DL_TEST_USE_OLD_REGISTER_INI_ENTRIES")) {
84102
zend_register_ini_entries(ini_entries, module_number);

ext/dl_test/dl_test.stub.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,7 @@
88
function dl_test_test1(): void {}
99

1010
function dl_test_test2(string $str = ""): string {}
11+
12+
class DlTest {
13+
public function test(string $str = ""): string {}
14+
}

ext/dl_test/dl_test_arginfo.h

Lines changed: 20 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
--TEST--
2+
dl() / observer segfault
3+
--EXTENSIONS--
4+
zend_test
5+
--SKIPIF--
6+
<?php include dirname(__DIR__, 3) . "/dl_test/tests/skip.inc"; ?>
7+
--INI--
8+
zend_test.observer.enabled=1
9+
zend_test.observer.observe_functions=1
10+
zend_test.observer.show_output=1
11+
--FILE--
12+
<?php
13+
14+
if (PHP_OS_FAMILY === 'Windows') {
15+
$loaded = dl('php_dl_test.dll');
16+
} else {
17+
$loaded = dl('dl_test.so');
18+
}
19+
20+
var_dump(dl_test_test2("World!"));
21+
22+
$test = new DlTest();
23+
var_dump($test->test("World!"));
24+
?>
25+
--EXPECTF--
26+
<!-- init '%sgh17211.php' -->
27+
<!-- init dl() -->
28+
<dl>
29+
</dl>
30+
<!-- init dl_test_test2() -->
31+
<dl_test_test2>
32+
</dl_test_test2>
33+
<!-- init var_dump() -->
34+
<var_dump>
35+
string(12) "Hello World!"
36+
</var_dump>
37+
<!-- init DlTest::test() -->
38+
<DlTest::test>
39+
</DlTest::test>
40+
<var_dump>
41+
string(12) "Hello World!"
42+
</var_dump>

0 commit comments

Comments
 (0)