Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 93cb539

Browse files
committed
Extend zend_test to allow hooks to be executed while observing the end of a function
Add a test verifying we can modify return values
1 parent 4123cc3 commit 93cb539

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

‎ext/zend_test/observer.c‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,46 @@ static void observer_end(zend_execute_data *execute_data, zval *retval)
119119
if (EG(exception)) {
120120
php_printf("%*s<!-- Exception: %s -->\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(EG(exception)->ce->name));
121121
}
122+
123+
if(ZT_G(observer_observe_end_call_function_name) && strlen(ZT_G(observer_observe_end_call_function_name)) > 0) {
124+
zend_fcall_info fci = empty_fcall_info;
125+
zend_fcall_info_cache fcc = empty_fcall_info_cache;
126+
127+
zval function_name = {.u1.type_info = IS_UNDEF};
128+
129+
// Initialize the zval with the zend_string value
130+
ZVAL_STRING(&function_name, ZT_G(observer_observe_end_call_function_name));
131+
132+
char* error = 0;
133+
if (zend_fcall_info_init(&function_name, 0, &fci, &fcc, NULL, &error) != SUCCESS) {
134+
135+
php_printf("<!-- Hook (%s) not found: %s-->\n", Z_STRVAL(function_name), error);
136+
efree(error);
137+
} else {
138+
139+
zval ret = {.u1.type_info = IS_UNDEF};
140+
fci.param_count = 0;
141+
fci.params = NULL;
142+
fci.named_params = NULL;
143+
fci.retval = &ret;
144+
145+
if (zend_call_function(&fci, &fcc) == SUCCESS) {
146+
if (!Z_ISUNDEF(ret) &&
147+
(fcc.function_handler->op_array.fn_flags &
148+
ZEND_ACC_HAS_RETURN_TYPE) &&
149+
!(ZEND_TYPE_PURE_MASK(
150+
fcc.function_handler->common.arg_info[-1].type) &
151+
MAY_BE_VOID)) {
152+
if (execute_data->return_value) {
153+
zval_ptr_dtor(execute_data->return_value);
154+
ZVAL_COPY(execute_data->return_value, &ret);
155+
ZVAL_UNDEF(&ret);
156+
}
157+
}
158+
}
159+
}
160+
zval_ptr_dtor(&function_name);
161+
}
122162
observer_show_opcode(execute_data);
123163
ZT_G(observer_nesting_depth)--;
124164
if (execute_data->func && execute_data->func->common.function_name) {
@@ -304,6 +344,7 @@ PHP_INI_BEGIN()
304344
STD_PHP_INI_BOOLEAN("zend_test.observer.observe_includes", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_observe_includes, zend_zend_test_globals, zend_test_globals)
305345
STD_PHP_INI_BOOLEAN("zend_test.observer.observe_functions", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_observe_functions, zend_zend_test_globals, zend_test_globals)
306346
STD_PHP_INI_ENTRY("zend_test.observer.observe_function_names", "", PHP_INI_SYSTEM, zend_test_observer_OnUpdateCommaList, observer_observe_function_names, zend_zend_test_globals, zend_test_globals)
347+
STD_PHP_INI_ENTRY("zend_test.observer.observe_end_call_function_name", "", PHP_INI_ALL, OnUpdateString, observer_observe_end_call_function_name, zend_zend_test_globals, zend_test_globals)
307348
STD_PHP_INI_BOOLEAN("zend_test.observer.show_return_type", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_return_type, zend_zend_test_globals, zend_test_globals)
308349
STD_PHP_INI_BOOLEAN("zend_test.observer.show_return_value", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_return_value, zend_zend_test_globals, zend_test_globals)
309350
STD_PHP_INI_BOOLEAN("zend_test.observer.show_init_backtrace", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_init_backtrace, zend_zend_test_globals, zend_test_globals)

‎ext/zend_test/php_test.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test)
3939
int observer_observe_includes;
4040
int observer_observe_functions;
4141
zend_array *observer_observe_function_names;
42+
const char *observer_observe_end_call_function_name;
4243
int observer_show_return_type;
4344
int observer_show_return_value;
4445
int observer_show_init_backtrace;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
Observer: Function return values are modifiable by observers
3+
--EXTENSIONS--
4+
zend_test
5+
--INI--
6+
zend_test.observer.enabled=1
7+
zend_test.observer.show_output=1
8+
zend_test.observer.show_return_value=1
9+
zend_test.observer.observe_function_names=foo
10+
zend_test.observer.observe_end_call_function_name=hook
11+
--FILE--
12+
<?php
13+
function foo(string $pin): string {
14+
15+
return 'original return value';
16+
}
17+
18+
function hook(): string {
19+
return 'hook value';
20+
}
21+
22+
$res = foo('some value'); // Retval used
23+
var_dump($res);
24+
echo 'Done' . PHP_EOL;
25+
?>
26+
--EXPECTF--
27+
<!-- init '%s/observer_retval_alter_%d.php' -->
28+
<!-- init foo() -->
29+
<foo>
30+
<!-- init hook() -->
31+
</foo:'original return value'>
32+
string(10) "hook value"
33+
Done

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /