mirror of https://github.com/rusefi/lua.git
Fixed detail in 'loadUpvalues'
In 'lundump.c', when loading the upvalues of a function, there can be a read error if the chunk is truncated. In that case, the creation of the error message can trigger an emergency collection while the prototype is still anchored. So, the prototype must be GC consistent before loading the upvales, which implies that it the 'name' fields must be filled with NULL before the reading.
This commit is contained in:
parent
c33b1728ae
commit
422ce50d2e
1
lapi.c
1
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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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')
|
||||
|
|
Loading…
Reference in New Issue