1
0
mirror of https://github.com/php/php-src.git synced 2026-04-03 14:12:38 +02:00

Avoid redundand repeatable VM stack overflow checks

This commit is contained in:
Dmitry Stogov
2021-08-26 16:50:29 +03:00
parent 5e424d2884
commit 0424ce0c15
4 changed files with 46 additions and 21 deletions

View File

@@ -3304,7 +3304,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
case ZEND_INIT_FCALL:
case ZEND_INIT_FCALL_BY_NAME:
case ZEND_INIT_NS_FCALL_BY_NAME:
if (!zend_jit_init_fcall(&dasm_state, opline, b, op_array, ssa, ssa_op, call_level, NULL, 1)) {
if (!zend_jit_init_fcall(&dasm_state, opline, b, op_array, ssa, ssa_op, call_level, NULL, 0)) {
goto jit_failure;
}
goto done;
@@ -3895,7 +3895,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
}
if (!zend_jit_init_method_call(&dasm_state, opline, b, op_array, ssa, ssa_op, call_level,
op1_info, op1_addr, ce, ce_is_instanceof, 0, NULL,
NULL, 1, 0)) {
NULL, 0, 0)) {
goto jit_failure;
}
goto done;

View File

@@ -8152,15 +8152,19 @@ static int zend_jit_stack_check(dasm_State **Dst, const zend_op *opline, uint32_
return 1;
}
static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_function *func, bool is_closure, bool use_this, bool stack_check)
static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_function *func, bool is_closure, bool use_this, int checked_stack)
{
uint32_t used_stack;
bool stack_check = 1;
// REG0 -> zend_function
// FCARG1 -> used_stack
if (func) {
used_stack = zend_vm_calc_used_stack(opline->extended_value, func);
if ((int)used_stack <= checked_stack) {
stack_check = 0;
}
} else {
used_stack = (ZEND_CALL_FRAME_SLOT + opline->extended_value) * sizeof(zval);
@@ -8406,7 +8410,7 @@ static int zend_jit_init_fcall_guard(dasm_State **Dst, uint32_t level, const zen
return 1;
}
static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t b, const zend_op_array *op_array, zend_ssa *ssa, const zend_ssa_op *ssa_op, int call_level, zend_jit_trace_rec *trace, bool stack_check)
static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t b, const zend_op_array *op_array, zend_ssa *ssa, const zend_ssa_op *ssa_op, int call_level, zend_jit_trace_rec *trace, int checked_stack)
{
zend_func_info *info = ZEND_FUNC_INFO(op_array);
zend_call_info *call_info = NULL;
@@ -8514,7 +8518,7 @@ static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t
|3:
}
if (!zend_jit_push_call_frame(Dst, opline, op_array, func, 0, 0, stack_check)) {
if (!zend_jit_push_call_frame(Dst, opline, op_array, func, 0, 0, checked_stack)) {
return 0;
}
@@ -8544,7 +8548,7 @@ static int zend_jit_init_method_call(dasm_State **Dst,
bool use_this,
zend_class_entry *trace_ce,
zend_jit_trace_rec *trace,
bool stack_check,
int checked_stack,
bool polymorphic_side_trace)
{
zend_func_info *info = ZEND_FUNC_INFO(op_array);
@@ -8728,7 +8732,7 @@ static int zend_jit_init_method_call(dasm_State **Dst,
}
if (!func || (func->common.fn_flags & ZEND_ACC_STATIC) == 0) {
if (!zend_jit_push_call_frame(Dst, opline, NULL, func, 0, use_this, stack_check)) {
if (!zend_jit_push_call_frame(Dst, opline, NULL, func, 0, use_this, checked_stack)) {
return 0;
}
}
@@ -8758,7 +8762,7 @@ static int zend_jit_init_closure_call(dasm_State **Dst,
const zend_ssa_op *ssa_op,
int call_level,
zend_jit_trace_rec *trace,
bool stack_check)
int checked_stack)
{
zend_function *func = NULL;
zend_jit_addr op2_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op2.var);
@@ -8813,7 +8817,7 @@ static int zend_jit_init_closure_call(dasm_State **Dst,
}
}
if (!zend_jit_push_call_frame(Dst, opline, NULL, func, 1, 0, stack_check)) {
if (!zend_jit_push_call_frame(Dst, opline, NULL, func, 1, 0, checked_stack)) {
return 0;
}

View File

@@ -3756,7 +3756,8 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
zend_uchar res_type = IS_UNKNOWN;
const zend_op *opline, *orig_opline;
const zend_ssa_op *ssa_op, *orig_ssa_op;
int used_stack;
int checked_stack;
int peek_checked_stack;
uint32_t frame_flags = 0;
JIT_G(current_trace) = trace_buffer;
@@ -3770,7 +3771,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
}
ssa_opcodes = ((zend_tssa*)ssa)->tssa_opcodes;
used_stack = ((zend_tssa*)ssa)->used_stack;
/* Register allocation */
if ((JIT_G(opt_flags) & (ZEND_JIT_REG_ALLOC_LOCAL|ZEND_JIT_REG_ALLOC_GLOBAL))
@@ -3784,6 +3784,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
frame = JIT_G(current_frame);
top = zend_jit_trace_call_frame(frame, op_array);
TRACE_FRAME_INIT(frame, op_array, TRACE_FRAME_MASK_UNKNOWN_RETURN, -1);
frame->used_stack = checked_stack = peek_checked_stack = 0;
stack = frame->stack;
for (i = 0; i < op_array->last_var + op_array->T; i++) {
SET_STACK_TYPE(stack, i, IS_UNKNOWN, 1);
@@ -3826,8 +3827,10 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
int last_var;
int parent_vars_count = 0;
zend_jit_trace_stack *parent_stack = NULL;
int used_stack = ((zend_tssa*)ssa)->used_stack;
if (used_stack > 0) {
peek_checked_stack = used_stack;
if (!zend_jit_stack_check(&dasm_state, opline, used_stack)) {
goto jit_failure;
}
@@ -4703,7 +4706,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
case ZEND_INIT_FCALL_BY_NAME:
case ZEND_INIT_NS_FCALL_BY_NAME:
frame_flags = TRACE_FRAME_MASK_NESTED;
if (!zend_jit_init_fcall(&dasm_state, opline, op_array_ssa->cfg.map ? op_array_ssa->cfg.map[opline - op_array->opcodes] : -1, op_array, ssa, ssa_op, frame->call_level, p + 1, used_stack < 0)) {
if (!zend_jit_init_fcall(&dasm_state, opline, op_array_ssa->cfg.map ? op_array_ssa->cfg.map[opline - op_array->opcodes] : -1, op_array, ssa, ssa_op, frame->call_level, p + 1, peek_checked_stack - checked_stack)) {
goto jit_failure;
}
goto done;
@@ -5740,7 +5743,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
op_array_ssa->cfg.map ? op_array_ssa->cfg.map[opline - op_array->opcodes] : -1,
op_array, ssa, ssa_op, frame->call_level,
op1_info, op1_addr, ce, ce_is_instanceof, delayed_fetch_this, op1_ce,
p + 1, used_stack < 0, polymorphic_side_trace)) {
p + 1, peek_checked_stack - checked_stack, polymorphic_side_trace)) {
goto jit_failure;
}
goto done;
@@ -5751,7 +5754,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
op2_info = OP2_INFO();
CHECK_OP2_TRACE_TYPE();
frame_flags = TRACE_FRAME_MASK_NESTED;
if (!zend_jit_init_closure_call(&dasm_state, opline, op_array_ssa->cfg.map ? op_array_ssa->cfg.map[opline - op_array->opcodes] : -1, op_array, ssa, ssa_op, frame->call_level, p + 1, used_stack < 0)) {
if (!zend_jit_init_closure_call(&dasm_state, opline, op_array_ssa->cfg.map ? op_array_ssa->cfg.map[opline - op_array->opcodes] : -1, op_array, ssa, ssa_op, frame->call_level, p + 1, peek_checked_stack - checked_stack)) {
goto jit_failure;
}
goto done;
@@ -6183,12 +6186,14 @@ done:
op_array_ssa = &jit_extension->func_info.ssa;
top = frame;
if (frame->prev) {
checked_stack -= frame->used_stack;
frame = frame->prev;
stack = frame->stack;
ZEND_ASSERT(&frame->func->op_array == op_array);
} else {
frame = zend_jit_trace_ret_frame(frame, op_array);
TRACE_FRAME_INIT(frame, op_array, TRACE_FRAME_MASK_UNKNOWN_RETURN, -1);
frame->used_stack = checked_stack = peek_checked_stack = 0;
stack = frame->stack;
if (JIT_G(opt_level) >= ZEND_JIT_LEVEL_INLINE) {
uint32_t j = ZEND_JIT_TRACE_GET_FIRST_SSA_VAR(p->info);
@@ -6337,10 +6342,22 @@ done:
}
if (p->info & ZEND_JIT_TRACE_FAKE_INIT_CALL) {
frame->call_level++;
call->used_stack = 0;
} else {
if (p->func) {
call->used_stack = zend_vm_calc_used_stack(init_opline->extended_value, (zend_function*)p->func);
} else {
call->used_stack = (ZEND_CALL_FRAME_SLOT + init_opline->extended_value) * sizeof(zval);
}
checked_stack += call->used_stack;
if (checked_stack > peek_checked_stack) {
peek_checked_stack = checked_stack;
}
}
} else if (p->op == ZEND_JIT_TRACE_DO_ICALL) {
call = frame->call;
if (call) {
checked_stack -= call->used_stack;
top = call;
frame->call = call->prev;
}

View File

@@ -8701,12 +8701,16 @@ static int zend_jit_stack_check(dasm_State **Dst, const zend_op *opline, uint32_
return 1;
}
static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_function *func, bool is_closure, bool use_this, bool stack_check)
static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_function *func, bool is_closure, bool use_this, int checked_stack)
{
uint32_t used_stack;
bool stack_check = 1;
if (func) {
used_stack = zend_vm_calc_used_stack(opline->extended_value, func);
if ((int)used_stack <= checked_stack) {
stack_check = 0;
}
} else {
used_stack = (ZEND_CALL_FRAME_SLOT + opline->extended_value) * sizeof(zval);
@@ -8959,7 +8963,7 @@ static int zend_jit_init_fcall_guard(dasm_State **Dst, uint32_t level, const zen
return 1;
}
static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t b, const zend_op_array *op_array, zend_ssa *ssa, const zend_ssa_op *ssa_op, int call_level, zend_jit_trace_rec *trace, bool stack_check)
static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t b, const zend_op_array *op_array, zend_ssa *ssa, const zend_ssa_op *ssa_op, int call_level, zend_jit_trace_rec *trace, int checked_stack)
{
zend_func_info *info = ZEND_FUNC_INFO(op_array);
zend_call_info *call_info = NULL;
@@ -9095,7 +9099,7 @@ static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t
|3:
}
if (!zend_jit_push_call_frame(Dst, opline, op_array, func, 0, 0, stack_check)) {
if (!zend_jit_push_call_frame(Dst, opline, op_array, func, 0, 0, checked_stack)) {
return 0;
}
@@ -9125,7 +9129,7 @@ static int zend_jit_init_method_call(dasm_State **Dst,
bool use_this,
zend_class_entry *trace_ce,
zend_jit_trace_rec *trace,
bool stack_check,
int checked_stack,
bool polymorphic_side_trace)
{
zend_func_info *info = ZEND_FUNC_INFO(op_array);
@@ -9340,7 +9344,7 @@ static int zend_jit_init_method_call(dasm_State **Dst,
}
if (!func || (func->common.fn_flags & ZEND_ACC_STATIC) == 0) {
if (!zend_jit_push_call_frame(Dst, opline, NULL, func, 0, use_this, stack_check)) {
if (!zend_jit_push_call_frame(Dst, opline, NULL, func, 0, use_this, checked_stack)) {
return 0;
}
}
@@ -9370,7 +9374,7 @@ static int zend_jit_init_closure_call(dasm_State **Dst,
const zend_ssa_op *ssa_op,
int call_level,
zend_jit_trace_rec *trace,
bool stack_check)
int checked_stack)
{
zend_function *func = NULL;
zend_jit_addr op2_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op2.var);
@@ -9439,7 +9443,7 @@ static int zend_jit_init_closure_call(dasm_State **Dst,
}
}
if (!zend_jit_push_call_frame(Dst, opline, NULL, func, 1, 0, stack_check)) {
if (!zend_jit_push_call_frame(Dst, opline, NULL, func, 1, 0, checked_stack)) {
return 0;
}