diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 21870089e484a..83837bb34545d 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -2489,6 +2489,11 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op goto jit_failure; } 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: if (opline->op2_type != IS_CONST || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING) { @@ -2542,6 +2547,23 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op goto jit_failure; } goto done; + case ZEND_FRAMELESS_ICALL_0: + jit_frameless_icall0(jit, opline); + goto done; + case ZEND_FRAMELESS_ICALL_1: + op1_info = OP1_INFO(); + jit_frameless_icall1(jit, opline, op1_info); + goto done; + case ZEND_FRAMELESS_ICALL_2: + op1_info = OP1_INFO(); + op2_info = OP2_INFO(); + jit_frameless_icall2(jit, opline, op1_info, op2_info); + goto done; + case ZEND_FRAMELESS_ICALL_3: + op1_info = OP1_INFO(); + op2_info = OP2_INFO(); + jit_frameless_icall3(jit, opline, op1_info, op2_info, OP1_DATA_INFO()); + goto done; default: break; } @@ -2644,17 +2666,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_RW: case ZEND_BIND_INIT_STATIC_OR_JMP: + case ZEND_JMP_FRAMELESS: if (!zend_jit_handler(&ctx, opline, zend_may_throw(opline, ssa_op, op_array, ssa)) || !zend_jit_cond_jmp(&ctx, opline + 1, ssa->cfg.blocks[b].successors[0])) { goto jit_failure; } break; - case ZEND_JMP_FRAMELESS: - if (!zend_jit_jmp_frameless(&ctx, opline, /* exit_addr */ NULL, /* guard */ 0)) { - goto jit_failure; - } - break; case ZEND_NEW: if (!zend_jit_handler(&ctx, opline, 1)) { return 0; @@ -2692,23 +2710,6 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op call_level--; } break; - case ZEND_FRAMELESS_ICALL_0: - jit_frameless_icall0(jit, opline); - goto done; - case ZEND_FRAMELESS_ICALL_1: - op1_info = OP1_INFO(); - jit_frameless_icall1(jit, opline, op1_info); - goto done; - case ZEND_FRAMELESS_ICALL_2: - op1_info = OP1_INFO(); - op2_info = OP2_INFO(); - jit_frameless_icall2(jit, opline, op1_info, op2_info); - goto done; - case ZEND_FRAMELESS_ICALL_3: - op1_info = OP1_INFO(); - op2_info = OP2_INFO(); - jit_frameless_icall3(jit, opline, op1_info, op2_info, OP1_DATA_INFO()); - goto done; default: if (!zend_jit_handler(&ctx, opline, zend_may_throw(opline, ssa_op, op_array, ssa))) { diff --git a/ext/opcache/tests/jit/gh15981.phpt b/ext/opcache/tests/jit/gh15981.phpt new file mode 100644 index 0000000000000..823b6122dc1d9 --- /dev/null +++ b/ext/opcache/tests/jit/gh15981.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-15981 (Segfault with frameless jumps and minimal JIT) +--EXTENSIONS-- +opcache +--INI-- +opcache.jit=1111 +--FILE-- + +--EXPECTF-- +string(%d) "%s"