[php-src] Issue #24436: Tracing JIT: value of `$x = $y + 2` is int with raw double bits when $x is a reference to a typed float property
| From: | waroad | Date: | Mon, 19 Oct 2026 13:57:03 +0000 |
| Subject: | [php-src] Issue #24436: Tracing JIT: value of `$x = $y + 2` is int with raw double bits when $x is a reference to a typed float property | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-253028@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/24436
Author: waroad
With
opcache.jit=tracing, the value of an assignment expression $x = $y +
2 passed to a function is an int holding the raw bits of the double, when $x is
a reference to a typed float property and the function was first run with a reference
to an untyped property.
```php
<?php
class Box {public $v=1;public float $f=1;}
function sink($x) {return $x;}
function work(&$x,$y) {
return [sink($x=7),sink($x=$y+2),sink($x=3.5)];
}
$o=new Box;
for($j=0;$j<80;$j++) work($o->v,3);
for($j=0;$j<80;$j++) $r=work($o->f,3);
var_dump($r[1]);
```
```
php -n -d opcache.enable_cli=1 -d opcache.file_update_protection=0 -d opcache.jit_buffer_size=64M -d
opcache.jit=tracing input.php
```
```
int(4617315517961601024)
```
Expected float(5): the int is coerced to float when stored into the typed property, so
the expression has the value 5.0. The interpreter and opcache.jit=function print
float(5). 4617315517961601024 is 0x4014000000000000, the bit pattern of 5.0.
Found at c65321c70f7de5f4a4f810f1d23112374d92d1a7 (8.7.0-dev) and it still reproduces at
5ccc56b1e43f (latest upstream when checked). A debug build with ASan and UBSan (run with
opcache.protect_memory=1) and a release build both exit 0 with the wrong output above,
no assertion or sanitizer report.
Looks like the typed-reference branch of zend_jit_assign_to_variable in
ext/opcache/jit/zend_jit_ir.c: the helper stores the coerced double in the result slot, but the
trace types the result as long (from the earlier untyped run and from $y + 2), so the
double bits are read as an int. Possibly related open PR, not tested here: #18392.
I can send a patch if that helps.
Found with an LLM-based testing tool; I used Claude to reduce it and look for the cause.