diff options
author | Mike Pall <mike> | 2024-07-04 00:48:49 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2024-07-04 00:48:49 +0200 |
commit | 7421a1b33c7ea46f12bba9700c15b5c90253fee0 (patch) | |
tree | f4ee88df19d406b0bda1d90fd00caf0a23a49f79 | |
parent | 510f88d468b8a6d6feb02890417a7261073bcd87 (diff) | |
download | luajit-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.c | 26 |
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 | ||
2080 | typedef struct RecCatDataCP { | ||
2081 | jit_State *J; | ||
2082 | RecordIndex *ix; | ||
2083 | } RecCatDataCP; | ||
2084 | |||
2085 | static 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 | |||
2078 | static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) | 2093 | static 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 --------------------------------------------- */ |