size_t jit_size = 0;
zend_bool reattached = 0;
- if (JIT_G(enabled) && JIT_G(buffer_size)) {
+ if (JIT_G(enabled) && JIT_G(buffer_size)
+ && zend_jit_check_support() == SUCCESS) {
size_t page_size;
# ifdef _WIN32
#endif
}
-ZEND_EXT_API int zend_jit_startup(void *buf, size_t size, zend_bool reattached)
+ZEND_EXT_API int zend_jit_check_support(void)
{
- int ret;
+ int i;
zend_jit_vm_kind = zend_vm_kind();
if (zend_jit_vm_kind != ZEND_VM_KIND_CALL &&
zend_jit_vm_kind != ZEND_VM_KIND_HYBRID) {
- // TODO: error reporting and cleanup ???
+ zend_error(E_WARNING, "JIT is compatible only with CALL and HYBRID VM. JIT disabled.");
+ JIT_G(enabled) = 0;
return FAILURE;
}
+ if (zend_execute_ex != execute_ex) {
+ zend_error(E_WARNING, "JIT is incompatible with third party extensions that override zend_execute_ex(). JIT disabled.");
+ JIT_G(enabled) = 0;
+ return FAILURE;
+ }
+
+ for (i = 0; i <= 256; i++) {
+ if (zend_get_user_opcode_handler(i) != NULL) {
+ zend_error(E_WARNING, "JIT is incompatible with third party extensions that setup user opcode handlers. JIT disabled.");
+ JIT_G(enabled) = 0;
+ return FAILURE;
+ }
+ }
+
+ return SUCCESS;
+}
+
+ZEND_EXT_API int zend_jit_startup(void *buf, size_t size, zend_bool reattached)
+{
+ int ret;
+
zend_jit_halt_op = zend_get_halt_op();
if (zend_jit_setup() != SUCCESS) {
ZEND_EXT_API void zend_jit_init(void);
ZEND_EXT_API int zend_jit_config(zend_string *jit_options, int stage);
ZEND_EXT_API int zend_jit_debug_config(zend_long old_val, zend_long new_val, int stage);
+ZEND_EXT_API int zend_jit_check_support(void);
ZEND_EXT_API int zend_jit_startup(void *jit_buffer, size_t size, zend_bool reattached);
ZEND_EXT_API void zend_jit_shutdown(void);
ZEND_EXT_API void zend_jit_activate(void);
--- /dev/null
+--TEST--
+Bug #80426: Crash when using JIT and an extension replacing zend_execute_ex with custom
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.jit_buffer_size=1M
+zend_test.replace_zend_execute_ex=1
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+<?php if (!extension_loaded('zend-test')) die('skip: zend-test extension required'); ?>
+--FILE--
+<?php
+
+function compute() {
+ if (true) {
+ }
+}
+
+for ($i = 0; $i <= 64; $i++) {
+ compute();
+}
+
+?>
+===DONE===
+--EXPECT--
+Warning: JIT is incompatible with third party extensions that override zend_execute_ex(). JIT disabled. in Unknown on line 0
+===DONE===
int observer_show_init_backtrace;
int observer_show_opcode;
int observer_nesting_depth;
+ int replace_zend_execute_ex;
ZEND_END_MODULE_GLOBALS(zend_test)
ZEND_DECLARE_MODULE_GLOBALS(zend_test)
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)
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)
STD_PHP_INI_BOOLEAN("zend_test.observer.show_opcode", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_opcode, zend_zend_test_globals, zend_test_globals)
+ STD_PHP_INI_BOOLEAN("zend_test.replace_zend_execute_ex", "0", PHP_INI_SYSTEM, OnUpdateBool, replace_zend_execute_ex, zend_zend_test_globals, zend_test_globals)
PHP_INI_END()
static zend_observer_fcall_handlers observer_fcall_init(zend_execute_data *execute_data);
+void (*old_zend_execute_ex)(zend_execute_data *execute_data);
+static void custom_zend_execute_ex(zend_execute_data *execute_data)
+{
+ old_zend_execute_ex(execute_data);
+}
+
PHP_MINIT_FUNCTION(zend_test)
{
zend_class_entry class_entry;
(void)ini_entries;
}
+ if (ZT_G(replace_zend_execute_ex)) {
+ old_zend_execute_ex = zend_execute_ex;
+ zend_execute_ex = custom_zend_execute_ex;
+ }
+
return SUCCESS;
}