Skip to content

Commit 6d75431

Browse files
nielsdoscharmitro
authored andcommitted
Fix phpGH-17654: Multiple classes using same trait causes function JIT crash
This test has two classes that use the same trait. In function JIT mode the same cache slot will be used. This causes problems because it is primed for the first class and then reused for the second class, resulting in an incorrect type check failure. The current check for a megamorphic trait call requires current_frame to not be NULL, but this is only set in tracing mode and not in function mode. This patch corrects the check. Closes phpGH-17660.
1 parent 30ce63f commit 6d75431

File tree

4 files changed

+48
-6
lines changed

4 files changed

+48
-6
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ PHP NEWS
1111
. Fixed bug GH-17618 (UnhandledMatchError does not take
1212
zend.exception_ignore_args=1 into account). (timwolla)
1313

14+
- Opcache:
15+
. Fixed bug GH-17654 (Multiple classes using same trait causes function
16+
JIT crash). (nielsdos)
17+
1418
- PHPDBG:
1519
. Partially fixed bug GH-17387 (Trivial crash in phpdbg lexer). (nielsdos)
1620
. Fix memory leak in phpdbg calling registered function. (nielsdos)

ext/opcache/jit/zend_jit_arm64.dasc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9174,9 +9174,9 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
91749174
func = call_info->callee_func;
91759175
}
91769176
if ((op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)
9177-
&& JIT_G(current_frame)
9178-
&& JIT_G(current_frame)->call
9179-
&& !JIT_G(current_frame)->call->func) {
9177+
&& (!JIT_G(current_frame) ||
9178+
!JIT_G(current_frame)->call ||
9179+
!JIT_G(current_frame)->call->func)) {
91809180
call_info = NULL; func = NULL; /* megamorphic call from trait */
91819181
}
91829182
}

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9897,9 +9897,9 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
98979897
func = call_info->callee_func;
98989898
}
98999899
if ((op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)
9900-
&& JIT_G(current_frame)
9901-
&& JIT_G(current_frame)->call
9902-
&& !JIT_G(current_frame)->call->func) {
9900+
&& (!JIT_G(current_frame) ||
9901+
!JIT_G(current_frame)->call ||
9902+
!JIT_G(current_frame)->call->func)) {
99039903
call_info = NULL; func = NULL; /* megamorphic call from trait */
99049904
}
99059905
}

ext/opcache/tests/jit/gh17654.phpt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
GH-17654 (Multiple classes using same trait causes function JIT crash)
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.jit=1214
7+
opcache.jit_buffer_size=16M
8+
--FILE--
9+
<?php
10+
trait TestTrait {
11+
public function addUnit(string $x) {
12+
self::addRawUnit($this, $x);
13+
}
14+
15+
public function addRawUnit(self $data, string $x) {
16+
var_dump($x);
17+
}
18+
}
19+
20+
class Test {
21+
use TestTrait;
22+
}
23+
24+
class Test2 {
25+
use TestTrait;
26+
}
27+
28+
function main()
29+
{
30+
(new Test2)->addUnit("test2");
31+
(new Test)->addUnit("test");
32+
}
33+
34+
main();
35+
?>
36+
--EXPECT--
37+
string(5) "test2"
38+
string(4) "test"

0 commit comments

Comments
 (0)