[php-src] master: Merge branch 'PHP-8.5'

Arnaud Le Blanc <[email protected]> Wed, 22 Jul 2026 07:32:29 +0000
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Arnaud Le Blanc (arnaud-lb)
Date: 2026-07-22T09:32:17+02:00

Commit: https://github.com/php/php-src/commit/417e3d7269a8b11fb7632977b9e0074bc14d2eae
Raw diff: https://github.com/php/php-src/commit/417e3d7269a8b11fb7632977b9e0074bc14d2eae.diff

Merge branch 'PHP-8.5'

* PHP-8.5:
  Clear ZREG_TYPE_ONLY flag for in-register vars in zend_jit_snapshot_handler() (#22764)

Changed paths:
  A  ext/opcache/tests/jit/gh22763.phpt
  M  ext/opcache/jit/zend_jit_ir.c
  M  ext/opcache/jit/zend_jit_trace.c


Diff:

diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c
index f3dbcc84c124..8f6804cb8915 100644
--- a/ext/opcache/jit/zend_jit_ir.c
+++ b/ext/opcache/jit/zend_jit_ir.c
@@ -858,12 +858,14 @@ void *zend_jit_snapshot_handler(ir_ctx *ctx, ir_ref snapshot_ref, ir_insn *snaps
 							t->stack_map[t->exit_info[exit_point].stack_offset + var].flags = ZREG_TYPE_ONLY;
 						} else {
 							if ((exit_flags & ZEND_JIT_EXIT_FIXED)
-							 && t->stack_map[t->exit_info[exit_point].stack_offset + var].reg != IR_REG_NUM(reg)) {
+							 && (t->stack_map[t->exit_info[exit_point].stack_offset + var].reg != IR_REG_NUM(reg)
+							 || (t->stack_map[t->exit_info[exit_point].stack_offset + var].flags & ~(ZREG_LOAD|ZREG_STORE|ZREG_LAST_USE)))) {
 								exit_point = zend_jit_duplicate_exit_point(ctx, t, exit_point, snapshot_ref);
 								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 = IR_REG_NUM(reg);
+							t->stack_map[t->exit_info[exit_point].stack_offset + var].flags &= (ZREG_LOAD|ZREG_STORE|ZREG_LAST_USE);
 						}
 					} else {
 						if ((exit_flags & ZEND_JIT_EXIT_FIXED)
diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c
index 77bfaa03473a..505427890129 100644
--- a/ext/opcache/jit/zend_jit_trace.c
+++ b/ext/opcache/jit/zend_jit_trace.c
@@ -3571,6 +3571,8 @@ static int zend_jit_trace_deoptimization(
 				}
 			}
 		} else if (STACK_FLAGS(parent_stack, i) == ZREG_TYPE_ONLY) {
+			ZEND_ASSERT(reg == ZREG_NONE);
+
 			uint8_t type = STACK_TYPE(parent_stack, i);
 
 			if (!zend_jit_store_type(jit, i, type)) {
diff --git a/ext/opcache/tests/jit/gh22763.phpt b/ext/opcache/tests/jit/gh22763.phpt
new file mode 100644
index 000000000000..67d7caa308ed
--- /dev/null
+++ b/ext/opcache/tests/jit/gh22763.phpt
@@ -0,0 +1,58 @@
+--TEST--
+GH-22763: JIT fails to clear ZREG_TYPE_ONLY after setting reg
+--FILE--
+<?php
+
+function findMiddleSnake(array $a, int $aLo, int $aHi, array $b, int $bLo, int $bHi): array
+{
+    $n          = $aHi - $aLo;
+    $m          = $bHi - $bLo;
+    $delta      = $n - $m;
+    $deltaIsOdd = ($delta & 1) !== 0;
+    $offset     = 4;
+    $size       = 2 * 3 + 2;
+    $vf         = array_fill(0, $size, 0);
+    $vb         = array_fill(0, $size, 0);
+
+    $d = 2;
+    $x = 0;
+
+    for ($k = -$d; $k <= $d; $k += 2) {
+        if ($k === -$d || ($k !== $d && $vb[$offset + $k - 1] < $vb[$offset + $k + 1])) {
+            $x = $vb[$offset + $k + 1];
+            var_dump($x);
+        } else {
+            $x = $vb[$offset + $k - 1] + 1;
+        }
+
+        $y  = $x - $k;
+        $xs = $x;
+        $ys = $y;
+
+        while ($x < $n && $y < $m && $a[$aLo + $n - 1 - $x] === $b[$bLo + $m - 1 - $y]) {
+            $x++;
+            $y++;
+        }
+
+        $vb[$offset + $k] = $x;
+
+        if (!$deltaIsOdd) {
+            $kf = $delta - $k;
+
+            if ($kf >= -$d && $kf <= $d && $vf[$offset + $kf] + $vb[$offset + $k] >= $n) {
+                return [$n - $x, $m - $y, $n - $xs, $m - $ys];
+            }
+        }
+    }
+
+    return [];
+}
+
+$from = [3,2,1];
+$to = [1,99,3];
+findMiddleSnake($from, 0, count($from), $to, 0, count($to));
+?>
+--EXPECTF--
+int(0)
+
+Warning: Undefined array key 3 in %s on line %d