aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2024-07-04 00:48:49 +0200
committerMike Pall <mike>2024-07-04 00:48:49 +0200
commit7421a1b33c7ea46f12bba9700c15b5c90253fee0 (patch)
treef4ee88df19d406b0bda1d90fd00caf0a23a49f79
parent510f88d468b8a6d6feb02890417a7261073bcd87 (diff)
downloadluajit-7421a1b33c7ea46f12bba9700c15b5c90253fee0.tar.gz
luajit-7421a1b33c7ea46f12bba9700c15b5c90253fee0.tar.bz2
luajit-7421a1b33c7ea46f12bba9700c15b5c90253fee0.zip
Restore state when recording __concat metamethod throws an error.
Thanks to Sergey Kaplun. #1234
-rw-r--r--src/lj_record.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/src/lj_record.c b/src/lj_record.c
index 48bbbb20..6666b3c6 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -1025,7 +1025,9 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
1025 J->L->base = b + baseadj; 1025 J->L->base = b + baseadj;
1026 copyTV(J->L, b-(2<<LJ_FR2), &save); 1026 copyTV(J->L, b-(2<<LJ_FR2), &save);
1027 } 1027 }
1028 if (tr) { /* Store final result. */ 1028 if (tr >= 0xffffff00) {
1029 lj_err_throw(J->L, -(int32_t)tr); /* Propagate errors. */
1030 } else if (tr) { /* Store final result. */
1029 BCReg dst = bc_a(*(frame_contpc(frame)-1)); 1031 BCReg dst = bc_a(*(frame_contpc(frame)-1));
1030 J->base[dst] = tr; 1032 J->base[dst] = tr;
1031 if (dst >= J->maxslot) { 1033 if (dst >= J->maxslot) {
@@ -2075,12 +2077,27 @@ static TRef rec_tnew(jit_State *J, uint32_t ah)
2075 2077
2076/* -- Concatenation ------------------------------------------------------- */ 2078/* -- Concatenation ------------------------------------------------------- */
2077 2079
2080typedef struct RecCatDataCP {
2081 jit_State *J;
2082 RecordIndex *ix;
2083} RecCatDataCP;
2084
2085static TValue *rec_mm_concat_cp(lua_State *L, lua_CFunction dummy, void *ud)
2086{
2087 RecCatDataCP *rcd = (RecCatDataCP *)ud;
2088 UNUSED(L); UNUSED(dummy);
2089 rec_mm_arith(rcd->J, rcd->ix, MM_concat); /* Call __concat metamethod. */
2090 return NULL;
2091}
2092
2078static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) 2093static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot)
2079{ 2094{
2080 TRef *top = &J->base[topslot]; 2095 TRef *top = &J->base[topslot];
2081 TValue savetv[5+LJ_FR2]; 2096 TValue savetv[5+LJ_FR2];
2082 BCReg s; 2097 BCReg s;
2083 RecordIndex ix; 2098 RecordIndex ix;
2099 RecCatDataCP rcd;
2100 int errcode;
2084 lj_assertJ(baseslot < topslot, "bad CAT arg"); 2101 lj_assertJ(baseslot < topslot, "bad CAT arg");
2085 for (s = baseslot; s <= topslot; s++) 2102 for (s = baseslot; s <= topslot; s++)
2086 (void)getslot(J, s); /* Ensure all arguments have a reference. */ 2103 (void)getslot(J, s); /* Ensure all arguments have a reference. */
@@ -2116,8 +2133,11 @@ static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot)
2116 ix.tab = top[-1]; 2133 ix.tab = top[-1];
2117 ix.key = top[0]; 2134 ix.key = top[0];
2118 memcpy(savetv, &J->L->base[topslot-1], sizeof(savetv)); /* Save slots. */ 2135 memcpy(savetv, &J->L->base[topslot-1], sizeof(savetv)); /* Save slots. */
2119 rec_mm_arith(J, &ix, MM_concat); /* Call __concat metamethod. */ 2136 rcd.J = J;
2137 rcd.ix = &ix;
2138 errcode = lj_vm_cpcall(J->L, NULL, &rcd, rec_mm_concat_cp);
2120 memcpy(&J->L->base[topslot-1], savetv, sizeof(savetv)); /* Restore slots. */ 2139 memcpy(&J->L->base[topslot-1], savetv, sizeof(savetv)); /* Restore slots. */
2140 if (errcode) return (TRef)(-errcode);
2121 return 0; /* No result yet. */ 2141 return 0; /* No result yet. */
2122} 2142}
2123 2143
@@ -2440,6 +2460,8 @@ void lj_record_ins(jit_State *J)
2440 2460
2441 case BC_CAT: 2461 case BC_CAT:
2442 rc = rec_cat(J, rb, rc); 2462 rc = rec_cat(J, rb, rc);
2463 if (rc >= 0xffffff00)
2464 lj_err_throw(J->L, -(int32_t)rc); /* Propagate errors. */
2443 break; 2465 break;
2444 2466
2445 /* -- Constant and move ops --------------------------------------------- */ 2467 /* -- Constant and move ops --------------------------------------------- */