Fix state restore when recording __concat metamethod.

Reported by Sergey Kaplun. #1338 #1298
This commit is contained in:
Mike Pall
2025-03-09 21:28:17 +01:00
parent 4219efae43
commit eee16efa77

View File

@@ -2079,6 +2079,7 @@ static TRef rec_tnew(jit_State *J, uint32_t ah)
/* -- Concatenation ------------------------------------------------------- */ /* -- Concatenation ------------------------------------------------------- */
typedef struct RecCatDataCP { typedef struct RecCatDataCP {
TValue savetv[5+LJ_FR2];
jit_State *J; jit_State *J;
BCReg baseslot, topslot; BCReg baseslot, topslot;
TRef tr; TRef tr;
@@ -2119,7 +2120,9 @@ static TValue *rec_mm_concat_cp(lua_State *L, lua_CFunction dummy, void *ud)
return NULL; return NULL;
} }
/* Pass partial result. */ /* Pass partial result. */
topslot = J->maxslot--; rcd->topslot = topslot = J->maxslot--;
/* Save updated range of slots. */
memcpy(rcd->savetv, &L->base[topslot-1], sizeof(rcd->savetv));
*xbase = tr; *xbase = tr;
top = xbase; top = xbase;
setstrV(J->L, &ix.keyv, &J2G(J)->strempty); /* Simulate string result. */ setstrV(J->L, &ix.keyv, &J2G(J)->strempty); /* Simulate string result. */
@@ -2139,16 +2142,18 @@ static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot)
{ {
lua_State *L = J->L; lua_State *L = J->L;
ptrdiff_t delta = L->top - L->base; ptrdiff_t delta = L->top - L->base;
TValue savetv[5+LJ_FR2], errobj; TValue errobj;
RecCatDataCP rcd; RecCatDataCP rcd;
int errcode; int errcode;
rcd.J = J; rcd.J = J;
rcd.baseslot = baseslot; rcd.baseslot = baseslot;
rcd.topslot = topslot; rcd.topslot = topslot;
memcpy(savetv, &L->base[topslot-1], sizeof(savetv)); /* Save slots. */ /* Save slots. */
memcpy(rcd.savetv, &L->base[topslot-1], sizeof(rcd.savetv));
errcode = lj_vm_cpcall(L, NULL, &rcd, rec_mm_concat_cp); errcode = lj_vm_cpcall(L, NULL, &rcd, rec_mm_concat_cp);
if (errcode) copyTV(L, &errobj, L->top-1); if (errcode) copyTV(L, &errobj, L->top-1);
memcpy(&L->base[topslot-1], savetv, sizeof(savetv)); /* Restore slots. */ /* Restore slots. */
memcpy(&L->base[rcd.topslot-1], rcd.savetv, sizeof(rcd.savetv));
if (errcode) { if (errcode) {
L->top = L->base + delta; L->top = L->base + delta;
copyTV(L, L->top++, &errobj); copyTV(L, L->top++, &errobj);