Skip to content

Commit d50919a

Browse files
committed
Check type guard on result of FETCH_OBJ_R/IS instructions
1 parent 50fb12c commit d50919a

File tree

2 files changed

+76
-16
lines changed

2 files changed

+76
-16
lines changed

ext/opcache/jit/zend_jit_trace.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5554,7 +5554,10 @@ int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf
55545554
if (t->exit_info[exit_num].flags & ZEND_JIT_EXIT_FREE_OP1) {
55555555
ZEND_ASSERT((opline-1)->opcode == ZEND_FETCH_DIM_R
55565556
|| (opline-1)->opcode == ZEND_FETCH_DIM_IS
5557-
|| (opline-1)->opcode == ZEND_FETCH_DIM_FUNC_ARG);
5557+
|| (opline-1)->opcode == ZEND_FETCH_DIM_FUNC_ARG
5558+
|| (opline-1)->opcode == ZEND_FETCH_OBJ_R
5559+
|| (opline-1)->opcode == ZEND_FETCH_OBJ_IS
5560+
|| (opline-1)->opcode == ZEND_FETCH_OBJ_FUNC_ARG);
55585561
EX(opline) = opline-1;
55595562
zval_ptr_dtor_nogc(EX_VAR((opline-1)->op1.var));
55605563
}

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 72 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,6 +1023,23 @@ static void* dasm_labels[zend_lb_MAX];
10231023

10241024
/* the same as above, but "src" may overlap with "tmp_reg1" */
10251025
|.macro ZVAL_COPY_VALUE, dst_addr, dst_info, src_addr, src_info, tmp_reg1, tmp_reg2
1026+
| ZVAL_COPY_VALUE_V dst_addr, dst_info, src_addr, src_info, tmp_reg1, tmp_reg2
1027+
|| if ((src_info & (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE)) &&
1028+
|| !(src_info & MAY_BE_GUARD) &&
1029+
|| has_concrete_type(src_info & MAY_BE_ANY)) {
1030+
|| if (Z_MODE(dst_addr) == IS_MEM_ZVAL) {
1031+
|| if ((dst_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_GUARD)) != (src_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_GUARD))) {
1032+
|| zend_uchar type = concrete_type(src_info);
1033+
| SET_ZVAL_TYPE_INFO dst_addr, type
1034+
|| }
1035+
|| }
1036+
|| } else {
1037+
| GET_ZVAL_TYPE_INFO Rd(tmp_reg1), src_addr
1038+
| SET_ZVAL_TYPE_INFO dst_addr, Rd(tmp_reg1)
1039+
|| }
1040+
|.endmacro
1041+
1042+
|.macro ZVAL_COPY_VALUE_V, dst_addr, dst_info, src_addr, src_info, tmp_reg1, tmp_reg2
10261043
|| if (src_info & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE))) {
10271044
|| if ((src_info & (MAY_BE_ANY|MAY_BE_GUARD)) == MAY_BE_LONG) {
10281045
|| if (Z_MODE(src_addr) == IS_REG) {
@@ -1066,19 +1083,6 @@ static void* dasm_labels[zend_lb_MAX];
10661083
| .endif
10671084
|| }
10681085
|| }
1069-
|| if ((src_info & (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE)) &&
1070-
|| !(src_info & MAY_BE_GUARD) &&
1071-
|| has_concrete_type(src_info & MAY_BE_ANY)) {
1072-
|| if (Z_MODE(dst_addr) == IS_MEM_ZVAL) {
1073-
|| if ((dst_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_GUARD)) != (src_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_GUARD))) {
1074-
|| zend_uchar type = concrete_type(src_info);
1075-
| SET_ZVAL_TYPE_INFO dst_addr, type
1076-
|| }
1077-
|| }
1078-
|| } else {
1079-
| GET_ZVAL_TYPE_INFO Rd(tmp_reg1), src_addr
1080-
| SET_ZVAL_TYPE_INFO dst_addr, Rd(tmp_reg1)
1081-
|| }
10821086
|.endmacro
10831087

10841088
|.macro ZVAL_COPY_VALUE_2, dst_addr, dst_info, res_addr, src_addr, src_info, tmp_reg1, tmp_reg2
@@ -11235,8 +11239,61 @@ static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zen
1123511239
| SET_ZVAL_PTR res_addr, FCARG1a
1123611240
| SET_ZVAL_TYPE_INFO res_addr, IS_INDIRECT
1123711241
} else {
11238-
if (!zend_jit_zval_copy_deref(Dst, res_addr, prop_addr, ZREG_R2)) {
11239-
return 0;
11242+
uint32_t res_info = RES_INFO();
11243+
11244+
if ((res_info & MAY_BE_GUARD) && JIT_G(current_frame) && prop_info) {
11245+
uint32_t flags = 0;
11246+
uint32_t old_info;
11247+
zend_jit_trace_stack *stack = JIT_G(current_frame)->stack;
11248+
int32_t exit_point;
11249+
const void *exit_addr;
11250+
zend_uchar type;
11251+
zend_jit_addr val_addr = ZEND_ADDR_MEM_ZVAL(ZREG_R0, 0);
11252+
11253+
if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && !use_this) {
11254+
flags = ZEND_JIT_EXIT_FREE_OP1;
11255+
}
11256+
11257+
| LOAD_ZVAL_ADDR r0, prop_addr
11258+
11259+
old_info = STACK_INFO(stack, EX_VAR_TO_NUM(opline->result.var));
11260+
SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), IS_UNKNOWN);
11261+
SET_STACK_REG(stack, EX_VAR_TO_NUM(opline->result.var), ZREG_ZVAL_COPY_R0);
11262+
exit_point = zend_jit_trace_get_exit_point(opline, opline+1, NULL, flags);
11263+
SET_STACK_INFO(stack, EX_VAR_TO_NUM(opline->result.var), old_info);
11264+
exit_addr = zend_jit_trace_get_exit_addr(exit_point);
11265+
if (!exit_addr) {
11266+
return 0;
11267+
}
11268+
11269+
res_info &= ~MAY_BE_GUARD;
11270+
ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD;
11271+
type = concrete_type(res_info);
11272+
11273+
| // ZVAL_DEREF()
11274+
| IF_NOT_TYPE dl, IS_REFERENCE, >1
11275+
| GET_Z_PTR r0, r0
11276+
| add r0, offsetof(zend_reference, val)
11277+
if (type < IS_STRING) {
11278+
|1:
11279+
| IF_NOT_ZVAL_TYPE val_addr, type, &exit_addr
11280+
} else {
11281+
| GET_ZVAL_TYPE_INFO edx, val_addr
11282+
|1:
11283+
| IF_NOT_TYPE dl, type, &exit_addr
11284+
}
11285+
| // ZVAL_COPY
11286+
| ZVAL_COPY_VALUE_V res_addr, -1, val_addr, res_info, ZREG_R2, ZREG_R1
11287+
if (type < IS_STRING) {
11288+
| SET_ZVAL_TYPE_INFO res_addr, type
11289+
} else {
11290+
| SET_ZVAL_TYPE_INFO res_addr, edx
11291+
| TRY_ADDREF res_info, dh, r1
11292+
}
11293+
} else {
11294+
if (!zend_jit_zval_copy_deref(Dst, res_addr, prop_addr, ZREG_R2)) {
11295+
return 0;
11296+
}
1124011297
}
1124111298
}
1124211299

0 commit comments

Comments
 (0)