[php-src] Issue #22443: SIGSEGV in execute_ex with tracing JIT on PHP 8.5.7 ZTS, AMD EPYC (Zen 4 / AVX-512) under Azure Container Apps — run-time-cache / zend_map_ptr base resolves to ~0

[email protected] (leonelfranchellimdlz) Wed, 24 Jun 2026 22:22:55 +0000
Newsgroups php.bugs
Message-ID <[email protected]>
Issue: https://github.com/php/php-src/issues/22443
Author: leonelfranchellimdlz

### Description

## Description

PHP **8.5.7 ZTS** with OPcache **tracing JIT** crashes with SIGSEGV in short-lived CLI processes on an **AMD EPYC 9V74 (Zen 4, AVX-512)** host under **Azure Container Apps (ACA)**. The same image, the same `php` binary, and the same opcache config run fine on an Intel **Core Ultra 7 255HX** (no AVX-512) dev machine and on a self-managed Linux VM.

The crash is in the interpreter (`execute_ex`), not in JIT-generated code, at the tail of a trivial run (`artisan migrate:modules` → prints "Nothing to migrate." twice → segfaults on exit). It is 100% reproducible on the affected host. **Disabling only the JIT (keeping opcode caching) eliminates it.**

## Reproduction

On the ACA container (PHP 8.5.7 ZTS, OPcache tracing JIT on):

```
$ php artisan migrate:modules; echo "exit=$?"
   INFO  Nothing to migrate.
   INFO  Nothing to migrate.
Segmentation fault (core dumped)
exit=139
```

Same binary/process, only ini flags changed:

| OPcache config | Result |
|---|---|
| opcache ini removed (no OPcache) | ✅ exit 0 |
| `opcache.enable=1`, `opcache.jit=tracing`, `opcache.jit_buffer_size=256M` | ❌ SIGSEGV (139) |
| `opcache.enable=1`, **`opcache.jit=disable`**, `opcache.jit_buffer_size=0` | ✅ exit 0 |
| `opcache.enable_cli=0` | ✅ exit 0 |

→ **The tracing JIT is the trigger; the opcode cache alone is fine.**

Same image + identical opcache config across environments:

| Host CPU | AVX-512 | Runtime | Result |
|---|---|---|---|
| AMD EPYC 9V74 (Zen 4) | **yes** | Azure Container Apps (virtualized) | ❌ SIGSEGV |
| Intel Core Ultra 7 255HX (Arrow Lake) | **no** | local Docker, bare metal | ✅ works |
| x86-64 VM, Docker Compose | — | self-managed VM | ✅ works |

## Crash details

`gdb` on the deterministic in-container repro (binary is stripped; `execute_ex`/`zend_exec

```
Program received signal SIGSEGV, Segmentation fault.
0x000056a6bb3df512 in execute_ex ()
#0  0x000056a6bb3df512 in execute_ex ()
#1  0x000056a6bb3da62d in zend_execute ()
#2  0x000056a6bb448bbe in zend_execute_script ()
#3  0x000056a6bb2d28f4 in php_execute_script_ex ()
#4  0x000056a6bb44aead in ?? ()
#5  0x000056a6bae5fb42 in ?? ()
#6  0x00007a18905ebca8 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#7  0x00007a18905ebd65 in __libc_start_main () from /lib/x86_64-linux-gnu/libc.so.6
#8  0x000056a6bae60f41 in _start ()
```

Faulting instruction and registers:

```
=> 0x56a6bb3df512 <execute_ex+13762>:   cmp    (%rdx,%rax,1),%r12
rax 0x8     rdx 0x13949 (80201)     rip execute_ex+13762
effective read = rdx + rax*1 = 0x13951  (~80 KB)  -> SIGSEGV
```

`%rdx` (0x13949 ≈ 80,201) is used as a **base pointer** but holds a tiny value — every othis a normal `0x56a6…`/`0x7a18…` address. The read at `base + 8` ≈ `0x13951` is thesignature of a **run-time-cache / `zend_map_ptr` base that resolved to ~0**, so `base + slot_offset` collapses to just `slot_offset` (~80 KB). The fault address is consistently in the ~`0x138xx`–`0x139xx` range
across runs (deterministic, not random heap corruption).

**Working theory:** with the tracing JIT enabled, the per-process run-time-cache / `map_pt in **freshly-spawned CLI processes on this CPU/runtime**, and the interpreter then
dereferences `map_ptr_base(≈0) + offset`. Disabling JIT (opcode cache still on) avoids it uild (ZTS + JIT is less exercised), and the standout hardware difference between crashingand non-crashing hosts is **AVX-512 / Zen 4** (plus the virtualized Azure host). The faulting instruction itself is a plain `cmp` (not an AVX instruction), so this looks like a JIT codegen / `map_ptr`-setup interaction with the CPU/environment rather than an illegal-instruction fault.

Consistent asymmetry: a **long-lived server SAPI** (FrankenPHP worker) on the same ACA hosonfig serves requests fine — only **freshly-spawned CLI processes** crash, matching aper-process `map_ptr` base set up wrong once per CLI invocation.

## Environment

- **PHP:** 8.5.7 (cli) (built: Jun 24 2026) (**ZTS**); Zend Engine v4.5.7; Zend OPcache v8.5.7 (`Built by https://github.com/docker-library/php`).
- **OPcache at crash:** `enable=1`, `enable_cli=1`, `memory_consumption=1024M`, `max_accele_timestamps=0`, `jit=tracing`, `jit_buffer_size=256M`.
- **Image:** `dunglas/frankenphp:php8.5` (embeds docker-library php 8.5.7 ZTS), amd64.
- **Crashing host:** AMD **EPYC 9V74** 80-Core (cpu family 25, model 17, stepping 1, `micrposed, `hypervisor` flag set, `bugs: ... srso tsa`. Flags include `avx512f avx512dq
avx512bw avx512vl avx512vnni avx512_bf16 avx512vbmi avx512_vbmi2 avx512ifma avx512cd avx51s vpclmulqdq sha_ni`. Runtime: Azure Container Apps.
- **Non-crashing host (identical image/binary/config):** Intel **Core Ultra 7 255HX** (Arr12**, bare metal, local Docker. Also reproduced clean on a self-managed x86-64 VM.

## Limitations / further diagnostics I can run

- I can't `dmesg`/inspect the host on ACA (managed runtime); the backtrace is from `gdb` o
- The `php` binary is stripped (no symbols past `execute_ex`/`zend_execute*`). I can rebuild an unstripped / `--enable-debug` PHP 8.5.7 ZTS and re-run to provide `bt full`, `disassemble`, and the `EG()/CG()`
`map_ptr` field values — happy to, just say what you'd like.
- Three variables differ between crashing and non-crashing hosts (CPU vendor/µarch, **AVX-512**, virtualization), so I can't isolate the cause from two machines. Isolation tests I can run on the ACA host:
disable glibc's AVX-512 ifunc routines (`GLIBC_TUNABLES=glibc.cpu.hwcaps=-AVX512F,...`) wic memcpy/memmove vs. PHP JIT codegen apart; and try another AVX-512 host outside Azure.
- No framework-free minimal repro yet (only reproduces in-app on the affected host, though the workload is trivial — no migrations actually run); I can try to reduce it to a plain `php -r` script.

### PHP Version

8.5.7 (ZTS)

### Operating System

Linux amd64 — AMD EPYC 9V74 (Zen 4) under Azure Container Apps

### PHP Version

```plain
8.5.7 (ZTS)
```

### Operating System

_No response_