Skip to content

Commit 5e4e06c

Browse files
committed
Fix JIT fuzzers never enabling the JIT
Since the default of opcache.jit changed from "tracing" to "disable" (c16ad91, RFC jit_config_defaults), JIT_G(enabled) is false after startup and zend_jit_config() rejects every runtime change of opcache.jit. The function-jit and tracing-jit fuzzers turn the JIT on at runtime without checking the result, so since PHP 8.4 they have only been running the VM. The OSS-Fuzz coverage report of 2026-10-24 shows 0.04% line coverage (40/103166) for ext/opcache/jit/. Start with opcache.jit=off, which keeps the JIT available, and abort if switching the JIT mode fails, so that this cannot regress silently.
1 parent 49b2bc4 commit 5e4e06c

3 files changed

Lines changed: 17 additions & 8 deletions

File tree

‎sapi/fuzzer/fuzzer-execute-common.h‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,12 @@ ZEND_ATTRIBUTE_UNUSED static void opcache_invalidate(void) {
146146
zval_ptr_dtor(&retval);
147147
EG(exception) = exception;
148148
}
149+
150+
ZEND_ATTRIBUTE_UNUSED static void set_jit_option(zend_string *jit_option, const char *value) {
151+
if (zend_alter_ini_entry_chars(
152+
jit_option, value, strlen(value), PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == FAILURE) {
153+
/* Fail loudly instead of silently fuzzing without the JIT. */
154+
fprintf(stderr, "Failed to set opcache.jit=%s\n", value);
155+
abort();
156+
}
157+
}

‎sapi/fuzzer/fuzzer-function-jit.c‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
2727
* we bail out here, as the JIT code may loop infinitely. */
2828
steps_left = MAX_STEPS;
2929
bailed_out = false;
30-
zend_alter_ini_entry_chars(
31-
jit_option, "off", sizeof("off")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
30+
set_jit_option(jit_option, "off");
3231
fuzzer_do_request_from_buffer(
3332
FILE_NAME, (const char *) Data, Size, /* execute */ 1, opcache_invalidate);
3433

3534
if (!bailed_out) {
3635
steps_left = MAX_STEPS;
37-
zend_alter_ini_entry_chars(jit_option,
38-
"function", sizeof("function")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
36+
set_jit_option(jit_option, "function");
3937
zend_execute_ex = orig_execute_ex;
4038
fuzzer_do_request_from_buffer(
4139
FILE_NAME, (const char *) Data, Size, /* execute */ 1, opcache_invalidate);
@@ -50,6 +48,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
5048
int LLVMFuzzerInitialize(int *argc, char ***argv) {
5149
char ini_buf[512];
5250
snprintf(ini_buf, sizeof(ini_buf),
51+
/* The default opcache.jit=disable does not allow enabling the JIT at runtime. */
52+
"opcache.jit=off\n"
5353
"opcache.validate_timestamps=0\n"
5454
"opcache.file_update_protection=0\n"
5555
"opcache.jit_buffer_size=128M\n"

‎sapi/fuzzer/fuzzer-tracing-jit.c‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
2727
* we bail out here, as the JIT code may loop infinitely. */
2828
steps_left = MAX_STEPS;
2929
bailed_out = false;
30-
zend_alter_ini_entry_chars(
31-
jit_option, "off", sizeof("off")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
30+
set_jit_option(jit_option, "off");
3231
fuzzer_do_request_from_buffer(
3332
FILE_NAME, (const char *) Data, Size, /* execute */ 1, opcache_invalidate);
3433

3534
if (!bailed_out) {
3635
steps_left = MAX_STEPS;
37-
zend_alter_ini_entry_chars(jit_option,
38-
"tracing", sizeof("tracing")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
36+
set_jit_option(jit_option, "tracing");
3937
zend_execute_ex = orig_execute_ex;
4038
/* Trace & compile */
4139
fuzzer_do_request_from_buffer(
@@ -54,6 +52,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
5452
int LLVMFuzzerInitialize(int *argc, char ***argv) {
5553
char ini_buf[512];
5654
snprintf(ini_buf, sizeof(ini_buf),
55+
/* The default opcache.jit=disable does not allow enabling the JIT at runtime. */
56+
"opcache.jit=off\n"
5757
"opcache.validate_timestamps=0\n"
5858
"opcache.file_update_protection=0\n"
5959
"opcache.memory_consumption=1024\n"

0 commit comments

Comments
 (0)