diff --git a/lapi.c b/lapi.c index 3e24781e..184b8dd7 100644 --- a/lapi.c +++ b/lapi.c @@ -563,6 +563,7 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { while (n--) { setobj2n(L, &cl->upvalue[n], s2v(L->top + n)); /* does not need barrier because closure is white */ + lua_assert(iswhite(cl)); } setclCvalue(L, s2v(L->top), cl); api_incr_top(L); diff --git a/lundump.c b/lundump.c index 4243678a..cb124d6f 100644 --- a/lundump.c +++ b/lundump.c @@ -200,13 +200,20 @@ static void loadProtos (LoadState *S, Proto *f) { } +/* +** Load the upvalues for a function. The names must be filled first, +** because the filling of the other fields can raise read errors and +** the creation of the error message can call an emergency collection; +** in that case all prototypes must be consistent for the GC. +*/ static void loadUpvalues (LoadState *S, Proto *f) { int i, n; n = loadInt(S); f->upvalues = luaM_newvectorchecked(S->L, n, Upvaldesc); f->sizeupvalues = n; - for (i = 0; i < n; i++) { + for (i = 0; i < n; i++) /* make array valid for GC */ f->upvalues[i].name = NULL; + for (i = 0; i < n; i++) { /* following calls can raise errors */ f->upvalues[i].instack = loadByte(S); f->upvalues[i].idx = loadByte(S); f->upvalues[i].kind = loadByte(S); diff --git a/testes/calls.lua b/testes/calls.lua index 1701f155..decf4176 100644 --- a/testes/calls.lua +++ b/testes/calls.lua @@ -422,20 +422,30 @@ assert((function (a) return a end)() == nil) print("testing binary chunks") do - local header = string.pack("c4BBc6BBBj", + local header = string.pack("c4BBc6BBB", "\27Lua", -- signature 0x54, -- version 5.4 (0x54) 0, -- format "\x19\x93\r\n\x1a\n", -- data 4, -- size of instruction string.packsize("j"), -- sizeof(lua integer) - string.packsize("n"), -- sizeof(lua number) - 0x5678 -- LUAC_INT - -- LUAC_NUM may not have a unique binary representation (padding...) + string.packsize("n") -- sizeof(lua number) ) - local c = string.dump(function () local a = 1; local b = 3; return a+b*3 end) + local c = string.dump(function () + local a = 1; local b = 3; + local f = function () return a + b + _ENV.c; end -- upvalues + local s1 = "a constant" + local s2 = "another constant" + return a + b * 3 + end) + assert(assert(load(c))() == 10) + + -- check header assert(string.sub(c, 1, #header) == header) + -- check LUAC_INT and LUAC_NUM + local ci, cn = string.unpack("jn", c, #header + 1) + assert(ci == 0x5678 and cn == 370.5) -- corrupted header for i = 1, #header do @@ -451,7 +461,6 @@ do local st, msg = load(string.sub(c, 1, i)) assert(not st and string.find(msg, "truncated")) end - assert(assert(load(c))() == 10) end print('OK')