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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user