[php-src] PR #24273: Fix JIT stub veneers being reused after an OPcache restart on AArch64

From: Date: Mon, 12 Oct 2026 13:36:51 +0000
Subject: [php-src] PR #24273: Fix JIT stub veneers being reused after an OPcache restart on AArch64
Groups: php.git-pulls 
Request: Send a blank email to git-pulls+get-39357@lists.php.net to get a copy of this message
Pull Request: https://github.com/php/php-src/pull/24273 Author: pavimus Prepared with an AI assistant (Claude), which also ran the reproduction and the tests on my machine; I reviewed the result. The text below is AI-generated (quoted, as asked in CONTRIBUTING.md). > While testing OPcache restarts with tracing JIT on AArch64 we found crashes caused by a JIT > issue that is independent of threading. > > On AArch64 a branch from JIT code to a stub can be out of range (conditional branches reach > ±1 MB), and IR emits a veneer next to the new code. > zend_jit_set_veneer() / > zend_jit_commit_veneers() then replace the address of the stub > in zend_jit_stub_handlers[] > by the address of that veneer, so that later code reuses it. > > These veneers live after the JIT restart point (dasm_ptr[1]). > zend_jit_restart() rewinds the > buffer to that point but leaves zend_jit_stub_handlers[] > pointing to the old veneers. Code > compiled after the restart branches to those addresses, which are overwritten by new traces as > the > buffer fills up again, and jumps into the middle of unrelated code when the stub is taken > (exception handling, leaving a function, ...). > > Observed with opcache.jit=tracing, more than 1 MB of JIT code > and repeated OOM restarts under > FrankenPHP (ZTS): crash in JIT code in 8 of 8 runs. At the crash, gdb shows e.g. > zend_jit_stub_handlers[JIT$$leave_function_handler] == > $pc, and that address holds an ldr > of a trace, not the b of a veneer. In a single-process NTS > server the same stale entries are > present at zend_jit_restart() > (JIT$$exception_handler, > JIT$$leave_function_handler, > JIT$$icall_throw, > JIT$$leave_throw pointing past the restart point); we did not manage > to turn > that into a deterministic crash in NTS, so there is no test yet. > > The fix keeps the original stub addresses in a third block after the pending veneers (allocated > in > the same place as the existing two) and restores them in > zend_jit_restart(). x86 and Windows > are not affected (no veneers). > > With this change (and the GH-8739 fix, which is needed to have restarts at all under ZTS): 0 > crashes > in 40 runs of the FrankenPHP scenario, and 9 of 10 runs without a crash on Apache event (the > remaining > crash has a different signature and is not understood yet). make > test for ext/opcache and > Zend/tests passes. 🤖 Generated with [Claude Code](https://claude.com/claude-code)

« previous php.git-pulls (#39357) next »