Skip to content

Fix JIT fuzzers never enabling the JIT - #24717

Open
yumasansansan wants to merge 1 commit into
php:masterfrom
yumasansansan:fuzzer-jit-enable
Open

yumasansansan wants to merge 1 commit into
php:masterfrom
yumasansansan:fuzzer-jit-enable

Conversation

@yumasansansan

Copy link
Copy Markdown

The php-fuzz-function-jit and php-fuzz-tracing-jit fuzzers switch opcache.jit at runtime (off for the first run, then function / tracing). Since c16ad91 (RFC jit_config_defaults, PHP 8.4) the default is opcache.jit=disable, which leaves JIT_G(enabled) = 0, and zend_jit_config() then refuses runtime changes with "Cannot change opcache.jit setting at run-time (JIT is disabled)". The fuzzers ignore the return value of zend_alter_ini_entry_chars(), so the JIT has not been exercised by these fuzzers since PHP 8.4.

Evidence:

  • gdb on the current master: zend_jit_config("function", ZEND_INI_STAGE_RUNTIME) is entered with JIT_G(enabled) == 0, and zend_jit_script() / zend_jit_op_array() are never called. With this patch they are.
  • OSS-Fuzz coverage report (2026-10-24): ext/opcache/jit/ has 0.04% line coverage (40/103166 lines, 7/1407 functions), and the JIT fuzzers have lower total coverage than php-fuzz-execute.
  • Replaying the seed corpus generated from Zend/tests and ext/opcache/tests/jit (6181 files, one run each, ASan build):
Fuzzer Before (cov / ft) After (cov / ft)
php-fuzz-function-jit 10664 / 17448 13472 / 28214
php-fuzz-tracing-jit 10664 / 19061 14320 / 29350

Before the patch both fuzzers reach exactly the same edges, as neither runs the JIT.

The patch starts with opcache.jit=off (JIT available but off) and makes a failure to switch the JIT mode abort the fuzzer, so a future change of the defaults shows up as a crash on OSS-Fuzz instead of silently disabling JIT fuzzing.

Note: once this lands, OSS-Fuzz will start exercising the JIT again after a gap of about three years, so a burst of new JIT reports is to be expected.

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant