Skip to content

Commit f74e9a4

Browse files
committed
Check type guard on result of FETCH_DIM_R/IS instructions
1 parent 1c0ee68 commit f74e9a4

File tree

4 files changed

+190
-24
lines changed

4 files changed

+190
-24
lines changed

ext/opcache/jit/zend_jit_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ typedef enum _zend_jit_trace_stop {
208208
#define ZEND_JIT_EXIT_TO_VM (1<<2) /* exit to VM without attempt to create a side trace */
209209
#define ZEND_JIT_EXIT_RESTORE_CALL (1<<3) /* deoptimizer should restore EX(call) chain */
210210
#define ZEND_JIT_EXIT_POLYMORPHISM (1<<4) /* exit because of polymorphic call */
211+
#define ZEND_JIT_EXIT_FREE_OP1 (1<<5)
212+
#define ZEND_JIT_EXIT_FREE_OP2 (1<<6)
211213

212214
typedef union _zend_op_trace_info {
213215
zend_op dummy; /* the size of this structure must be the same as zend_op */

ext/opcache/jit/zend_jit_trace.c

Lines changed: 87 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@ static uint32_t zend_jit_trace_get_exit_point(const zend_op *from_opline, const
146146
if (stack_size) {
147147
stack = JIT_G(current_frame)->stack;
148148
do {
149-
if (STACK_TYPE(stack, stack_size-1) != IS_UNKNOWN) {
149+
if (STACK_TYPE(stack, stack_size-1) != IS_UNKNOWN
150+
|| STACK_REG(stack, stack_size-1) != ZREG_NONE) {
150151
break;
151152
}
152153
stack_size--;
@@ -2832,17 +2833,37 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
28322833
goto jit_failure;
28332834
}
28342835
} else {
2835-
SET_STACK_REG(stack, i, ZREG_NONE);
2836+
if (STACK_REG(parent_stack, i) == ZREG_ZVAL_COPY_R0) {
2837+
SET_STACK_TYPE(stack, i, IS_UNKNOWN);
2838+
} else {
2839+
SET_STACK_REG(stack, i, ZREG_NONE);
2840+
}
28362841
if (!zend_jit_store_const(&dasm_state, i, STACK_REG(parent_stack, i))) {
28372842
goto jit_failure;
28382843
}
28392844
}
28402845
}
28412846
}
2842-
28432847
if (zend_jit_traces[parent_trace].exit_info[exit_num].flags & ZEND_JIT_EXIT_RESTORE_CALL) {
28442848
zend_jit_save_call_chain(&dasm_state, -1);
28452849
}
2850+
if (zend_jit_traces[parent_trace].exit_info[exit_num].flags & ZEND_JIT_EXIT_FREE_OP2) {
2851+
const zend_op *op = zend_jit_traces[parent_trace].exit_info[exit_num].opline - 1;
2852+
if (!zend_jit_free_op(&dasm_state, op, -1, op->op2.var)) {
2853+
goto jit_failure;
2854+
}
2855+
}
2856+
if (zend_jit_traces[parent_trace].exit_info[exit_num].flags & ZEND_JIT_EXIT_FREE_OP1) {
2857+
const zend_op *op = zend_jit_traces[parent_trace].exit_info[exit_num].opline - 1;
2858+
if (!zend_jit_free_op(&dasm_state, op, -1, op->op1.var)) {
2859+
goto jit_failure;
2860+
}
2861+
}
2862+
if (zend_jit_traces[parent_trace].exit_info[exit_num].flags & (ZEND_JIT_EXIT_FREE_OP1|ZEND_JIT_EXIT_FREE_OP2)) {
2863+
if (!zend_jit_check_exception(&dasm_state)) {
2864+
goto jit_failure;
2865+
}
2866+
}
28462867
}
28472868

28482869
if (ra
@@ -3750,6 +3771,11 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
37503771
(op2_info & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY)) != 0)))) {
37513772
goto jit_failure;
37523773
}
3774+
if ((res_info & MAY_BE_GUARD)
3775+
&& JIT_G(current_frame)
3776+
&& (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) {
3777+
ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD;
3778+
}
37533779
goto done;
37543780
case ZEND_ISSET_ISEMPTY_DIM_OBJ:
37553781
if ((opline->extended_value & ZEND_ISEMPTY)) {
@@ -4598,6 +4624,21 @@ static const void *zend_jit_trace_exit_to_vm(uint32_t trace_num, uint32_t exit_n
45984624

45994625
opline = zend_jit_traces[trace_num].exit_info[exit_num].opline;
46004626
if (opline) {
4627+
if (zend_jit_traces[trace_num].exit_info[exit_num].flags & ZEND_JIT_EXIT_FREE_OP2) {
4628+
if (!zend_jit_free_op(&dasm_state, (opline-1), -1, (opline-1)->op2.var)) {
4629+
goto jit_failure;
4630+
}
4631+
}
4632+
if (zend_jit_traces[trace_num].exit_info[exit_num].flags & ZEND_JIT_EXIT_FREE_OP1) {
4633+
if (!zend_jit_free_op(&dasm_state, (opline-1), -1, (opline-1)->op1.var)) {
4634+
goto jit_failure;
4635+
}
4636+
}
4637+
if (zend_jit_traces[trace_num].exit_info[exit_num].flags & (ZEND_JIT_EXIT_FREE_OP1|ZEND_JIT_EXIT_FREE_OP2)) {
4638+
if (!zend_jit_check_exception(&dasm_state)) {
4639+
goto jit_failure;
4640+
}
4641+
}
46014642
zend_jit_set_ip(&dasm_state, opline);
46024643
if (opline == zend_jit_traces[zend_jit_traces[trace_num].root].opline) {
46034644
/* prevent endless loop */
@@ -4995,6 +5036,12 @@ static void zend_jit_dump_exit_info(zend_jit_trace_info *t)
49955036
if (t->exit_info[i].flags & ZEND_JIT_EXIT_POLYMORPHISM) {
49965037
fprintf(stderr, "/POLY");
49975038
}
5039+
if (t->exit_info[i].flags & ZEND_JIT_EXIT_FREE_OP1) {
5040+
fprintf(stderr, "/FREE_OP1");
5041+
}
5042+
if (t->exit_info[i].flags & ZEND_JIT_EXIT_FREE_OP2) {
5043+
fprintf(stderr, "/FREE_OP2");
5044+
}
49985045
for (j = 0; j < stack_size; j++) {
49995046
zend_uchar type = STACK_TYPE(stack, j);
50005047
if (type != IS_UNKNOWN) {
@@ -5005,16 +5052,18 @@ static void zend_jit_dump_exit_info(zend_jit_trace_info *t)
50055052
fprintf(stderr, "undef");
50065053
} else {
50075054
fprintf(stderr, "%s", zend_get_type_by_const(type));
5008-
if (STACK_REG(stack, j) != ZREG_NONE) {
5009-
if (STACK_REG(stack, j) < ZREG_NUM) {
5010-
fprintf(stderr, "(%s)", zend_reg_name[STACK_REG(stack, j)]);
5011-
} else if (STACK_REG(stack, j) == ZREG_THIS) {
5012-
fprintf(stderr, "(this)");
5013-
} else {
5014-
fprintf(stderr, "(const_%d)", STACK_REG(stack, j) - ZREG_NUM);
5015-
}
5055+
}
5056+
if (STACK_REG(stack, j) != ZREG_NONE) {
5057+
if (STACK_REG(stack, j) < ZREG_NUM) {
5058+
fprintf(stderr, "(%s)", zend_reg_name[STACK_REG(stack, j)]);
5059+
} else if (STACK_REG(stack, j) == ZREG_THIS) {
5060+
fprintf(stderr, "(this)");
5061+
} else {
5062+
fprintf(stderr, "(const_%d)", STACK_REG(stack, j) - ZREG_NUM);
50165063
}
50175064
}
5065+
} else if (STACK_REG(stack, j) == ZREG_ZVAL_COPY_R0) {
5066+
fprintf(stderr, " zval_copy(%s)", zend_reg_name[0]);
50185067
}
50195068
}
50205069
fprintf(stderr, "\n");
@@ -5477,14 +5526,41 @@ int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf
54775526

54785527
GC_ADDREF(obj);
54795528
ZVAL_OBJ(EX_VAR_NUM(i), obj);
5529+
} else if (STACK_REG(stack, i) == ZREG_NULL) {
5530+
ZVAL_NULL(EX_VAR_NUM(i));
5531+
} else if (STACK_REG(stack, i) == ZREG_ZVAL_COPY_R0) {
5532+
zval *val = (zval*)regs->r[0];
5533+
5534+
ZVAL_COPY(EX_VAR_NUM(i), val);
54805535
} else {
54815536
ZEND_UNREACHABLE();
54825537
}
54835538
}
54845539
}
54855540

54865541
opline = t->exit_info[exit_num].opline;
5542+
54875543
if (opline) {
5544+
if (t->exit_info[exit_num].flags & ZEND_JIT_EXIT_FREE_OP2) {
5545+
ZEND_ASSERT((opline-1)->opcode == ZEND_FETCH_DIM_R
5546+
|| (opline-1)->opcode == ZEND_FETCH_DIM_IS
5547+
|| (opline-1)->opcode == ZEND_FETCH_DIM_FUNC_ARG);
5548+
EX(opline) = opline-1;
5549+
zval_ptr_dtor_nogc(EX_VAR((opline-1)->op2.var));
5550+
}
5551+
if (t->exit_info[exit_num].flags & ZEND_JIT_EXIT_FREE_OP1) {
5552+
ZEND_ASSERT((opline-1)->opcode == ZEND_FETCH_DIM_R
5553+
|| (opline-1)->opcode == ZEND_FETCH_DIM_IS
5554+
|| (opline-1)->opcode == ZEND_FETCH_DIM_FUNC_ARG);
5555+
EX(opline) = opline-1;
5556+
zval_ptr_dtor_nogc(EX_VAR((opline-1)->op1.var));
5557+
}
5558+
if (t->exit_info[exit_num].flags & (ZEND_JIT_EXIT_FREE_OP1|ZEND_JIT_EXIT_FREE_OP2)) {
5559+
if (EG(exception)) {
5560+
return 1;
5561+
}
5562+
}
5563+
54885564
/* Set VM opline to continue interpretation */
54895565
EX(opline) = opline;
54905566
}

0 commit comments

Comments
 (0)