aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ldo.c32
-rw-r--r--ldo.h1
-rw-r--r--lparser.c23
-rw-r--r--lparser.h5
-rw-r--r--lundump.c13
-rw-r--r--lundump.h4
-rw-r--r--testes/calls.lua26
7 files changed, 77 insertions, 27 deletions
diff --git a/ldo.c b/ldo.c
index 12e0364b..ec360ee8 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1128,28 +1128,54 @@ static void checkmode (lua_State *L, const char *mode, const char *x) {
1128} 1128}
1129 1129
1130 1130
1131/*
1132** Before the first call to the reader function, Lua reserves a slot
1133** with a table for anchoring stuff.
1134*/
1131static void f_parser (lua_State *L, void *ud) { 1135static void f_parser (lua_State *L, void *ud) {
1132 LClosure *cl; 1136 LClosure *cl;
1133 struct SParser *p = cast(struct SParser *, ud); 1137 struct SParser *p = cast(struct SParser *, ud);
1134 const char *mode = p->mode ? p->mode : "bt"; 1138 const char *mode = p->mode ? p->mode : "bt";
1135 int c = zgetc(p->z); /* read first character */ 1139 int c;
1140 Table *anchor;
1141 ptrdiff_t otop = savestack(L, L->top.p); /* original top */
1142 luaD_checkstack(L, 2);
1143 anchor = luaH_new(L); /* create the anchor table */
1144 sethvalue2s(L, L->top.p++, anchor); /* anchor the anchor table */
1145 c = zgetc(p->z); /* read first character */
1136 if (c == LUA_SIGNATURE[0]) { 1146 if (c == LUA_SIGNATURE[0]) {
1137 int fixed = 0; 1147 int fixed = 0;
1138 if (strchr(mode, 'B') != NULL) 1148 if (strchr(mode, 'B') != NULL)
1139 fixed = 1; 1149 fixed = 1;
1140 else 1150 else
1141 checkmode(L, mode, "binary"); 1151 checkmode(L, mode, "binary");
1142 cl = luaU_undump(L, p->z, p->name, fixed); 1152 cl = luaU_undump(L, p->z, anchor, p->name, fixed);
1143 } 1153 }
1144 else { 1154 else {
1145 checkmode(L, mode, "text"); 1155 checkmode(L, mode, "text");
1146 cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); 1156 cl = luaY_parser(L, p->z, anchor, &p->buff, &p->dyd, p->name, c);
1147 } 1157 }
1158 L->top.p = restorestack(L, otop); /* restore stack */
1159 setclLvalue2s(L, L->top.p++, cl); /* push closure */
1148 lua_assert(cl->nupvalues == cl->p->sizeupvalues); 1160 lua_assert(cl->nupvalues == cl->p->sizeupvalues);
1149 luaF_initupvals(L, cl); 1161 luaF_initupvals(L, cl);
1150} 1162}
1151 1163
1152 1164
1165/*
1166** Anchor an object in a table in the stack. First, anchor the object
1167** temporarily in the stack, as luaH_set may call an emergency GC.
1168** Then, add it in the table with itself as its key.
1169*/
1170void luaD_anchorobj (lua_State *L, Table *anchor, GCObject *obj) {
1171 setgcovalue(L, s2v(L->top.p++), obj); /* temporary anchor in the stack */
1172 luaH_set(L, anchor, s2v(L->top.p - 1), s2v(L->top.p - 1));
1173 /* Because this is a new key, luaH_set will call the GC barrier, so
1174 we don't need to call the barrier again here */
1175 L->top.p--;
1176}
1177
1178
1153TStatus luaD_protectedparser (lua_State *L, ZIO *z, const char *name, 1179TStatus luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
1154 const char *mode) { 1180 const char *mode) {
1155 struct SParser p; 1181 struct SParser p;
diff --git a/ldo.h b/ldo.h
index b6472954..2b3b0db4 100644
--- a/ldo.h
+++ b/ldo.h
@@ -90,6 +90,7 @@ LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror);
90LUAI_FUNC void luaD_shrinkstack (lua_State *L); 90LUAI_FUNC void luaD_shrinkstack (lua_State *L);
91LUAI_FUNC void luaD_inctop (lua_State *L); 91LUAI_FUNC void luaD_inctop (lua_State *L);
92LUAI_FUNC int luaD_checkminstack (lua_State *L); 92LUAI_FUNC int luaD_checkminstack (lua_State *L);
93LUAI_FUNC void luaD_anchorobj (lua_State *L, Table *anchor, GCObject *obj);
93 94
94LUAI_FUNC l_noret luaD_throw (lua_State *L, TStatus errcode); 95LUAI_FUNC l_noret luaD_throw (lua_State *L, TStatus errcode);
95LUAI_FUNC l_noret luaD_throwbaselevel (lua_State *L, TStatus errcode); 96LUAI_FUNC l_noret luaD_throwbaselevel (lua_State *L, TStatus errcode);
diff --git a/lparser.c b/lparser.c
index 6b87773e..1850d6dc 100644
--- a/lparser.c
+++ b/lparser.c
@@ -821,8 +821,7 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
821 luaC_objbarrier(L, f, f->source); 821 luaC_objbarrier(L, f, f->source);
822 f->maxstacksize = 2; /* registers 0/1 are always valid */ 822 f->maxstacksize = 2; /* registers 0/1 are always valid */
823 fs->kcache = luaH_new(L); /* create table for function */ 823 fs->kcache = luaH_new(L); /* create table for function */
824 sethvalue2s(L, L->top.p, fs->kcache); /* anchor it */ 824 luaD_anchorobj(L, ls->h, obj2gco(fs->kcache)); /* anchor it */
825 luaD_inctop(L);
826 enterblock(fs, bl, 0); 825 enterblock(fs, bl, 0);
827} 826}
828 827
@@ -831,6 +830,7 @@ static void close_func (LexState *ls) {
831 lua_State *L = ls->L; 830 lua_State *L = ls->L;
832 FuncState *fs = ls->fs; 831 FuncState *fs = ls->fs;
833 Proto *f = fs->f; 832 Proto *f = fs->f;
833 TValue temp;
834 luaK_ret(fs, luaY_nvarstack(fs), 0); /* final return */ 834 luaK_ret(fs, luaY_nvarstack(fs), 0); /* final return */
835 leaveblock(fs); 835 leaveblock(fs);
836 lua_assert(fs->bl == NULL); 836 lua_assert(fs->bl == NULL);
@@ -843,8 +843,10 @@ static void close_func (LexState *ls) {
843 luaM_shrinkvector(L, f->p, f->sizep, fs->np, Proto *); 843 luaM_shrinkvector(L, f->p, f->sizep, fs->np, Proto *);
844 luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->ndebugvars, LocVar); 844 luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->ndebugvars, LocVar);
845 luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); 845 luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc);
846 /* remove kcache table from scanner table ("weigh" its anchor) */
847 sethvalue(L, &temp, fs->kcache); /* key to be set to nil */
848 luaH_set(L, ls->h, &temp, &G(L)->nilvalue);
846 ls->fs = fs->prev; 849 ls->fs = fs->prev;
847 L->top.p--; /* pop kcache table */
848 luaC_checkGC(L); 850 luaC_checkGC(L);
849} 851}
850 852
@@ -2174,16 +2176,14 @@ static void mainfunc (LexState *ls, FuncState *fs) {
2174} 2176}
2175 2177
2176 2178
2177LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, 2179LClosure *luaY_parser (lua_State *L, ZIO *z, Table *anchor, Mbuffer *buff,
2178 Dyndata *dyd, const char *name, int firstchar) { 2180 Dyndata *dyd, const char *name, int firstchar) {
2179 LexState lexstate; 2181 LexState lexstate;
2180 FuncState funcstate; 2182 FuncState funcstate;
2181 LClosure *cl = luaF_newLclosure(L, 1); /* create main closure */ 2183 LClosure *cl;
2182 setclLvalue2s(L, L->top.p, cl); /* anchor it (to avoid being collected) */ 2184 lexstate.h = anchor; /* table for scanner */
2183 luaD_inctop(L); 2185 cl = luaF_newLclosure(L, 1); /* create main closure */
2184 lexstate.h = luaH_new(L); /* create table for scanner */ 2186 luaD_anchorobj(L, anchor, obj2gco(cl)); /* anchor it in scanner table */
2185 sethvalue2s(L, L->top.p, lexstate.h); /* anchor it */
2186 luaD_inctop(L);
2187 funcstate.f = cl->p = luaF_newproto(L); 2187 funcstate.f = cl->p = luaF_newproto(L);
2188 luaC_objbarrier(L, cl, cl->p); 2188 luaC_objbarrier(L, cl, cl->p);
2189 funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ 2189 funcstate.f->source = luaS_new(L, name); /* create and anchor TString */
@@ -2196,7 +2196,6 @@ LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
2196 lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); 2196 lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs);
2197 /* all scopes should be correctly finished */ 2197 /* all scopes should be correctly finished */
2198 lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); 2198 lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0);
2199 L->top.p--; /* remove scanner's table */ 2199 return cl;
2200 return cl; /* closure is on the stack, too */
2201} 2200}
2202 2201
diff --git a/lparser.h b/lparser.h
index a30df04f..4fad6bdc 100644
--- a/lparser.h
+++ b/lparser.h
@@ -189,8 +189,9 @@ typedef struct FuncState {
189LUAI_FUNC lu_byte luaY_nvarstack (FuncState *fs); 189LUAI_FUNC lu_byte luaY_nvarstack (FuncState *fs);
190LUAI_FUNC void luaY_checklimit (FuncState *fs, int v, int l, 190LUAI_FUNC void luaY_checklimit (FuncState *fs, int v, int l,
191 const char *what); 191 const char *what);
192LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, 192LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Table *anchor,
193 Dyndata *dyd, const char *name, int firstchar); 193 Mbuffer *buff, Dyndata *dyd,
194 const char *name, int firstchar);
194 195
195 196
196#endif 197#endif
diff --git a/lundump.c b/lundump.c
index 3b61cc8c..d5fdc64b 100644
--- a/lundump.c
+++ b/lundump.c
@@ -392,7 +392,8 @@ static void checkHeader (LoadState *S) {
392/* 392/*
393** Load precompiled chunk. 393** Load precompiled chunk.
394*/ 394*/
395LClosure *luaU_undump (lua_State *L, ZIO *Z, const char *name, int fixed) { 395LClosure *luaU_undump (lua_State *L, ZIO *Z, Table *anchor, const char *name,
396 int fixed) {
396 LoadState S; 397 LoadState S;
397 LClosure *cl; 398 LClosure *cl;
398 if (*name == '@' || *name == '=') 399 if (*name == '@' || *name == '=')
@@ -405,20 +406,16 @@ LClosure *luaU_undump (lua_State *L, ZIO *Z, const char *name, int fixed) {
405 S.fixed = cast_byte(fixed); 406 S.fixed = cast_byte(fixed);
406 S.offset = 1; /* fist byte was already read */ 407 S.offset = 1; /* fist byte was already read */
407 checkHeader(&S); 408 checkHeader(&S);
408 cl = luaF_newLclosure(L, loadByte(&S)); 409 S.h = anchor;
409 setclLvalue2s(L, L->top.p, cl);
410 luaD_inctop(L);
411 S.h = luaH_new(L); /* create list of saved strings */
412 S.nstr = 0; 410 S.nstr = 0;
413 sethvalue2s(L, L->top.p, S.h); /* anchor it */ 411 cl = luaF_newLclosure(L, loadByte(&S));
414 luaD_inctop(L); 412 luaD_anchorobj(L, anchor, obj2gco(cl));
415 cl->p = luaF_newproto(L); 413 cl->p = luaF_newproto(L);
416 luaC_objbarrier(L, cl, cl->p); 414 luaC_objbarrier(L, cl, cl->p);
417 loadFunction(&S, cl->p); 415 loadFunction(&S, cl->p);
418 if (cl->nupvalues != cl->p->sizeupvalues) 416 if (cl->nupvalues != cl->p->sizeupvalues)
419 error(&S, "corrupted chunk"); 417 error(&S, "corrupted chunk");
420 luai_verifycode(L, cl->p); 418 luai_verifycode(L, cl->p);
421 L->top.p--; /* pop table */
422 return cl; 419 return cl;
423} 420}
424 421
diff --git a/lundump.h b/lundump.h
index c4e06f9e..186e25f8 100644
--- a/lundump.h
+++ b/lundump.h
@@ -30,8 +30,8 @@
30 30
31 31
32/* load one chunk; from lundump.c */ 32/* load one chunk; from lundump.c */
33LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name, 33LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, Table *anchor,
34 int fixed); 34 const char* name, int fixed);
35 35
36/* dump one chunk; from ldump.c */ 36/* dump one chunk; from ldump.c */
37LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, 37LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w,
diff --git a/testes/calls.lua b/testes/calls.lua
index 0dacb85a..cd4510a2 100644
--- a/testes/calls.lua
+++ b/testes/calls.lua
@@ -372,6 +372,32 @@ do -- another bug (in 5.4.0)
372end 372end
373 373
374 374
375if T then
376 -- check stack level when calling reader function
377 local function get (str)
378 local pos = 0
379 local level = nil
380 return function ()
381 pos = pos + 1
382 local c = string.sub(str, pos, pos)
383 local newlevel = T.stacklevel()
384 if not level then
385 level = newlevel
386 else
387 assert(level == newlevel)
388 end
389 return #c > 0 and c or nil
390 end
391 end
392
393 local str = "local function foo () end; return 121"
394 assert(assert(load(get(str)))() == 121)
395
396 str = string.dump(load(str))
397 assert(assert(load(get(str)))() == 121)
398end
399
400
375x = string.dump(load("x = 1; return x")) 401x = string.dump(load("x = 1; return x"))
376a = assert(load(read1(x), nil, "b")) 402a = assert(load(read1(x), nil, "b"))
377assert(a() == 1 and _G.x == 1) 403assert(a() == 1 and _G.x == 1)