[php-src] master: Merge branch 'PHP-8.4' into PHP-8.5
| From: | ndossche | Date: | Wed, 07 Oct 2026 20:26:40 +0000 |
| Subject: | [php-src] master: Merge branch 'PHP-8.4' into PHP-8.5 | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-142073@lists.php.net to get a copy of this message | ||
Author: ndossche (ndossche)
Date: 2026-10-07T22:26:04+02:00
Commit: https://github.com/php/php-src/commit/c2e9c098f39e5514c73861d723f6fbd1efdfe775
Raw diff: https://github.com/php/php-src/commit/c2e9c098f39e5514c73861d723f6fbd1efdfe775.diff
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4:
Fix GH-17626: JIT corrupts opline handler when blacklisting root trace
Changed paths:
A ext/opcache/tests/jit/gh17626.inc
A ext/opcache/tests/jit/gh17626.phpt
A ext/opcache/tests/jit/gh17626_002.inc
A ext/opcache/tests/jit/gh17626_002.phpt
M NEWS
M ext/opcache/jit/zend_jit_trace.c
Diff:
diff --git a/NEWS b/NEWS
index ef5c9882ce99..061ecfdf74ce 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,10 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 8.5.13
+- Opcache:
+ . Fixed bug GH-17626 (JIT corrupts an opline handler when blacklisting a
+ root trace at the opcache.jit_max_root_traces limit, causing spurious
+ "Too few arguments" errors and crashes). (RV7PR)
22 Oct 2026, PHP 8.5.12
diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c
index d78baf3838c3..53235702fa44 100644
--- a/ext/opcache/jit/zend_jit_trace.c
+++ b/ext/opcache/jit/zend_jit_trace.c
@@ -8863,7 +8863,7 @@ int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num,
zend_jit_registers_buf
SHM_UNPROTECT();
zend_jit_unprotect();
- ((zend_op*)opline)->handler =
+ ((zend_op*)(t->opline))->handler =
ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->orig_handler;
ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags &=
~ZEND_JIT_TRACE_JITED;
diff --git a/ext/opcache/tests/jit/gh17626.inc b/ext/opcache/tests/jit/gh17626.inc
new file mode 100644
index 000000000000..307a47ad2943
--- /dev/null
+++ b/ext/opcache/tests/jit/gh17626.inc
@@ -0,0 +1,2 @@
+<?php
+function gh17626_callee(string $s) { return strtoupper($s); }
diff --git a/ext/opcache/tests/jit/gh17626.phpt b/ext/opcache/tests/jit/gh17626.phpt
new file mode 100644
index 000000000000..dbd917935c5f
--- /dev/null
+++ b/ext/opcache/tests/jit/gh17626.phpt
@@ -0,0 +1,41 @@
+--TEST--
+GH-17626: Opline handler corrupted when a root trace is blacklisted at the max_root_traces limit
(fails with --repeat 2)
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.file_update_protection=0
+opcache.revalidate_freq=0
+opcache.jit=tracing
+opcache.jit_buffer_size=16M
+opcache.jit_hot_func=2
+opcache.jit_hot_loop=255
+opcache.jit_hot_return=255
+opcache.jit_hot_side_exit=255
+opcache.jit_max_root_traces=2
+--EXTENSIONS--
+opcache
+--FILE--
+<?php
+namespace GH17626;
+
+// In --repeat 2 the callee is recompiled after the first run, so the function
+// guard in the trace compiled for caller() fails with ZEND_JIT_EXIT_INVALIDATE.
+
+require __DIR__ . '/gh17626.inc';
+
+function caller(string $s) {
+ return gh17626_callee($s) . $s;
+}
+
+caller('a');
+caller('a');
+caller('a');
+echo caller('a'), "\n";
+echo caller('b'), "\n";
+
+touch(__DIR__ . '/gh17626.inc');
+opcache_invalidate(__DIR__ . '/gh17626.inc', true);
+?>
+--EXPECT--
+Aa
+Bb
diff --git a/ext/opcache/tests/jit/gh17626_002.inc b/ext/opcache/tests/jit/gh17626_002.inc
new file mode 100644
index 000000000000..8a12c7ae9fb6
--- /dev/null
+++ b/ext/opcache/tests/jit/gh17626_002.inc
@@ -0,0 +1,2 @@
+<?php
+class GH17626GrandParent {}
diff --git a/ext/opcache/tests/jit/gh17626_002.phpt b/ext/opcache/tests/jit/gh17626_002.phpt
new file mode 100644
index 000000000000..a0f4792f5404
--- /dev/null
+++ b/ext/opcache/tests/jit/gh17626_002.phpt
@@ -0,0 +1,47 @@
+--TEST--
+GH-17626: Opline handler corrupted when a root trace is blacklisted at the max_root_traces limit
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.file_update_protection=0
+opcache.jit=tracing
+opcache.jit_buffer_size=16M
+opcache.jit_hot_func=2
+opcache.jit_hot_loop=255
+opcache.jit_hot_return=255
+opcache.jit_hot_side_exit=255
+opcache.jit_max_root_traces=2
+--EXTENSIONS--
+opcache
+--FILE--
+<?php
+require __DIR__ . '/gh17626_002.inc';
+
+class ParentA extends GH17626GrandParent { public static function m() { return 'A'; } }
+class ParentB extends GH17626GrandParent { public static function m() { return 'B'; } }
+
+trait T {
+ public function run(string $s) {
+ return parent::m() . $s;
+ }
+}
+
+class A extends ParentA { use T; }
+class B extends ParentB { use T; }
+
+$a = new A;
+$b = new B;
+
+$a->run('x');
+$a->run('x');
+$a->run('x');
+echo $a->run('x'), "\n";
+echo $b->run('y'), "\n";
+echo $b->run('y'), "\n";
+echo $a->run('x'), "\n";
+?>
+--EXPECT--
+Ax
+By
+By
+Ax