Commit 9f33bff0906 for php.net
commit 9f33bff09067fd3e5807df23a56b0560dca05b47
Author: Arnaud Le Blanc <arnaud.lb@gmail.com>
Date: Wed Mar 25 19:01:49 2026 +0100
Reset stackmap reg
Add a missing `t->stack_map[...].reg = ZREG_NONE` in `zend_jit_snapshot_handler`.
This is needed when reg is `ZREG_NONE`, otherwise side traces will have wrong
assumptions.
Fixes GH-21158
Closes GH-21531
diff --git a/NEWS b/NEWS
index 0e042bb864c..d87ceb7d818 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,10 @@ PHP NEWS
- Iconv:
. Fixed bug GH-17399 (iconv memory leak on bailout). (iliaal)
+- Opcache:
+ . Fixed bug GH-21158 (JIT: Assertion jit->ra[var].flags & (1<<0) failed in
+ zend_jit_use_reg). (Arnaud)
+
- SPL:
. Fixed bug GH-21499 (RecursiveArrayIterator getChildren UAF after parent
free). (Girgias)
diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c
index b87abad4361..2bad605c537 100644
--- a/ext/opcache/jit/zend_jit_ir.c
+++ b/ext/opcache/jit/zend_jit_ir.c
@@ -835,6 +835,7 @@ void *zend_jit_snapshot_handler(ir_ctx *ctx, ir_ref snapshot_ref, ir_insn *snaps
addr = (void*)zend_jit_trace_get_exit_addr(exit_point);
exit_flags &= ~ZEND_JIT_EXIT_FIXED;
}
+ t->stack_map[t->exit_info[exit_point].stack_offset + var].reg = ZREG_NONE;
t->stack_map[t->exit_info[exit_point].stack_offset + var].flags = ZREG_TYPE_ONLY;
}
} else if (!(exit_flags & ZEND_JIT_EXIT_FIXED)) {
diff --git a/ext/opcache/tests/jit/gh21158.phpt b/ext/opcache/tests/jit/gh21158.phpt
new file mode 100644
index 00000000000..89afd058c66
--- /dev/null
+++ b/ext/opcache/tests/jit/gh21158.phpt
@@ -0,0 +1,49 @@
+--TEST--
+GH-21158: Assertion jit->ra[var].flags & (1<<0) failed in zend_jit_use_reg
+--CREDITS--
+YuanchengJiang
+--EXTENSIONS--
+opcache
+--INI--
+opcache.jit=1254
+--FILE--
+<?php
+define('ROW', 10);
+define('COL', 10);
+function count_live_neighbors($board, $row, $col) {
+ $live_neighbors = 0;
+ if ($col + 1 < COL && $board[$row][$col + 1] == 1) $live_neighbors++;
+ if ($row - 1 >= 0 && $col - 1 >= 0 && $board[$row - 1][$col - 1] == 1) $live_neighbors++;
+ if ($row >= 1 && $col + 1 < COL && $board[$row - 1][$col + 1] == 1) $live_neighbors++;
+ return $live_neighbors;
+}
+$board = [
+ [1,1,0,0,1,1,1,1,1,0],
+ [0,1,0,1,1,0,0,1,0,0],
+ [0,1,0,0,1,0,0,0,1,0],
+ [0,0,1,1,1,1,1,0,0,0],
+ [1,1,1,1,1,1,0,1,1,0],
+ [0,1,0,0,1,1,1,0,1,0],
+ [0,1,1,0,1,1,1,1,0,0],
+ [1,1,0,0,0,0,1,1,1,0],
+ [1,0,0,1,1,0,1,1,0,1],
+ [0,0,1,1,1,0,1,1,0,1],
+];
+for ($i = 0; $i < ROW; $i++) {
+ for ($j = 0; $j < COL; $j++) {
+ echo count_live_neighbors($board, $i, $j), ",";
+ }
+ echo "\n";
+}
+?>
+--EXPECT--
+1,0,0,1,1,1,1,1,0,0,
+2,1,2,2,1,2,3,2,1,1,
+2,0,2,2,1,1,1,1,1,0,
+1,1,2,2,1,2,0,1,0,1,
+1,2,2,3,3,2,2,2,0,0,
+2,2,2,3,3,2,2,2,1,1,
+2,1,1,2,2,3,2,2,0,1,
+2,1,1,2,1,3,3,2,1,0,
+1,1,2,1,0,2,2,2,2,1,
+0,2,2,2,1,3,2,1,3,0,