1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix GH-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.

Closes GH-16575.
This commit is contained in:
Niels Dossche
2024-10-24 21:47:55 +02:00
parent 757781a142
commit 38e1b0ac8c
3 changed files with 30 additions and 3 deletions

4
NEWS
View File

@@ -12,6 +12,10 @@ PHP NEWS
. Fixed bug GH-16559 (UBSan abort in ext/gd/libgd/gd_interpolation.c:1007).
(nielsdos)
- Opcache:
. Fixed bug GH-16572 (Incorrect result with reflection in low-trigger JIT).
(nielsdos)
- PDO:
. Fixed bug GH-16167 (Prevent mixing PDO sub-classes with different DSN).
(kocsismate)

View File

@@ -9887,6 +9887,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
if ((!func || func->type == ZEND_USER_FUNCTION)
&& opline->opcode != ZEND_DO_ICALL) {
bool recursive_call_through_jmp = 0;
uint32_t num_args = 0;
// JIT: EX(call) = NULL;
ir_STORE(jit_CALL(rx, call), IR_NULL);
@@ -9951,8 +9952,6 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
if (call_num_args <= func->op_array.num_args) {
if (!trace || (trace->op == ZEND_JIT_TRACE_END
&& trace->stop == ZEND_JIT_TRACE_STOP_INTERPRETER)) {
uint32_t num_args;
if ((func->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0) {
if (trace) {
num_args = 0;
@@ -10148,7 +10147,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
ir_insn *insn;
/* attempt to convert direct recursive call into loop */
begin = jit->bb_start_ref[call_num_args];
begin = jit->bb_start_ref[num_args];
ZEND_ASSERT(begin != IR_UNUSED);
insn = &jit->ctx.ir_base[begin];
if (insn->op == IR_BEGIN) {

View File

@@ -0,0 +1,24 @@
--TEST--
GH-16572 (Incorrect result with reflection in low-trigger JIT)
--EXTENSIONS--
opcache
--INI--
opcache.jit=1215
--FILE--
<?php
function dumpType(ReflectionType $rt) {
var_dump($rt::class);
dumpType(null);
}
function test1(): int { }
dumpType((new ReflectionFunction('test1'))->getReturnType());
?>
--EXPECTF--
string(19) "ReflectionNamedType"
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
Stack trace:
#0 %s(%d): dumpType(NULL)
#1 %s(%d): dumpType(Object(ReflectionNamedType))
#2 {main}
thrown in %s on line %d