diff options
author | Mike Pall <mike> | 2024-11-28 18:07:58 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2024-11-28 18:07:58 +0100 |
commit | 19878ec05c239ccaf5f3d17af27670a963e25b8b (patch) | |
tree | ebceb64f3727dc6cc432c656f59811967d8b7835 | |
parent | 35a4dd6f794e3ab7d2f41658212727ee85090448 (diff) | |
download | luajit-19878ec05c239ccaf5f3d17af27670a963e25b8b.tar.gz luajit-19878ec05c239ccaf5f3d17af27670a963e25b8b.tar.bz2 luajit-19878ec05c239ccaf5f3d17af27670a963e25b8b.zip |
Restore state when recording __concat metamethod throws OOM.
Reported by Sergey Kaplun. #1298 #1234
-rw-r--r-- | src/lj_record.c | 51 |
1 files 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) | |||
2080 | 2080 | ||
2081 | typedef struct RecCatDataCP { | 2081 | typedef struct RecCatDataCP { |
2082 | jit_State *J; | 2082 | jit_State *J; |
2083 | RecordIndex *ix; | 2083 | BCReg baseslot, topslot; |
2084 | TRef tr; | ||
2084 | } RecCatDataCP; | 2085 | } RecCatDataCP; |
2085 | 2086 | ||
2086 | static TValue *rec_mm_concat_cp(lua_State *L, lua_CFunction dummy, void *ud) | 2087 | static TValue *rec_mm_concat_cp(lua_State *L, lua_CFunction dummy, void *ud) |
2087 | { | 2088 | { |
2088 | RecCatDataCP *rcd = (RecCatDataCP *)ud; | 2089 | RecCatDataCP *rcd = (RecCatDataCP *)ud; |
2089 | UNUSED(L); UNUSED(dummy); | 2090 | jit_State *J = rcd->J; |
2090 | rec_mm_arith(rcd->J, rcd->ix, MM_concat); /* Call __concat metamethod. */ | 2091 | BCReg baseslot = rcd->baseslot, topslot = rcd->topslot; |
2091 | return NULL; | ||
2092 | } | ||
2093 | |||
2094 | static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) | ||
2095 | { | ||
2096 | TRef *top = &J->base[topslot]; | 2092 | TRef *top = &J->base[topslot]; |
2097 | TValue savetv[5+LJ_FR2]; | ||
2098 | BCReg s; | 2093 | BCReg s; |
2099 | RecordIndex ix; | 2094 | RecordIndex ix; |
2100 | RecCatDataCP rcd; | 2095 | UNUSED(L); UNUSED(dummy); |
2101 | int errcode; | ||
2102 | lj_assertJ(baseslot < topslot, "bad CAT arg"); | 2096 | lj_assertJ(baseslot < topslot, "bad CAT arg"); |
2103 | for (s = baseslot; s <= topslot; s++) | 2097 | for (s = baseslot; s <= topslot; s++) |
2104 | (void)getslot(J, s); /* Ensure all arguments have a reference. */ | 2098 | (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) | |||
2120 | } while (trp <= top); | 2114 | } while (trp <= top); |
2121 | tr = emitir(IRTG(IR_BUFSTR, IRT_STR), tr, hdr); | 2115 | tr = emitir(IRTG(IR_BUFSTR, IRT_STR), tr, hdr); |
2122 | J->maxslot = (BCReg)(xbase - J->base); | 2116 | J->maxslot = (BCReg)(xbase - J->base); |
2123 | if (xbase == base) return tr; /* Return simple concatenation result. */ | 2117 | if (xbase == base) { |
2118 | rcd->tr = tr; /* Return simple concatenation result. */ | ||
2119 | return NULL; | ||
2120 | } | ||
2124 | /* Pass partial result. */ | 2121 | /* Pass partial result. */ |
2125 | topslot = J->maxslot--; | 2122 | topslot = J->maxslot--; |
2126 | *xbase = tr; | 2123 | *xbase = tr; |
@@ -2133,13 +2130,31 @@ static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) | |||
2133 | copyTV(J->L, &ix.tabv, &J->L->base[topslot-1]); | 2130 | copyTV(J->L, &ix.tabv, &J->L->base[topslot-1]); |
2134 | ix.tab = top[-1]; | 2131 | ix.tab = top[-1]; |
2135 | ix.key = top[0]; | 2132 | ix.key = top[0]; |
2136 | memcpy(savetv, &J->L->base[topslot-1], sizeof(savetv)); /* Save slots. */ | 2133 | rec_mm_arith(J, &ix, MM_concat); /* Call __concat metamethod. */ |
2134 | rcd->tr = 0; /* No result yet. */ | ||
2135 | return NULL; | ||
2136 | } | ||
2137 | |||
2138 | static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) | ||
2139 | { | ||
2140 | lua_State *L = J->L; | ||
2141 | ptrdiff_t delta = L->top - L->base; | ||
2142 | TValue savetv[5+LJ_FR2], errobj; | ||
2143 | RecCatDataCP rcd; | ||
2144 | int errcode; | ||
2137 | rcd.J = J; | 2145 | rcd.J = J; |
2138 | rcd.ix = &ix; | 2146 | rcd.baseslot = baseslot; |
2139 | errcode = lj_vm_cpcall(J->L, NULL, &rcd, rec_mm_concat_cp); | 2147 | rcd.topslot = topslot; |
2140 | memcpy(&J->L->base[topslot-1], savetv, sizeof(savetv)); /* Restore slots. */ | 2148 | memcpy(savetv, &L->base[topslot-1], sizeof(savetv)); /* Save slots. */ |
2141 | if (errcode) return (TRef)(-errcode); | 2149 | errcode = lj_vm_cpcall(L, NULL, &rcd, rec_mm_concat_cp); |
2142 | return 0; /* No result yet. */ | 2150 | if (errcode) copyTV(L, &errobj, L->top-1); |
2151 | memcpy(&L->base[topslot-1], savetv, sizeof(savetv)); /* Restore slots. */ | ||
2152 | if (errcode) { | ||
2153 | L->top = L->base + delta; | ||
2154 | copyTV(L, L->top++, &errobj); | ||
2155 | return (TRef)(-errcode); | ||
2156 | } | ||
2157 | return rcd.tr; | ||
2143 | } | 2158 | } |
2144 | 2159 | ||
2145 | /* -- Record bytecode ops ------------------------------------------------- */ | 2160 | /* -- Record bytecode ops ------------------------------------------------- */ |