Tracing JIT loses the result of a dynamic method call traced with Closure::__invoke (8.5 regression)
Los mantenedores suelen responder en 1 día
Evaluación
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Aptitud para principiantes
- 8/100
Línea de trabajo
The payload points at the tracing JIT path around zend_execute in zend_vm_execute.h and the call return handling in ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER, with the valgrind traces naming zend_vm_stack_new_page as where the never-written memory comes from. Start by reproducing with the opcache.jit=tracing command in the issue, then compare against opcache.jit=function. Done would mean the result slot is written before it is read and the output is bool(false), with valgrind clean outside the JIT compiler.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Description
With the tracing JIT, the result of a dynamic method call
$o->{$m}()is lost when the call site was first traced while callingClosure::__invoke. The caller then reads whatever is left in the result slot.
The following code:
<?php
class A { function m() { return false; } }
function call($o, $m) { return $o->{$m}(); }
function every($items, $m) {
foreach ($items as $i) { if (!call($i, $m)) return false; }
return true;
}
$c = function () { return false; };
for ($i = 0; $i < 2000; $i++) every([$c], '__invoke');
var_dump(call(new A, 'm'));
php -n -d opcache.enable_cli=1 -d opcache.jit_buffer_size=64M -d opcache.jit=tracing test.php
Resulted in this output:
UNKNOWN:0
But I expected this output instead:
bool(false)
- Wrong on 8.5.0, 8.5.11 and PHP-8.5 @ bbfdd69f, with
opcache.jit=tracingand with1054.- Correct with
opcache.jit=function, with the JIT off, and on 8.4.26 and 8.3.35 (tracing).- Not fixed by #23611 (GH-23572).
- The warm-up through
Closure::__invokeis required: warming upcall()with a plain object's method does not reproduce it. The earlyreturn falseinevery()is also required.
Valgrind on PHP-8.5 @ bbfdd69f (
-g -O2,USE_ZEND_ALLOC=0 valgrind --smc-check=all --track-origins=yes). Leaving out their_sparse_set_inreports from the JIT compiler, every remaining error is about the same never-written VM stack memory: it is used in JIT code, printed byvar_dump(), then destroyed:
Conditional jump or move depends on uninitialised value(s)
at 0x11800ADF: ???
by 0x8C4E9F: zend_execute (zend_vm_execute.h:122008)
by 0x9270D5: zend_execute_script (zend.c:1985)
Uninitialised value was created by a heap allocation
by 0x88CAE8: zend_vm_stack_new_page (zend_execute.h:327)
by 0x88CAE8: zend_vm_stack_init (zend_execute.c:195)
Conditional jump or move depends on uninitialised value(s)
at 0x7668EE: php_var_dump (var.c:130)
by 0x7672E0: zif_var_dump (var.c:257)
by 0x8C0273: ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER (zend_vm_execute.h:1360)
Uninitialised value was created by a heap allocation
by 0x88CAE8: zend_vm_stack_new_page (zend_execute.h:327)
by 0x88CAE8: zend_vm_stack_init (zend_execute.c:195)
Conditional jump or move depends on uninitialised value(s)
at 0x8C02AE: zval_ptr_dtor_nogc (zend_variables.h:35)
by 0x8C02AE: zend_vm_stack_free_args (zend_execute.h:405)
by 0x8C02AE: ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER (zend_vm_execute.h:1379)
Uninitialised value was created by a heap allocation
by 0x88CAE8: zend_vm_stack_new_page (zend_execute.h:327)
by 0x88CAE8: zend_vm_stack_init (zend_execute.c:195)
Real-world impact: Laravel's
HigherOrderCollectionProxyclosure has this shape. Telescope calls it with->every->__invoke($entry)for its filters, and then with->partition->isException()when storing entries. On a freshlaravel/laravel13.35 +laravel/telescope5.25 install (officialphp:8.5.11-cliimage, default JIT settings apart fromopcache.jit=tracing), an artisan command that logs, uses the cache and runs queries in a loop crashes withzend_mm_heap corruptedor SIGSEGV withAPP_ENV=production. It crashed in 28 of 32 runs from 250 iterations up. It does not crash with function JIT, with the JIT off, or on 8.4.26.
PHP Version
PHP 8.5.11 (cli) (built: Oct 6 2026 01:22:31) (NTS)
Copyright (c) The PHP Group
Built by https://github.com/docker-library/php
Zend Engine v4.5.11, Copyright (c) Zend Technologies
with Zend OPcache v8.5.11, Copyright (c), by Zend Technologies
Operating System
Debian 13 (official Docker image), x86_64
- Lenguaje dominante
- C
- Estrellas
- 40.7k
- Forks
- 8.3k
- Merge medio
- 2 d 20 h
- PR fusionados (30 d)
- 147
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de php/php-src
-
sapi/fpm/tests/tester.inc can send SIGUSR2 to pid 0, killing run-tests.phpPosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. AbiertoBug Status: Needs Triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Los mantenedores suelen responder en 1 día
-
zend_set_local_var() overwrites existing compiled variable (CV) zval without calling zval_ptr_dtor()Posiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. AbiertoBug Status: Needs Triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Los mantenedores suelen responder en 1 día
-
Case-insensitive substr_compare, ksort, krsort are still locale-dependentPosiblemente ocupada @lazerg la tomó hace 4 días. AbiertoBug Extension: standard Status: Verified
Dificultad 2/5 1-3 horas Aptitud para principiantes 73/100
php/php-src#24552 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
master: part of the mbstring bailout fix got lost in a mergePosiblemente ocupada @lazerg la tomó hace 4 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Los mantenedores suelen responder en 1 día
Todos los issues de php/php-src
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
HexaCluster/credcheck#86 ·
-
Wheels for Python 3.15Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 66/100
mongodb/winkerberos#175 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 63/100
raspberrypi/linux#7718 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
AOMediaCodec/SVT-AV1#3320 ·