Skip to content

Commit 1c483f0

Browse files
committed
Fix phpGH-16572: Incorrect result with reflection in low-trigger JIT
When a recursive call happens with invalid arguments, the maximum valid arguments are computed and stored in `num_args`, but the RECV entry block we jump to is `call_num_args` instead. This can skip argument validation checks. Fix this by using `num_args` instead.
1 parent d8e5166 commit 1c483f0

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

ext/opcache/jit/zend_jit_ir.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9871,6 +9871,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
98719871
if ((!func || func->type == ZEND_USER_FUNCTION)
98729872
&& opline->opcode != ZEND_DO_ICALL) {
98739873
bool recursive_call_through_jmp = 0;
9874+
uint32_t num_args;
98749875

98759876
// JIT: EX(call) = NULL;
98769877
ir_STORE(jit_CALL(rx, call), IR_NULL);
@@ -9935,8 +9936,6 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
99359936
if (call_num_args <= func->op_array.num_args) {
99369937
if (!trace || (trace->op == ZEND_JIT_TRACE_END
99379938
&& trace->stop == ZEND_JIT_TRACE_STOP_INTERPRETER)) {
9938-
uint32_t num_args;
9939-
99409939
if ((func->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0) {
99419940
if (trace) {
99429941
num_args = 0;
@@ -10132,7 +10131,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
1013210131
ir_insn *insn;
1013310132

1013410133
/* attempt to convert direct recursive call into loop */
10135-
begin = jit->bb_start_ref[call_num_args];
10134+
begin = jit->bb_start_ref[num_args];
1013610135
ZEND_ASSERT(begin != IR_UNUSED);
1013710136
insn = &jit->ctx.ir_base[begin];
1013810137
if (insn->op == IR_BEGIN) {

ext/opcache/tests/jit/gh16572.phpt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
GH-16572 (Incorrect result with reflection in low-trigger JIT)
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.jit=1215
7+
--FILE--
8+
<?php
9+
function dumpType(ReflectionType $rt) {
10+
var_dump($rt::class);
11+
dumpType(null);
12+
}
13+
function test1(): int { }
14+
dumpType((new ReflectionFunction('test1'))->getReturnType());
15+
?>
16+
--EXPECTF--
17+
string(19) "ReflectionNamedType"
18+
19+
Fatal error: Uncaught TypeError: dumpType(): Argument #1 ($rt) must be of type ReflectionType, null given, called in %s on line %d and defined in %s:%d
20+
Stack trace:
21+
#0 %s(%d): dumpType(NULL)
22+
#1 %s(%d): dumpType(Object(ReflectionNamedType))
23+
#2 {main}
24+
thrown in %s on line %d

0 commit comments

Comments
 (0)