Skip to content

Commit d5a82e2

Browse files
committed
Disable JIT with incompatible third-party extensions
1 parent 15073d8 commit d5a82e2

File tree

5 files changed

+68
-4
lines changed

5 files changed

+68
-4
lines changed

ext/opcache/ZendAccelerator.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2970,7 +2970,8 @@ static zend_result accel_post_startup(void)
29702970
size_t jit_size = 0;
29712971
zend_bool reattached = 0;
29722972

2973-
if (JIT_G(enabled) && JIT_G(buffer_size)) {
2973+
if (JIT_G(enabled) && JIT_G(buffer_size)
2974+
&& zend_jit_check_support() == SUCCESS) {
29742975
size_t page_size;
29752976

29762977
# ifdef _WIN32

ext/opcache/jit/zend_jit.c

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4164,17 +4164,39 @@ ZEND_EXT_API void zend_jit_init(void)
41644164
#endif
41654165
}
41664166

4167-
ZEND_EXT_API int zend_jit_startup(void *buf, size_t size, zend_bool reattached)
4167+
ZEND_EXT_API int zend_jit_check_support(void)
41684168
{
4169-
int ret;
4169+
int i;
41704170

41714171
zend_jit_vm_kind = zend_vm_kind();
41724172
if (zend_jit_vm_kind != ZEND_VM_KIND_CALL &&
41734173
zend_jit_vm_kind != ZEND_VM_KIND_HYBRID) {
4174-
// TODO: error reporting and cleanup ???
4174+
zend_error(E_WARNING, "JIT is compatible only with CALL and HYBRID VM. JIT disabled.");
4175+
JIT_G(enabled) = 0;
41754176
return FAILURE;
41764177
}
41774178

4179+
if (zend_execute_ex != execute_ex) {
4180+
zend_error(E_WARNING, "JIT is incompatible with third party extensions that override zend_execute_ex(). JIT disabled.");
4181+
JIT_G(enabled) = 0;
4182+
return FAILURE;
4183+
}
4184+
4185+
for (i = 0; i <= 256; i++) {
4186+
if (zend_get_user_opcode_handler(i) != NULL) {
4187+
zend_error(E_WARNING, "JIT is incompatible with third party extensions that setup user opcode handlers. JIT disabled.");
4188+
JIT_G(enabled) = 0;
4189+
return FAILURE;
4190+
}
4191+
}
4192+
4193+
return SUCCESS;
4194+
}
4195+
4196+
ZEND_EXT_API int zend_jit_startup(void *buf, size_t size, zend_bool reattached)
4197+
{
4198+
int ret;
4199+
41784200
zend_jit_halt_op = zend_get_halt_op();
41794201

41804202
if (zend_jit_setup() != SUCCESS) {

ext/opcache/jit/zend_jit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ ZEND_EXT_API void zend_jit_protect(void);
136136
ZEND_EXT_API void zend_jit_init(void);
137137
ZEND_EXT_API int zend_jit_config(zend_string *jit_options, int stage);
138138
ZEND_EXT_API int zend_jit_debug_config(zend_long old_val, zend_long new_val, int stage);
139+
ZEND_EXT_API int zend_jit_check_support(void);
139140
ZEND_EXT_API int zend_jit_startup(void *jit_buffer, size_t size, zend_bool reattached);
140141
ZEND_EXT_API void zend_jit_shutdown(void);
141142
ZEND_EXT_API void zend_jit_activate(void);

ext/opcache/tests/jit/bug80426.phpt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Bug #80426: Crash when using JIT and an extension replacing zend_execute_ex with custom
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.jit_buffer_size=1M
7+
zend_test.replace_zend_execute_ex=1
8+
--SKIPIF--
9+
<?php require_once('skipif.inc'); ?>
10+
<?php if (!extension_loaded('zend-test')) die('skip: zend-test extension required'); ?>
11+
--FILE--
12+
<?php
13+
14+
function compute() {
15+
if (true) {
16+
}
17+
}
18+
19+
for ($i = 0; $i <= 64; $i++) {
20+
compute();
21+
}
22+
23+
?>
24+
===DONE===
25+
--EXPECT--
26+
Warning: JIT is incompatible with third party extensions that override zend_execute_ex(). JIT disabled. in Unknown on line 0
27+
===DONE===

ext/zend_test/test.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test)
3939
int observer_show_init_backtrace;
4040
int observer_show_opcode;
4141
int observer_nesting_depth;
42+
int replace_zend_execute_ex;
4243
ZEND_END_MODULE_GLOBALS(zend_test)
4344

4445
ZEND_DECLARE_MODULE_GLOBALS(zend_test)
@@ -332,10 +333,17 @@ PHP_INI_BEGIN()
332333
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)
333334
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)
334335
STD_PHP_INI_BOOLEAN("zend_test.observer.show_opcode", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_opcode, zend_zend_test_globals, zend_test_globals)
336+
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)
335337
PHP_INI_END()
336338

337339
static zend_observer_fcall_handlers observer_fcall_init(zend_execute_data *execute_data);
338340

341+
void (*old_zend_execute_ex)(zend_execute_data *execute_data);
342+
static void custom_zend_execute_ex(zend_execute_data *execute_data)
343+
{
344+
old_zend_execute_ex(execute_data);
345+
}
346+
339347
PHP_MINIT_FUNCTION(zend_test)
340348
{
341349
zend_class_entry class_entry;
@@ -431,6 +439,11 @@ PHP_MINIT_FUNCTION(zend_test)
431439
(void)ini_entries;
432440
}
433441

442+
if (ZT_G(replace_zend_execute_ex)) {
443+
old_zend_execute_ex = zend_execute_ex;
444+
zend_execute_ex = custom_zend_execute_ex;
445+
}
446+
434447
return SUCCESS;
435448
}
436449

0 commit comments

Comments
 (0)