diff --git a/NEWS b/NEWS index 5dac2613a0e4..703f57b79409 100644 --- a/NEWS +++ b/NEWS @@ -25,6 +25,11 @@ PHP NEWS . Fix stmt->query leak in mysqli_execute_query() validation errors. (David Carlier) +- Opcache: + . Fixed bug GH-22158 (Tracing JIT dispatches the observer begin handler + through the wrong run_time_cache slot on megamorphic calls). (ptondereau, + iliaal) + - Phar: . Fixed a bypass of the magic ".phar" directory protection in Phar::addEmptyDir() for paths starting with "/.phar", while allowing diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index f99605ee4208..2cc6a01c4107 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -4815,7 +4815,7 @@ static struct jit_observer_fcall_is_unobserved_data jit_observer_fcall_is_unobse ir_ref observer_handler_user = ir_ADD_OFFSET(run_time_cache, zend_observer_fcall_op_array_extension * sizeof(void *)); ir_MERGE_WITH(if_internal_func_end); - *observer_handler = ir_PHI_2(IR_ADDR, observer_handler_internal, observer_handler_user); + *observer_handler = ir_PHI_2(IR_ADDR, observer_handler_user, observer_handler_internal); } // JIT: if (*observer_handler == ZEND_OBSERVER_NONE_OBSERVED) { diff --git a/ext/opcache/tests/jit/gh22158.phpt b/ext/opcache/tests/jit/gh22158.phpt new file mode 100644 index 000000000000..ce7f9bc55938 --- /dev/null +++ b/ext/opcache/tests/jit/gh22158.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-22158 (Tracing JIT dispatches observer begin handler through the wrong run_time_cache slot on megamorphic calls) +--EXTENSIONS-- +opcache +zend_test +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.jit=tracing +opcache.jit_buffer_size=32M +opcache.jit_max_polymorphic_calls=0 +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.show_output=0 +zend_test.observer.reserve_op_array_handle=1 +--FILE-- +f(); +} +echo $t, "\n"; +?> +--EXPECT-- +600000 diff --git a/ext/zend_test/observer.c b/ext/zend_test/observer.c index 0dfb62723bc4..a7ab0c51e53f 100644 --- a/ext/zend_test/observer.c +++ b/ext/zend_test/observer.c @@ -18,6 +18,7 @@ #include "php_test.h" #include "observer.h" #include "zend_observer.h" +#include "zend_extensions.h" #include "zend_smart_str.h" #include "ext/standard/php_var.h" #include "zend_generators.h" @@ -378,6 +379,7 @@ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("zend_test.observer.fiber_switch", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_fiber_switch, zend_zend_test_globals, zend_test_globals) STD_PHP_INI_BOOLEAN("zend_test.observer.fiber_destroy", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_fiber_destroy, zend_zend_test_globals, zend_test_globals) STD_PHP_INI_BOOLEAN("zend_test.observer.execute_internal", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_execute_internal, zend_zend_test_globals, zend_test_globals) + STD_PHP_INI_BOOLEAN("zend_test.observer.reserve_op_array_handle", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_reserve_op_array_handle, zend_zend_test_globals, zend_test_globals) PHP_INI_END() void zend_test_observer_init(INIT_FUNC_ARGS) @@ -386,6 +388,9 @@ void zend_test_observer_init(INIT_FUNC_ARGS) if (type != MODULE_TEMPORARY) { REGISTER_INI_ENTRIES(); if (ZT_G(observer_enabled)) { + if (ZT_G(observer_reserve_op_array_handle)) { + zend_get_op_array_extension_handle("zend_test"); + } zend_observer_fcall_register(observer_fcall_init); } } else { diff --git a/ext/zend_test/php_test.h b/ext/zend_test/php_test.h index c1310db7bd70..f32c6338d5c6 100644 --- a/ext/zend_test/php_test.h +++ b/ext/zend_test/php_test.h @@ -51,6 +51,7 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test) int observer_fiber_switch; int observer_fiber_destroy; int observer_execute_internal; + int observer_reserve_op_array_handle; HashTable *global_weakmap; int replace_zend_execute_ex; int register_passes;