Fix GH-15981: Segfault with frameless jumps and minimal JIT

Minimal JIT shouldn't generate a call to the complex handler, but
instead rely on the VM and then check for a two-way jump.
This moves the frameless codegen under the check `JIT_G(opt_level) >=
ZEND_JIT_LEVEL_INLINE`.
This commit is contained in:
Niels Dossche 2025-01-02 23:48:47 +01:00
parent b666dc9788
commit 72184abd2f
No known key found for this signature in database
GPG key ID: B8A8AD166DF0E2E5
3 changed files with 34 additions and 5 deletions

4
NEWS
View file

@ -36,6 +36,10 @@ PHP NEWS
- Intl: - Intl:
. Fixed bug GH-11874 (intl causing segfault in docker images). (nielsdos) . Fixed bug GH-11874 (intl causing segfault in docker images). (nielsdos)
- Opcache:
. Fixed bug GH-15981 (Segfault with frameless jumps and minimal JIT).
(nielsdos)
- PHPDBG: - PHPDBG:
. Fix crashes in function registration + test. (nielsdos, Girgias) . Fix crashes in function registration + test. (nielsdos, Girgias)

View file

@ -2489,6 +2489,11 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
goto jit_failure; goto jit_failure;
} }
goto done; goto done;
case ZEND_JMP_FRAMELESS:
if (!zend_jit_jmp_frameless(&ctx, opline, /* exit_addr */ NULL, /* guard */ 0)) {
goto jit_failure;
}
goto done;
case ZEND_INIT_METHOD_CALL: case ZEND_INIT_METHOD_CALL:
if (opline->op2_type != IS_CONST if (opline->op2_type != IS_CONST
|| Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING) { || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING) {
@ -2644,17 +2649,13 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_R:
case ZEND_FE_FETCH_RW: case ZEND_FE_FETCH_RW:
case ZEND_BIND_INIT_STATIC_OR_JMP: case ZEND_BIND_INIT_STATIC_OR_JMP:
case ZEND_JMP_FRAMELESS:
if (!zend_jit_handler(&ctx, opline, if (!zend_jit_handler(&ctx, opline,
zend_may_throw(opline, ssa_op, op_array, ssa)) || zend_may_throw(opline, ssa_op, op_array, ssa)) ||
!zend_jit_cond_jmp(&ctx, opline + 1, ssa->cfg.blocks[b].successors[0])) { !zend_jit_cond_jmp(&ctx, opline + 1, ssa->cfg.blocks[b].successors[0])) {
goto jit_failure; goto jit_failure;
} }
break; break;
case ZEND_JMP_FRAMELESS:
if (!zend_jit_jmp_frameless(&ctx, opline, /* exit_addr */ NULL, /* guard */ 0)) {
goto jit_failure;
}
break;
case ZEND_NEW: case ZEND_NEW:
if (!zend_jit_handler(&ctx, opline, 1)) { if (!zend_jit_handler(&ctx, opline, 1)) {
return 0; return 0;

View file

@ -0,0 +1,24 @@
--TEST--
GH-15981 (Segfault with frameless jumps and minimal JIT)
--EXTENSIONS--
opcache
--INI--
opcache.jit=1111
--FILE--
<?php
namespace NS { // Namespace is important to reproduce the issue
class Tester {
static public function findExecutable(): string {
return dirname(__DIR__);
}
}
}
namespace {
var_dump(NS\Tester::findExecutable());
}
?>
--EXPECTF--
string(%d) "%s"