From c7bc715f9c4e061ab37317f1fc4c324c65cb507b Mon Sep 17 00:00:00 2001 From: Sergey Kaplun Date: Mon, 16 Jan 2023 12:39:16 +0300 Subject: [PATCH] Protect call to lj_gc_step on trace exit When we exited from trace because of GC and need to drive GC forward we call lj_gc_step() inside lj_trace_exit(). If we finalize some object and error is thrown it isn't caught. This patch adds additional protected frame to catch an error. --- src/lj_trace.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/lj_trace.c b/src/lj_trace.c index c2329394..36c30ed9 100644 --- a/src/lj_trace.c +++ b/src/lj_trace.c @@ -816,6 +816,18 @@ static TValue *trace_exit_cp(lua_State *L, lua_CFunction dummy, void *ud) return NULL; } +/* Need to protect lj_gc_step because it may throw. */ +static TValue *trace_exit_gc_cp(lua_State *L, lua_CFunction dummy, void *unused) +{ + /* Always catch error here and don't call error function. */ + cframe_errfunc(L->cframe) = 0; + cframe_nres(L->cframe) = -2*LUAI_MAXSTACK*(int)sizeof(TValue); + lj_gc_step(L); + UNUSED(dummy); + UNUSED(unused); + return NULL; +} + #ifndef LUAJIT_DISABLE_VMEVENT /* Push all registers from exit state. */ static void trace_exit_regs(lua_State *L, ExitState *ex) @@ -911,8 +923,12 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) } else if (LJ_HASPROFILE && (G(L)->hookmask & HOOK_PROFILE)) { /* Just exit to interpreter. */ } else if (G(L)->gc.state == GCSatomic || G(L)->gc.state == GCSfinalize) { - if (!(G(L)->hookmask & HOOK_GC)) - lj_gc_step(L); /* Exited because of GC: drive GC forward. */ + if (!(G(L)->hookmask & HOOK_GC)) { + /* Exited because of GC: drive GC forward. */ + errcode = lj_vm_cpcall(L, NULL, NULL, trace_exit_gc_cp); + if (errcode) + return -errcode; /* Return negated error code. */ + } } else { trace_hotside(J, pc); }