diff options
| -rw-r--r-- | ldo.c | 32 | ||||
| -rw-r--r-- | ldo.h | 1 | ||||
| -rw-r--r-- | lparser.c | 23 | ||||
| -rw-r--r-- | lparser.h | 5 | ||||
| -rw-r--r-- | lundump.c | 13 | ||||
| -rw-r--r-- | lundump.h | 4 | ||||
| -rw-r--r-- | testes/calls.lua | 26 |
7 files changed, 77 insertions, 27 deletions
| @@ -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 | */ | ||
| 1131 | static void f_parser (lua_State *L, void *ud) { | 1135 | static 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 | */ | ||
| 1170 | void 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 | |||
| 1153 | TStatus luaD_protectedparser (lua_State *L, ZIO *z, const char *name, | 1179 | TStatus 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; |
| @@ -90,6 +90,7 @@ LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror); | |||
| 90 | LUAI_FUNC void luaD_shrinkstack (lua_State *L); | 90 | LUAI_FUNC void luaD_shrinkstack (lua_State *L); |
| 91 | LUAI_FUNC void luaD_inctop (lua_State *L); | 91 | LUAI_FUNC void luaD_inctop (lua_State *L); |
| 92 | LUAI_FUNC int luaD_checkminstack (lua_State *L); | 92 | LUAI_FUNC int luaD_checkminstack (lua_State *L); |
| 93 | LUAI_FUNC void luaD_anchorobj (lua_State *L, Table *anchor, GCObject *obj); | ||
| 93 | 94 | ||
| 94 | LUAI_FUNC l_noret luaD_throw (lua_State *L, TStatus errcode); | 95 | LUAI_FUNC l_noret luaD_throw (lua_State *L, TStatus errcode); |
| 95 | LUAI_FUNC l_noret luaD_throwbaselevel (lua_State *L, TStatus errcode); | 96 | LUAI_FUNC l_noret luaD_throwbaselevel (lua_State *L, TStatus errcode); |
| @@ -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 | ||
| 2177 | LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, | 2179 | LClosure *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 | ||
| @@ -189,8 +189,9 @@ typedef struct FuncState { | |||
| 189 | LUAI_FUNC lu_byte luaY_nvarstack (FuncState *fs); | 189 | LUAI_FUNC lu_byte luaY_nvarstack (FuncState *fs); |
| 190 | LUAI_FUNC void luaY_checklimit (FuncState *fs, int v, int l, | 190 | LUAI_FUNC void luaY_checklimit (FuncState *fs, int v, int l, |
| 191 | const char *what); | 191 | const char *what); |
| 192 | LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, | 192 | LUAI_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 |
| @@ -392,7 +392,8 @@ static void checkHeader (LoadState *S) { | |||
| 392 | /* | 392 | /* |
| 393 | ** Load precompiled chunk. | 393 | ** Load precompiled chunk. |
| 394 | */ | 394 | */ |
| 395 | LClosure *luaU_undump (lua_State *L, ZIO *Z, const char *name, int fixed) { | 395 | LClosure *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 | ||
| @@ -30,8 +30,8 @@ | |||
| 30 | 30 | ||
| 31 | 31 | ||
| 32 | /* load one chunk; from lundump.c */ | 32 | /* load one chunk; from lundump.c */ |
| 33 | LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name, | 33 | LUAI_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 */ |
| 37 | LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, | 37 | LUAI_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) | |||
| 372 | end | 372 | end |
| 373 | 373 | ||
| 374 | 374 | ||
| 375 | if 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) | ||
| 398 | end | ||
| 399 | |||
| 400 | |||
| 375 | x = string.dump(load("x = 1; return x")) | 401 | x = string.dump(load("x = 1; return x")) |
| 376 | a = assert(load(read1(x), nil, "b")) | 402 | a = assert(load(read1(x), nil, "b")) |
| 377 | assert(a() == 1 and _G.x == 1) | 403 | assert(a() == 1 and _G.x == 1) |
