[php-src] Issue #24798: PHP 8.5.12 tracing JIT produces incorrect sums when DivisionByZeroError is caught inside a loop
| From: | mitchellvanw | Date: | Tue, 27 Oct 2026 19:33:09 +0000 |
| Subject: | [php-src] Issue #24798: PHP 8.5.12 tracing JIT produces incorrect sums when DivisionByZeroError is caught inside a loop | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-253250@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/24798
Author: mitchellvanw
## Description
The explanatory paragraphs marked as blockquotes were drafted with OpenAI Codex. A second Codex
agent independently checked the reproducer, commands, and outputs by running them locally against
the official Docker images.
> With tracing JIT and all four hot counters set to 1, the following program produces incorrect
> sums after division by zero is caught inside a loop. It reproduces in the official PHP 8.5.12 CLI
> Docker images on Linux ARM64 and Linux AMD64 (the latter under Docker Desktop emulation on an ARM64
> host). Disabling JIT gives the expected output on both. The failure also occurs with the OPcache
> optimizer disabled, as in the command below.
### Reproducer
Save as
repro.php:
```php
<?php
function f($n, $k) {
$s = 0.0;
for ($i = 0; $i < $n; $i++) {
try { $s += 1.0 / (($i - 5) * $k); } catch (DivisionByZeroError $e) { $s += 100; }
}
return $s;
}
echo f(12, 3), " ", f(12, intdiv(PHP_INT_MAX, 2)), "\n";
```
### Command
```sh
docker run --rm --platform linux/arm64 --network none \
--mount type=bind,source="$PWD/repro.php",target=/repro.php,readonly \
php:8.5.12-cli@sha256:635a4b998025ab269194639a5549c6fdcd9b4f88ec8cd761b092de8653d40663 \
php -n \
-d opcache.enable_cli=1 \
-d opcache.file_update_protection=0 \
-d opcache.jit_buffer_size=64M \
-d opcache.jit=tracing \
-d opcache.optimization_level=0 \
-d opcache.jit_hot_loop=1 \
-d opcache.jit_hot_func=1 \
-d opcache.jit_hot_return=1 \
-d opcache.jit_hot_side_exit=1 \
/repro.php
```
### Actual output
- **Linux ARM64:** tracing JIT prints 500.75 600.
- **Linux AMD64, under emulation:** tracing JIT prints 498.61111111111 600.
- **JIT disabled, both architectures:** correctly prints 100.05555555556 100.
> There is exactly one zero divisor per call, at $i == 5, so the
> catch should add 100 exactly once. In exact real arithmetic, the terms for $i - 5 ==
> -5..-1 cancel those for 1..5, leaving
> 100 + 1/(6*$k). PHP evaluates and accumulates these terms using
> floating-point arithmetic; the JIT-off output above is the observed PHP result. For the second call,
> each nonzero reciprocal has magnitude at most about 2.17e-19, far
> below the spacing of doubles near 100.
### Controls
> Both architectures give the same respective outputs with
> opcache.optimization_level=0x7FFEBFFF and
> opcache.optimization_level=0. Each of the eight combinations (two
> architectures, JIT on/off, optimizer on/off) was run three times using the command above with only
> those settings changed: 24 runs total, all with the respective output shown above, exit status 0,
> and empty stderr. Separate diagnostic invocations with the same PHP settings used
> opcache_get_status(false)['jit'] and confirmed
> on => true, kind => 5 for
> tracing, and on => false for the JIT-off control.
> The same failure also reproduces with Homebrew PHP 8.5.12 on macOS ARM64 (WêU×TMùпÕ|
> N500.75 600). On that build, using its default hot thresholds
> (loop=61, func=127,
> return=8, side_exit=8) makes this
> short reproducer print the correct result; this report uses thresholds of 1 to trigger compilation.
> No regression boundary or underlying code-generation cause has been established.
### Possibly related
> https://github.com/php/php-src/issues/24445 reports stale or
> undefined locals when an internal function throws and execution enters a catch block. This
> reproducer throws from the / operator instead. The symptoms may be
> related, but this report does not establish that they have the same cause.
## PHP Version
Official Docker image: docker.io/library/php:8.5.12-cli.
Multi-platform image digest:
```text
sha256:635a4b998025ab269194639a5549c6fdcd9b4f88ec8cd761b092de8653d40663
```
Linux ARM64, php -n -v:
```text
PHP 8.5.12 (cli) (built: Oct 21 2026 15:53:40) (NTS)
Copyright (c) The PHP Group
Built by https://github.com/docker-library/php
Zend Engine v4.5.12, Copyright (c) Zend Technologies
with Zend OPcache v8.5.12, Copyright (c), by Zend Technologies
```
Linux AMD64, php -n -v:
```text
PHP 8.5.12 (cli) (built: Oct 21 2026 15:48:53) (NTS)
Copyright (c) The PHP Group
Built by https://github.com/docker-library/php
Zend Engine v4.5.12, Copyright (c) Zend Technologies
with Zend OPcache v8.5.12, Copyright (c), by Zend Technologies
```
## Operating System
> Linux 7.0.14-linuxkit through Docker Desktop 4.94.0 on a macOS
> ARM64 host. ARM64 container runs natively in the Linux VM; AMD64 container runs under emulation.
> Native AMD64 hardware has not been tested.