Skip to content

Tracing JIT: keep the SEND_VAL type guard after assigning to a reference #24436

Closed

Description

@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
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 c65321c (8.7.0-dev) and it still reproduces at 5ccc56b (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.

Activity

  1. ndossche commented on Oct 23, 2026

    @ndossche
    Member

    I can send a patch if that helps.

    Feel free to do so and tag me ! 🙂

  2. changed the title [-]Tracing JIT: value of `$x = $y + 2` is int with raw double bits when $x is a reference to a typed float property[/-] [+]Tracing JIT: keep the SEND_VAL type guard after assigning to a reference[/+] on Oct 25, 2026
  3. added a commit that references this issue on Oct 25, 2026
    d5ab360
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions