beyondcode / beyondcode/herd-community
[Bug]: Static PHP 8.5 x86_64 (herd-lite) SIGILL / "Illegal instruction" (exit 132) on CPUs without ADX (e.g. Intel Haswell i7-4790) — GMP built with ADX enabled
- Dominant language
- No language data
- Stars
- 122
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
### Platform
macOS
### Operating system version
Linux 6.14.8-2-pve (Proxmox), x86_64
### System architecture
Intel (x86)
### Herd Version
laravel 13
### PHP Version
php 8.5.0 (cli), NTS, Nov 20 2025
### Bug description
## Summary
A prebuilt static PHP 8.5.0 binary from your distribution crashes with **SIGILL / Illegal instruction (exit 132)** on any CPU that lacks the ADX instruction set — for example an **Intel Core i7-4790 (Haswell)**. The crash is inside **GMP 6.3.0's big-number multiplication** (`mpn_mul_1`), which was compiled with **ADX (`adcx`/`adox`) and BMI2 (`mulx`) enabled** and shipped without a runtime CPUID gate. Haswell has BMI2 but **no ADX**, so the ADX instruction stream faults.
This is a broad compatibility problem: it will crash on every pre-Broadwell Intel (Sandy Bridge → Haswell) and many older/lower-end AMD parts, on a completely ordinary `gmp_mul()` call.
## Environment
- **Host CPU:** Intel Core i7-4790 @ 3.60GHz (Haswell)
- has: `bmi1 bmi2 avx2 sse4_2` — **`adx` ABSENT**
- **OS:** Linux 6.14.8-2-pve (Proxmox), x86_64
- **Binary:** `php` 8.5.0 (cli), NTS, `x86_64-linux-musl-gcc`, **static**, stripped
- Built by Beyond Code for php.new, Nov 20 2025
- GMP **6.3.0** (static), OpenSSL 3.6.0 (static)
- **Thread safety:** disabled
## Root cause (build-time)
Your static build compiled the bundled GMP with ADX enabled (the shipped object contains `adcx`/`adox`), but shipping it that way is only safe if a **runtime CPUID check** selects the ADX path; otherwise it faults on any non-ADX CPU. The GMP code path here has BMI2+ADX instructions reachable unconditionally on the affected CPUs.
## Suggested fix
- Rebuild GMP for the static PHP distribution **without ADX** — most simply `--disable-assembly` (GMP then uses its portable C path), or ensure the compile flags do not enable `-madx`/`-march` for the GMP low-level multiply objects.
- Ideally ensure GMP's runtime CPU detection (its `.asm` `mulx`/ADX variants gate on the CPUID ADX bit) is actually being used, rather than a fixed instruction stream.
- Re-test on a Haswell-class CPU (i7-4xxx / Xeon E3 v3) after rebuilding.
## Impact
Any deployment of this static PHP build on hardware older than ADX support (roughly pre-2015 Intel Broadwell and many older AMD CPUs) will crash during ordinary big-number arithmetic (`gmp_mul`, and any library built on it, e.g. phpseclib `BigInteger`). This makes the distributed binary unusable on a large class of still-common servers/VMs.
---
*Separate root-cause report filed with GMP upstream.
### Steps to reproduce
## Reproducer (self-contained, no external libs)
```php
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the static PHP distribution build configuration and GMP 6.3.0 compilation settings, then run the supplied repro_gmp.php script on a Haswell-class CPU. Check whether ADX instructions are enabled without runtime gating, and verify that a rebuilt binary completes gmp_mul without SIGILL on CPUs lacking ADX.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- php
- Domain
- build-system
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100