From 19878ec05c239ccaf5f3d17af27670a963e25b8b Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Thu, 28 Nov 2024 18:07:58 +0100 Subject: [PATCH] Restore state when recording __concat metamethod throws OOM. Reported by Sergey Kaplun. #1298 #1234 --- src/lj_record.c | 51 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/src/lj_record.c b/src/lj_record.c index fedd47a6..3f250008 100644 --- a/src/lj_record.c +++ b/src/lj_record.c @@ -2080,25 +2080,19 @@ static TRef rec_tnew(jit_State *J, uint32_t ah) typedef struct RecCatDataCP { jit_State *J; - RecordIndex *ix; + BCReg baseslot, topslot; + TRef tr; } RecCatDataCP; static TValue *rec_mm_concat_cp(lua_State *L, lua_CFunction dummy, void *ud) { RecCatDataCP *rcd = (RecCatDataCP *)ud; - UNUSED(L); UNUSED(dummy); - rec_mm_arith(rcd->J, rcd->ix, MM_concat); /* Call __concat metamethod. */ - return NULL; -} - -static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) -{ + jit_State *J = rcd->J; + BCReg baseslot = rcd->baseslot, topslot = rcd->topslot; TRef *top = &J->base[topslot]; - TValue savetv[5+LJ_FR2]; BCReg s; RecordIndex ix; - RecCatDataCP rcd; - int errcode; + UNUSED(L); UNUSED(dummy); lj_assertJ(baseslot < topslot, "bad CAT arg"); for (s = baseslot; s <= topslot; s++) (void)getslot(J, s); /* Ensure all arguments have a reference. */ @@ -2120,7 +2114,10 @@ static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) } while (trp <= top); tr = emitir(IRTG(IR_BUFSTR, IRT_STR), tr, hdr); J->maxslot = (BCReg)(xbase - J->base); - if (xbase == base) return tr; /* Return simple concatenation result. */ + if (xbase == base) { + rcd->tr = tr; /* Return simple concatenation result. */ + return NULL; + } /* Pass partial result. */ topslot = J->maxslot--; *xbase = tr; @@ -2133,13 +2130,31 @@ static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) copyTV(J->L, &ix.tabv, &J->L->base[topslot-1]); ix.tab = top[-1]; ix.key = top[0]; - memcpy(savetv, &J->L->base[topslot-1], sizeof(savetv)); /* Save slots. */ + rec_mm_arith(J, &ix, MM_concat); /* Call __concat metamethod. */ + rcd->tr = 0; /* No result yet. */ + return NULL; +} + +static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) +{ + lua_State *L = J->L; + ptrdiff_t delta = L->top - L->base; + TValue savetv[5+LJ_FR2], errobj; + RecCatDataCP rcd; + int errcode; rcd.J = J; - rcd.ix = &ix; - errcode = lj_vm_cpcall(J->L, NULL, &rcd, rec_mm_concat_cp); - memcpy(&J->L->base[topslot-1], savetv, sizeof(savetv)); /* Restore slots. */ - if (errcode) return (TRef)(-errcode); - return 0; /* No result yet. */ + rcd.baseslot = baseslot; + rcd.topslot = topslot; + memcpy(savetv, &L->base[topslot-1], sizeof(savetv)); /* Save slots. */ + errcode = lj_vm_cpcall(L, NULL, &rcd, rec_mm_concat_cp); + if (errcode) copyTV(L, &errobj, L->top-1); + memcpy(&L->base[topslot-1], savetv, sizeof(savetv)); /* Restore slots. */ + if (errcode) { + L->top = L->base + delta; + copyTV(L, L->top++, &errobj); + return (TRef)(-errcode); + } + return rcd.tr; } /* -- Record bytecode ops ------------------------------------------------- */