Commit ef589ce6698 for php.net
commit ef589ce6698405721e0e061142a6192e1bf8c2b0
Author: Arnaud Le Blanc <arnaud.lb@gmail.com>
Date: Mon May 11 13:35:28 2026 +0200
JIT: Fix TSSA of ZEND_FE_FETCH_R with key operand
During type inference of `foreach ($array as $key => $elem)`, in the case of
loops that didn't iterate during tracing, we copy the use var info of $elem
to the def, but we forgot to do the same for $key.
Fixes GH-22004
Closes GH-22008
diff --git a/NEWS b/NEWS
index c2767fd3c30..8dea2348ff3 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,8 @@ PHP NEWS
- Opcache:
. Fixed tracing JIT crash when a VM interrupt is handled during an observed
user function call. (Levi Morrison)
+ . Fixed bug GH-22004 (Assertion failure at ext/opcache/jit/zend_jit_trace.c).
+ (Arnaud)
- OpenSSL:
. Fix compatibility issues with OpenSSL 4.0. (jordikroon, Remi)
diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c
index 1237d1b7a42..da97d102f20 100644
--- a/ext/opcache/jit/zend_jit_trace.c
+++ b/ext/opcache/jit/zend_jit_trace.c
@@ -2315,6 +2315,9 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
if (ssa_ops[idx].op2_use >= 0 && ssa_ops[idx].op2_def >= 0) {
ssa_var_info[ssa_ops[idx].op2_def] = ssa_var_info[ssa_ops[idx].op2_use];
}
+ if (ssa_ops[idx].result_use >= 0 && ssa_ops[idx].result_def >= 0) {
+ ssa_var_info[ssa_ops[idx].result_def] = ssa_var_info[ssa_ops[idx].result_use];
+ }
} else {
if (zend_update_type_info(op_array, tssa, script, (zend_op*)opline, ssa_ops + idx, ssa_opcodes, optimization_level) == FAILURE) {
// TODO:
diff --git a/ext/opcache/tests/jit/gh22004.phpt b/ext/opcache/tests/jit/gh22004.phpt
new file mode 100644
index 00000000000..bb60868a269
--- /dev/null
+++ b/ext/opcache/tests/jit/gh22004.phpt
@@ -0,0 +1,63 @@
+--TEST--
+GH-22004: ZEND_FE_FETCH_R with key operand
+--CREDITS--
+YuanchengJiang
+--FILE--
+<?php
+
+function doRandom($iter) {
+ for ($i = 0; $i < $iter; $i++) {
+ $lines = [];
+ for ($j = 0; $j < $nLines; $j++) {
+ $lines[] = $line;
+ }
+ foreach ($lines as $i => $line) {
+ }
+ }
+}
+$iter = 20;
+doRandom($iter);
+
+?>
+==DONE==
+--EXPECTF--
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+
+Warning: Undefined variable $nLines in %s on line %d
+==DONE==