Skip to content

Commit 60702fa

Browse files
committed
Merge branch 'PHP-8.6'
* PHP-8.6: Fix GH-17626: JIT corrupts opline handler when blacklisting root trace
2 parents 26e588f + 1228a4c commit 60702fa

5 files changed

Lines changed: 93 additions & 1 deletion

File tree

‎ext/opcache/jit/zend_jit_trace.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8890,7 +8890,7 @@ int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf
88908890
SHM_UNPROTECT();
88918891
zend_jit_unprotect();
88928892

8893-
((zend_op*)opline)->handler =
8893+
((zend_op*)(t->opline))->handler =
88948894
ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->orig_handler;
88958895

88968896
ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags &= ~ZEND_JIT_TRACE_JITED;

‎ext/opcache/tests/jit/gh17626.inc‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?php
2+
function gh17626_callee(string $s) { return strtoupper($s); }

‎ext/opcache/tests/jit/gh17626.phpt‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
GH-17626: Opline handler corrupted when a root trace is blacklisted at the max_root_traces limit (fails with --repeat 2)
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.file_update_protection=0
7+
opcache.revalidate_freq=0
8+
opcache.jit=tracing
9+
opcache.jit_buffer_size=16M
10+
opcache.jit_hot_func=2
11+
opcache.jit_hot_loop=255
12+
opcache.jit_hot_return=255
13+
opcache.jit_hot_side_exit=255
14+
opcache.jit_max_root_traces=2
15+
--EXTENSIONS--
16+
opcache
17+
--FILE--
18+
<?php
19+
namespace GH17626;
20+
21+
// In --repeat 2 the callee is recompiled after the first run, so the function
22+
// guard in the trace compiled for caller() fails with ZEND_JIT_EXIT_INVALIDATE.
23+
24+
require __DIR__ . '/gh17626.inc';
25+
26+
function caller(string $s) {
27+
return gh17626_callee($s) . $s;
28+
}
29+
30+
caller('a');
31+
caller('a');
32+
caller('a');
33+
echo caller('a'), "\n";
34+
echo caller('b'), "\n";
35+
36+
touch(__DIR__ . '/gh17626.inc');
37+
opcache_invalidate(__DIR__ . '/gh17626.inc', true);
38+
?>
39+
--EXPECT--
40+
Aa
41+
Bb
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?php
2+
class GH17626GrandParent {}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
--TEST--
2+
GH-17626: Opline handler corrupted when a root trace is blacklisted at the max_root_traces limit
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.file_update_protection=0
7+
opcache.jit=tracing
8+
opcache.jit_buffer_size=16M
9+
opcache.jit_hot_func=2
10+
opcache.jit_hot_loop=255
11+
opcache.jit_hot_return=255
12+
opcache.jit_hot_side_exit=255
13+
opcache.jit_max_root_traces=2
14+
--EXTENSIONS--
15+
opcache
16+
--FILE--
17+
<?php
18+
require __DIR__ . '/gh17626_002.inc';
19+
20+
class ParentA extends GH17626GrandParent { public static function m() { return 'A'; } }
21+
class ParentB extends GH17626GrandParent { public static function m() { return 'B'; } }
22+
23+
trait T {
24+
public function run(string $s) {
25+
return parent::m() . $s;
26+
}
27+
}
28+
29+
class A extends ParentA { use T; }
30+
class B extends ParentB { use T; }
31+
32+
$a = new A;
33+
$b = new B;
34+
35+
$a->run('x');
36+
$a->run('x');
37+
$a->run('x');
38+
echo $a->run('x'), "\n";
39+
echo $b->run('y'), "\n";
40+
echo $b->run('y'), "\n";
41+
echo $a->run('x'), "\n";
42+
?>
43+
--EXPECT--
44+
Ax
45+
By
46+
By
47+
Ax

0 commit comments

Comments
 (0)