]> granicus.if.org Git - php/commitdiff
Check type guard on result of FETCH_OBJ_R/IS instructions
authorDmitry Stogov <dmitry@zend.com>
Thu, 16 Jul 2020 12:14:11 +0000 (15:14 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 16 Jul 2020 12:14:11 +0000 (15:14 +0300)
ext/opcache/jit/zend_jit_trace.c
ext/opcache/jit/zend_jit_x86.dasc

index b64429b1a7b06a6b403f1a8bddc2be10134471c7..b15346545c16c2404cf278a8b82c43263bd8432b 100644 (file)
@@ -5554,7 +5554,10 @@ int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf
                if (t->exit_info[exit_num].flags & ZEND_JIT_EXIT_FREE_OP1) {
                        ZEND_ASSERT((opline-1)->opcode == ZEND_FETCH_DIM_R
                                        || (opline-1)->opcode == ZEND_FETCH_DIM_IS
-                                       || (opline-1)->opcode == ZEND_FETCH_DIM_FUNC_ARG);
+                                       || (opline-1)->opcode == ZEND_FETCH_DIM_FUNC_ARG
+                                       || (opline-1)->opcode == ZEND_FETCH_OBJ_R
+                                       || (opline-1)->opcode == ZEND_FETCH_OBJ_IS
+                                       || (opline-1)->opcode == ZEND_FETCH_OBJ_FUNC_ARG);
                        EX(opline) = opline-1;
                        zval_ptr_dtor_nogc(EX_VAR((opline-1)->op1.var));
                }
index 5a181b0df847031a8039046676cecbb7e16cedac..407d8a178d4a97df0a704fe77976066183d07a84 100644 (file)
@@ -1023,6 +1023,23 @@ static void* dasm_labels[zend_lb_MAX];
 
 /* the same as above, but "src" may overlap with "tmp_reg1" */
 |.macro ZVAL_COPY_VALUE, dst_addr, dst_info, src_addr, src_info, tmp_reg1, tmp_reg2
+|      ZVAL_COPY_VALUE_V dst_addr, dst_info, src_addr, src_info, tmp_reg1, tmp_reg2
+||     if ((src_info & (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE)) &&
+||      !(src_info & MAY_BE_GUARD) &&
+||             has_concrete_type(src_info & MAY_BE_ANY)) {
+||             if (Z_MODE(dst_addr) == IS_MEM_ZVAL) {
+||                     if ((dst_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_GUARD)) != (src_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_GUARD))) {
+||                             zend_uchar type = concrete_type(src_info);
+|                              SET_ZVAL_TYPE_INFO dst_addr, type
+||                     }
+||             }
+||     } else {
+|              GET_ZVAL_TYPE_INFO Rd(tmp_reg1), src_addr
+|              SET_ZVAL_TYPE_INFO dst_addr, Rd(tmp_reg1)
+||     }
+|.endmacro
+
+|.macro ZVAL_COPY_VALUE_V, dst_addr, dst_info, src_addr, src_info, tmp_reg1, tmp_reg2
 ||     if (src_info & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE))) {
 ||             if ((src_info & (MAY_BE_ANY|MAY_BE_GUARD)) == MAY_BE_LONG) {
 ||                     if (Z_MODE(src_addr) == IS_REG) {
@@ -1066,19 +1083,6 @@ static void* dasm_labels[zend_lb_MAX];
 |                      .endif
 ||             }
 ||     }
-||     if ((src_info & (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE)) &&
-||      !(src_info & MAY_BE_GUARD) &&
-||             has_concrete_type(src_info & MAY_BE_ANY)) {
-||             if (Z_MODE(dst_addr) == IS_MEM_ZVAL) {
-||                     if ((dst_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_GUARD)) != (src_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_GUARD))) {
-||                             zend_uchar type = concrete_type(src_info);
-|                              SET_ZVAL_TYPE_INFO dst_addr, type
-||                     }
-||             }
-||     } else {
-|              GET_ZVAL_TYPE_INFO Rd(tmp_reg1), src_addr
-|              SET_ZVAL_TYPE_INFO dst_addr, Rd(tmp_reg1)
-||     }
 |.endmacro
 
 |.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
                |       SET_ZVAL_PTR res_addr, FCARG1a
                |       SET_ZVAL_TYPE_INFO res_addr, IS_INDIRECT
        } else {
-               if (!zend_jit_zval_copy_deref(Dst, res_addr, prop_addr, ZREG_R2)) {
-                       return 0;
+               uint32_t res_info = RES_INFO();
+
+               if ((res_info & MAY_BE_GUARD) && JIT_G(current_frame) && prop_info) {
+                       uint32_t flags = 0;
+                       uint32_t old_info;
+                       zend_jit_trace_stack *stack = JIT_G(current_frame)->stack;
+                       int32_t exit_point;
+                       const void *exit_addr;
+                       zend_uchar type;
+                       zend_jit_addr val_addr = ZEND_ADDR_MEM_ZVAL(ZREG_R0, 0);
+
+                       if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && !use_this) {
+                               flags = ZEND_JIT_EXIT_FREE_OP1;
+                       }
+
+                       |       LOAD_ZVAL_ADDR r0, prop_addr
+
+                       old_info = STACK_INFO(stack, EX_VAR_TO_NUM(opline->result.var));
+                       SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), IS_UNKNOWN);
+                       SET_STACK_REG(stack, EX_VAR_TO_NUM(opline->result.var), ZREG_ZVAL_COPY_R0);
+                       exit_point = zend_jit_trace_get_exit_point(opline, opline+1, NULL, flags);
+                       SET_STACK_INFO(stack, EX_VAR_TO_NUM(opline->result.var), old_info);
+                       exit_addr = zend_jit_trace_get_exit_addr(exit_point);
+                       if (!exit_addr) {
+                               return 0;
+                       }
+
+                       res_info &= ~MAY_BE_GUARD;
+                       ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD;
+                       type = concrete_type(res_info);
+
+                       |       // ZVAL_DEREF()
+                       |       IF_NOT_TYPE dl, IS_REFERENCE, >1
+                       |       GET_Z_PTR r0, r0
+                       |       add r0, offsetof(zend_reference, val)
+                       if (type < IS_STRING) {
+                               |1:
+                               |       IF_NOT_ZVAL_TYPE val_addr, type, &exit_addr
+                       } else {
+                               |       GET_ZVAL_TYPE_INFO edx, val_addr
+                               |1:
+                               |       IF_NOT_TYPE dl, type, &exit_addr
+                       }
+                       |       // ZVAL_COPY
+                       |       ZVAL_COPY_VALUE_V res_addr, -1, val_addr, res_info, ZREG_R2, ZREG_R1
+                       if (type < IS_STRING) {
+                               |       SET_ZVAL_TYPE_INFO res_addr, type
+                       } else {
+                               |       SET_ZVAL_TYPE_INFO res_addr, edx
+                               |       TRY_ADDREF res_info, dh, r1
+                       }
+               } else {
+                       if (!zend_jit_zval_copy_deref(Dst, res_addr, prop_addr, ZREG_R2)) {
+                               return 0;
+                       }
                }
        }