]> granicus.if.org Git - php/commitdiff
Replace ZEND_ASSERT() by conditional compilation abort.
authorDmitry Stogov <dmitry@zend.com>
Thu, 30 Apr 2020 12:32:01 +0000 (15:32 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 30 Apr 2020 12:32:01 +0000 (15:32 +0300)
Prevent endless loop through ESCAPE code.

ext/opcache/jit/zend_jit_internal.h
ext/opcache/jit/zend_jit_trace.c
ext/opcache/jit/zend_jit_x86.dasc

index c787bbf8b114b8a677aec409f91a1fe9ae35176a..b5f8428689aa5ebbace23684dd5c5a0c89f39dde 100644 (file)
@@ -351,6 +351,7 @@ typedef struct _zend_jit_trace_info {
        uint32_t                  code_size;     /* size of native code */
        uint32_t                  exit_counters; /* offset in exit counters array */
        uint32_t                  stack_map_size;
+       const zend_op            *opline;        /* first opline */
        const void               *code_start;    /* address of native code */
        zend_jit_trace_exit_info *exit_info;     /* info about side exits */
        zend_jit_trace_stack     *stack_map;
index 20696f5f5f48bc040bea00efd55f4141438cc1c2..88d927213af36279eeb908696a674868c9311da6 100644 (file)
@@ -1056,7 +1056,10 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
                        stack = frame->stack;
                        op_array = p->op_array;
                        level++;
-                       ZEND_ASSERT(ssa_vars_count < 0xff);
+                       // TODO: remove this restriction ???
+                       if (ssa_vars_count >= 0xff) {
+                               return NULL;
+                       }
                        p->first_ssa_var = ssa_vars_count;
                        for (i = 0; i < op_array->last_var; i++) {
                                SET_STACK_VAR(stack, i, ssa_vars_count++);
@@ -1066,7 +1069,10 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
                        frame = zend_jit_trace_ret_frame(frame, op_array);
                        stack = frame->stack;
                        if (level == 0) {
-                               ZEND_ASSERT(ssa_vars_count <= 0xff);
+                               // TODO: remove this restriction ???
+                               if (ssa_vars_count >= 0xff) {
+                                       return NULL;
+                               }
                                p->first_ssa_var = ssa_vars_count;
                                for (i = 0; i < op_array->last_var + op_array->T; i++) {
                                        SET_STACK_VAR(stack, i, ssa_vars_count++);
@@ -2456,6 +2462,12 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
 
        ssa = zend_jit_trace_build_tssa(trace_buffer, parent_trace, exit_num, script, op_arrays, &num_op_arrays);
 
+       if (!ssa) {
+               zend_arena_release(&CG(arena), checkpoint);
+               JIT_G(current_trace) = NULL;
+               return NULL;
+       }
+
        /* Register allocation */
        if (zend_jit_reg_alloc && zend_jit_level >= ZEND_JIT_LEVEL_INLINE) {
                ra = zend_jit_trace_allocate_registers(trace_buffer, ssa, parent_trace, exit_num);
@@ -3990,7 +4002,7 @@ done:
                t->link = zend_jit_find_trace(p->opline->handler);
                zend_jit_trace_link_to_root(&dasm_state, p->opline->handler);
        } else if (p->stop == ZEND_JIT_TRACE_STOP_RETURN) {
-               zend_jit_trace_return(&dasm_state);
+               zend_jit_trace_return(&dasm_state, 0);
        } else {
                // TODO: not implemented ???
                ZEND_ASSERT(0 && p->stop);
@@ -4053,6 +4065,7 @@ static const void *zend_jit_trace_exit_to_vm(uint32_t trace_num, uint32_t exit_n
        const zend_op *opline;
        uint32_t i, stack_size;
        zend_jit_trace_stack *stack;
+       zend_bool original_handler = 0;
 
        if (!zend_jit_trace_exit_needs_deoptimization(trace_num, exit_num)) {
                return dasm_labels[zend_lbtrace_escape];
@@ -4084,9 +4097,13 @@ static const void *zend_jit_trace_exit_to_vm(uint32_t trace_num, uint32_t exit_n
        opline = (const zend_op*)((uintptr_t)opline & ~(ZEND_JIT_EXIT_JITED|ZEND_JIT_EXIT_BLACKLISTED));
        if (opline) {
                zend_jit_set_ip(&dasm_state, opline);
+               if (opline == zend_jit_traces[zend_jit_traces[trace_num].root].opline) {
+                       /* prevent endless loop */
+                       original_handler = 1;
+               }
        }
 
-       zend_jit_trace_return(&dasm_state);
+       zend_jit_trace_return(&dasm_state, original_handler);
 
        handler = dasm_link_and_encode(&dasm_state, NULL, NULL, NULL, NULL, name, 1);
 
@@ -4123,6 +4140,7 @@ static zend_jit_trace_stop zend_jit_compile_root_trace(zend_jit_trace_rec *trace
                t->exit_count = 0;
                t->child_count = 0;
                t->stack_map_size = 0;
+               t->opline = ((zend_jit_trace_start_rec*)trace_buffer)->opline;
                t->exit_info = exit_info;
                t->stack_map = NULL;
 
@@ -4674,6 +4692,7 @@ static zend_jit_trace_stop zend_jit_compile_side_trace(zend_jit_trace_rec *trace
                t->exit_count = 0;
                t->child_count = 0;
                t->stack_map_size = 0;
+               t->opline = NULL;
                t->exit_info = exit_info;
                t->stack_map = NULL;
 
index 9501e08375eb58e4d1c8abcbe2df48e8189b0e10..11377f051e2a4045ae83ee08be6df7fd09d01165 100644 (file)
@@ -2995,23 +2995,38 @@ static int zend_jit_trace_link_to_root(dasm_State **Dst, const void *code)
        return 1;
 }
 
-static int zend_jit_trace_return(dasm_State **Dst)
+static int zend_jit_trace_return(dasm_State **Dst, zend_bool original_handler)
 {
 #if 0
        |       jmp ->trace_escape
 #else
        if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
                |       add r4, HYBRID_SPAD
-               |       JMP_IP
+               if (!original_handler) {
+                       |       JMP_IP
+               } else {
+                       |       mov r0, EX->func
+                       |       mov r0, aword [r0 + offsetof(zend_op_array, reserved[zend_func_info_rid])]
+                       |       mov r0, aword [r0 + offsetof(zend_jit_op_array_trace_extension, offset)]
+                       |       jmp aword [IP + r0]
+               }
        } else if (GCC_GLOBAL_REGS) {
                |       add r4, SPAD // stack alignment
-               |       JMP_IP
+               if (!original_handler) {
+                       |       JMP_IP
+               } else {
+                       |       mov r0, EX->func
+                       |       mov r0, aword [r0 + offsetof(zend_op_array, reserved[zend_func_info_rid])]
+                       |       mov r0, aword [r0 + offsetof(zend_jit_op_array_trace_extension, offset)]
+                       |       jmp aword [IP + r0]
+               }
        } else {
                |       mov FP, aword T2 // restore FP
                |       mov RX, aword T3 // restore IP
                |       add r4, NR_SPAD // stack alignment
                |       mov r0, 2 // ZEND_VM_LEAVE
                |       ret
+               // TODO: support for "original_handler" ????
        }
 #endif
        return 1;