summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/snuffleupagus.c50
-rw-r--r--src/tests/disable_function/disabled_function_echo_2.phpt2
2 files changed, 49 insertions, 3 deletions
diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c
index 4d5fa09..ca7e6d4 100644
--- a/src/snuffleupagus.c
+++ b/src/snuffleupagus.c
@@ -25,6 +25,39 @@ static inline void sp_op_array_handler(zend_op_array *const op) {
25 op->fn_flags |= ZEND_ACC_STRICT_TYPES; 25 op->fn_flags |= ZEND_ACC_STRICT_TYPES;
26 } 26 }
27 } 27 }
28#if PHP_VERSION_ID >= 80500
29 /* Prevent opcache from inlining user functions that have return-value
30 * monitoring rules, otherwise zend_execute_ex is never called and the
31 * hook never fires. ZEND_ACC_HAS_TYPE_HINTS is checked by
32 * zend_try_inline_call() and blocks inlining. For functions without
33 * actual type hints the only runtime effect is that ZEND_RECV opcodes
34 * are executed instead of skipped; for 0-arg functions (the common
35 * inlineable case) there are no RECV opcodes so the impact is zero. */
36 if (op->function_name && ZEND_USER_CODE(op->type) &&
37 ((SPCFG(disabled_functions_ret) && zend_hash_num_elements(SPCFG(disabled_functions_ret))) ||
38 SPCFG(disabled_functions_reg_ret).disabled_functions)) {
39 char *fname = NULL;
40 if (op->scope) {
41 const size_t len = ZSTR_LEN(op->scope->name) + 2 + ZSTR_LEN(op->function_name) + 1;
42 fname = emalloc(len);
43 snprintf(fname, len, "%s::%s", ZSTR_VAL(op->scope->name), ZSTR_VAL(op->function_name));
44 } else {
45 fname = estrdup(ZSTR_VAL(op->function_name));
46 }
47 bool has_ret_rule = false;
48 if (SPCFG(disabled_functions_ret) &&
49 zend_hash_str_find_ptr(SPCFG(disabled_functions_ret), fname, strlen(fname))) {
50 has_ret_rule = true;
51 }
52 if (!has_ret_rule && SPCFG(disabled_functions_reg_ret).disabled_functions) {
53 has_ret_rule = true; /* regex rules require runtime matching */
54 }
55 if (has_ret_rule) {
56 op->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
57 }
58 efree(fname);
59 }
60#endif
28} 61}
29 62
30ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) 63ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus)
@@ -582,12 +615,25 @@ static PHP_INI_MH(OnUpdateConfiguration) {
582 615
583 sp_hook_register_server_variables(); 616 sp_hook_register_server_variables();
584 617
585 if (SPCFG(global_strict).enable) { 618 bool need_op_array_handler = SPCFG(global_strict).enable;
619
620#if PHP_VERSION_ID >= 80500
621 /* Register as zend extension to get op_array_handler callbacks, which we
622 * use to prevent opcache from inlining monitored functions. */
623 if (SPCFG(disabled_functions_ret) && zend_hash_num_elements(SPCFG(disabled_functions_ret))) {
624 need_op_array_handler = true;
625 }
626 if (SPCFG(disabled_functions_reg_ret).disabled_functions) {
627 need_op_array_handler = true;
628 }
629#endif
630
631 if (need_op_array_handler) {
586 if (!zend_get_extension(PHP_SNUFFLEUPAGUS_EXTNAME)) { 632 if (!zend_get_extension(PHP_SNUFFLEUPAGUS_EXTNAME)) {
587 zend_extension_entry.startup = NULL; 633 zend_extension_entry.startup = NULL;
588 zend_register_extension(&zend_extension_entry, NULL); 634 zend_register_extension(&zend_extension_entry, NULL);
589 } 635 }
590 // This is needed to implement the global strict mode 636 // This is needed to enable the op_array_handler callback
591 CG(compiler_options) |= ZEND_COMPILE_HANDLE_OP_ARRAY; 637 CG(compiler_options) |= ZEND_COMPILE_HANDLE_OP_ARRAY;
592 } 638 }
593 639
diff --git a/src/tests/disable_function/disabled_function_echo_2.phpt b/src/tests/disable_function/disabled_function_echo_2.phpt
index e519ec4..ce3488e 100644
--- a/src/tests/disable_function/disabled_function_echo_2.phpt
+++ b/src/tests/disable_function/disabled_function_echo_2.phpt
@@ -2,9 +2,9 @@
2Echo hooking 2Echo hooking
3--SKIPIF-- 3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?> 4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5<?php if (PHP_VERSION_ID >= 80500) print "skip"; ?>
6--INI-- 5--INI--
7sp.configuration_file={PWD}/config/disabled_function_echo.ini 6sp.configuration_file={PWD}/config/disabled_function_echo.ini
7opcache.optimization_level=0
8--FILE-- 8--FILE--
9<?php 9<?php
10echo "qwe"; 10echo "qwe";