From: Dmitry Stogov Date: Tue, 28 Jul 2020 16:03:05 +0000 (+0300) Subject: Check for EG(exception) after leaving function frame X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2a72778e2dc4f8dd9d3843e87138e0d33d928066;p=php Check for EG(exception) after leaving function frame --- diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 1968eff8d5..7b7534fff6 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -2727,7 +2727,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op } } } - if (!zend_jit_leave_func(&dasm_state, opline, op_array, NULL, NULL)) { + if (!zend_jit_leave_func(&dasm_state, opline, op_array, NULL, NULL, 1)) { goto jit_failure; } } diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index a018c31c2e..d894b50f18 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -3724,6 +3724,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par } } else { int j; + int may_throw = 0; if (!zend_jit_return(&dasm_state, opline, op_array, op1_info, OP1_REG_ADDR())) { @@ -3750,9 +3751,14 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par if (!zend_jit_free_cv(&dasm_state, opline, op_array, info, j)) { goto jit_failure; } + if (info & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_RESOURCE)) { + if (info & MAY_BE_RC1) { + may_throw = 1; + } + } } } - if (!zend_jit_leave_func(&dasm_state, opline, op_array, p + 1, &zend_jit_traces[ZEND_JIT_TRACE_NUM])) { + if (!zend_jit_leave_func(&dasm_state, opline, op_array, p + 1, &zend_jit_traces[ZEND_JIT_TRACE_NUM], may_throw)) { goto jit_failure; } } diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 0c8d847dec..a63db2ad9a 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -9986,7 +9986,7 @@ static int zend_jit_free_op(dasm_State **Dst, const zend_op *opline, /*const zen return 1; } -static int zend_jit_leave_func(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_jit_trace_rec *trace, zend_jit_trace_info *trace_info) +static int zend_jit_leave_func(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_jit_trace_rec *trace, zend_jit_trace_info *trace_info, int may_throw) { /* ZEND_CALL_FAKE_CLOSURE handled on slow path to eliminate check for ZEND_CALL_CLOSURE on fast path */ | mov FCARG1d, dword [FP + offsetof(zend_execute_data, This.u1.type_info)] @@ -10055,13 +10055,20 @@ static int zend_jit_leave_func(dasm_State **Dst, const zend_op *opline, const ze && (JIT_G(current_frame) && !TRACE_FRAME_IS_UNKNOWN_RETURN(JIT_G(current_frame)))) { zend_jit_reset_opline(Dst, NULL); } else { - // TODO: exception handling for tracing JIT ??? | LOAD_OPLINE | ADD_IP sizeof(zend_op) } |8: + if ((trace->op != ZEND_JIT_TRACE_END || + trace->stop != ZEND_JIT_TRACE_STOP_RECURSIVE_RET) && + may_throw) { + | // if (EG(exception)) + | MEM_OP2_1_ZTS cmp, aword, executor_globals, exception, 0, r0 + | jne ->leave_throw_handler + } + if (trace->op == ZEND_JIT_TRACE_BACK && (!JIT_G(current_frame) || TRACE_FRAME_IS_UNKNOWN_RETURN(JIT_G(current_frame)))) { const zend_op *next_opline = trace->opline; @@ -10074,6 +10081,7 @@ static int zend_jit_leave_func(dasm_State **Dst, const zend_op *opline, const ze } while (trace->op == ZEND_JIT_TRACE_INIT_CALL); ZEND_ASSERT(trace->op == ZEND_JIT_TRACE_VM || trace->op == ZEND_JIT_TRACE_END); next_opline = trace->opline; + ZEND_ASSERT(next_opline != NULL); current_frame = JIT_G(current_frame); JIT_G(current_frame) = NULL; exit_point = zend_jit_trace_get_exit_point(opline, NULL, trace, 0); @@ -10082,7 +10090,6 @@ static int zend_jit_leave_func(dasm_State **Dst, const zend_op *opline, const ze if (!exit_addr) { return 0; } - | // TODO: exception handling ??? if (trace->op == ZEND_JIT_TRACE_END && trace->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET) { trace_info->flags |= ZEND_JIT_TRACE_LOOP;