aboutsummaryrefslogtreecommitdiff
path: root/lundump.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2023-11-13 13:11:09 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2023-11-13 13:11:09 -0300
commiteabf425c76e0089eb88e102e2a44d8c8a37bc213 (patch)
tree7ad9e9901cbab5f2852187c16560ec74d21a0921 /lundump.c
parent3b57e37e4821ddce4756428956b7e9f4969efa4c (diff)
downloadlua-eabf425c76e0089eb88e102e2a44d8c8a37bc213.tar.gz
lua-eabf425c76e0089eb88e102e2a44d8c8a37bc213.tar.bz2
lua-eabf425c76e0089eb88e102e2a44d8c8a37bc213.zip
Correct anchoring and GC barriers in 'loadString'
Call to 'luaH_setint' could call the GC with the string unanchored. Moreover, previously saved strings were being assigned to the prototype without a barrier.
Diffstat (limited to 'lundump.c')
-rw-r--r--lundump.c72
1 files changed, 35 insertions, 37 deletions
diff --git a/lundump.c b/lundump.c
index 09752d99..3f18343a 100644
--- a/lundump.c
+++ b/lundump.c
@@ -132,57 +132,49 @@ static lua_Integer loadInteger (LoadState *S) {
132 132
133 133
134/* 134/*
135** Load a nullable string into prototype 'p'. 135** Load a nullable string into slot 'sl' from prototype 'p'. The
136** assignment to the slot and the barrier must be performed before any
137** possible GC activity, to anchor the string. (Both 'loadVector' and
138** 'luaH_setint' can call the GC.)
136*/ 139*/
137static TString *loadStringN (LoadState *S, Proto *p) { 140static void loadString (LoadState *S, Proto *p, TString **sl) {
138 lua_State *L = S->L; 141 lua_State *L = S->L;
139 TString *ts; 142 TString *ts;
140 TValue sv; 143 TValue sv;
141 size_t size = loadSize(S); 144 size_t size = loadSize(S);
142 if (size == 0) /* no string? */ 145 if (size == 0) { /* no string? */
143 return NULL; 146 *sl = NULL;
147 return;
148 }
144 else if (size == 1) { /* previously saved string? */ 149 else if (size == 1) { /* previously saved string? */
145 int idx = loadInt(S); /* get its index */ 150 int idx = loadInt(S); /* get its index */
146 TValue stv; 151 TValue stv;
147 luaH_getint(S->h, idx, &stv); 152 luaH_getint(S->h, idx, &stv);
148 return tsvalue(&stv); 153 *sl = ts = tsvalue(&stv);
154 luaC_objbarrier(L, p, ts);
155 return;
149 } 156 }
150 else if ((size -= 2) <= LUAI_MAXSHORTLEN) { /* short string? */ 157 else if ((size -= 2) <= LUAI_MAXSHORTLEN) { /* short string? */
151 char buff[LUAI_MAXSHORTLEN + 1]; /* extra space for '\0' */ 158 char buff[LUAI_MAXSHORTLEN + 1]; /* extra space for '\0' */
152 loadVector(S, buff, size + 1); /* load string into buffer */ 159 loadVector(S, buff, size + 1); /* load string into buffer */
153 ts = luaS_newlstr(L, buff, size); /* create string */ 160 *sl = ts = luaS_newlstr(L, buff, size); /* create string */
161 luaC_objbarrier(L, p, ts);
154 } 162 }
155 else { /* long string */ 163 else if (S->fixed) { /* for a fixed buffer, use a fixed string */
156 if (S->fixed) { /* for a fixed buffer, use a fixed string */ 164 const char *s = getaddr(S, size + 1, char); /* get content address */
157 const char *s = getaddr(S, size + 1, char); /* get content address */ 165 *sl = ts = luaS_newextlstr(L, s, size, NULL, NULL);
158 ts = luaS_newextlstr(L, s, size, NULL, NULL); 166 luaC_objbarrier(L, p, ts);
159 } 167 }
160 else { /* create internal copy */ 168 else { /* create internal copy */
161 ts = luaS_createlngstrobj(L, size); /* create string */ 169 *sl = ts = luaS_createlngstrobj(L, size); /* create string */
162 setsvalue2s(L, L->top.p, ts); /* anchor it ('loadVector' can GC) */ 170 luaC_objbarrier(L, p, ts);
163 luaD_inctop(L); 171 loadVector(S, getlngstr(ts), size); /* load directly in final place */
164 loadVector(S, getlngstr(ts), size); /* load directly in final place */ 172 loadByte(S); /* skip ending '\0' */
165 loadByte(S); /* skip ending '\0' */
166 L->top.p--; /* pop string */
167 }
168 } 173 }
169 luaC_objbarrier(L, p, ts);
170 S->nstr++; /* add string to list of saved strings */ 174 S->nstr++; /* add string to list of saved strings */
171 setsvalue(L, &sv, ts); 175 setsvalue(L, &sv, ts);
172 luaH_setint(L, S->h, S->nstr, &sv); 176 luaH_setint(L, S->h, S->nstr, &sv);
173 luaC_objbarrierback(L, obj2gco(S->h), ts); 177 luaC_objbarrierback(L, obj2gco(S->h), ts);
174 return ts;
175}
176
177
178/*
179** Load a non-nullable string into prototype 'p'.
180*/
181static TString *loadString (LoadState *S, Proto *p) {
182 TString *st = loadStringN(S, p);
183 if (st == NULL)
184 error(S, "bad format for constant string");
185 return st;
186} 178}
187 179
188 180
@@ -231,9 +223,15 @@ static void loadConstants (LoadState *S, Proto *f) {
231 setivalue(o, loadInteger(S)); 223 setivalue(o, loadInteger(S));
232 break; 224 break;
233 case LUA_VSHRSTR: 225 case LUA_VSHRSTR:
234 case LUA_VLNGSTR: 226 case LUA_VLNGSTR: {
235 setsvalue2n(S->L, o, loadString(S, f)); 227 lua_assert(f->source == NULL);
228 loadString(S, f, &f->source); /* use 'source' to anchor string */
229 if (f->source == NULL)
230 error(S, "bad format for constant string");
231 setsvalue2n(S->L, o, f->source); /* save it in the right place */
232 f->source = NULL;
236 break; 233 break;
234 }
237 default: lua_assert(0); 235 default: lua_assert(0);
238 } 236 }
239 } 237 }
@@ -301,7 +299,7 @@ static void loadDebug (LoadState *S, Proto *f) {
301 for (i = 0; i < n; i++) 299 for (i = 0; i < n; i++)
302 f->locvars[i].varname = NULL; 300 f->locvars[i].varname = NULL;
303 for (i = 0; i < n; i++) { 301 for (i = 0; i < n; i++) {
304 f->locvars[i].varname = loadStringN(S, f); 302 loadString(S, f, &f->locvars[i].varname);
305 f->locvars[i].startpc = loadInt(S); 303 f->locvars[i].startpc = loadInt(S);
306 f->locvars[i].endpc = loadInt(S); 304 f->locvars[i].endpc = loadInt(S);
307 } 305 }
@@ -309,12 +307,11 @@ static void loadDebug (LoadState *S, Proto *f) {
309 if (n != 0) /* does it have debug information? */ 307 if (n != 0) /* does it have debug information? */
310 n = f->sizeupvalues; /* must be this many */ 308 n = f->sizeupvalues; /* must be this many */
311 for (i = 0; i < n; i++) 309 for (i = 0; i < n; i++)
312 f->upvalues[i].name = loadStringN(S, f); 310 loadString(S, f, &f->upvalues[i].name);
313} 311}
314 312
315 313
316static void loadFunction (LoadState *S, Proto *f) { 314static void loadFunction (LoadState *S, Proto *f) {
317 f->source = loadStringN(S, f);
318 f->linedefined = loadInt(S); 315 f->linedefined = loadInt(S);
319 f->lastlinedefined = loadInt(S); 316 f->lastlinedefined = loadInt(S);
320 f->numparams = loadByte(S); 317 f->numparams = loadByte(S);
@@ -326,6 +323,7 @@ static void loadFunction (LoadState *S, Proto *f) {
326 loadConstants(S, f); 323 loadConstants(S, f);
327 loadUpvalues(S, f); 324 loadUpvalues(S, f);
328 loadProtos(S, f); 325 loadProtos(S, f);
326 loadString(S, f, &f->source);
329 loadDebug(S, f); 327 loadDebug(S, f);
330} 328}
331 329