aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-06-30 15:36:26 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-06-30 15:36:26 -0300
commit422ce50d2e8856ed789d1359c673122dbb0088ea (patch)
tree163c566c322915b12d13e4b1d1966d5658e19086
parentc33b1728aeb7dfeec4013562660e07d32697aa6b (diff)
downloadlua-422ce50d2e8856ed789d1359c673122dbb0088ea.tar.gz
lua-422ce50d2e8856ed789d1359c673122dbb0088ea.tar.bz2
lua-422ce50d2e8856ed789d1359c673122dbb0088ea.zip
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.
-rw-r--r--lapi.c1
-rw-r--r--lundump.c9
-rw-r--r--testes/calls.lua21
3 files changed, 24 insertions, 7 deletions
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) {
563 while (n--) { 563 while (n--) {
564 setobj2n(L, &cl->upvalue[n], s2v(L->top + n)); 564 setobj2n(L, &cl->upvalue[n], s2v(L->top + n));
565 /* does not need barrier because closure is white */ 565 /* does not need barrier because closure is white */
566 lua_assert(iswhite(cl));
566 } 567 }
567 setclCvalue(L, s2v(L->top), cl); 568 setclCvalue(L, s2v(L->top), cl);
568 api_incr_top(L); 569 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) {
200} 200}
201 201
202 202
203/*
204** Load the upvalues for a function. The names must be filled first,
205** because the filling of the other fields can raise read errors and
206** the creation of the error message can call an emergency collection;
207** in that case all prototypes must be consistent for the GC.
208*/
203static void loadUpvalues (LoadState *S, Proto *f) { 209static void loadUpvalues (LoadState *S, Proto *f) {
204 int i, n; 210 int i, n;
205 n = loadInt(S); 211 n = loadInt(S);
206 f->upvalues = luaM_newvectorchecked(S->L, n, Upvaldesc); 212 f->upvalues = luaM_newvectorchecked(S->L, n, Upvaldesc);
207 f->sizeupvalues = n; 213 f->sizeupvalues = n;
208 for (i = 0; i < n; i++) { 214 for (i = 0; i < n; i++) /* make array valid for GC */
209 f->upvalues[i].name = NULL; 215 f->upvalues[i].name = NULL;
216 for (i = 0; i < n; i++) { /* following calls can raise errors */
210 f->upvalues[i].instack = loadByte(S); 217 f->upvalues[i].instack = loadByte(S);
211 f->upvalues[i].idx = loadByte(S); 218 f->upvalues[i].idx = loadByte(S);
212 f->upvalues[i].kind = loadByte(S); 219 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)
422 422
423print("testing binary chunks") 423print("testing binary chunks")
424do 424do
425 local header = string.pack("c4BBc6BBBj", 425 local header = string.pack("c4BBc6BBB",
426 "\27Lua", -- signature 426 "\27Lua", -- signature
427 0x54, -- version 5.4 (0x54) 427 0x54, -- version 5.4 (0x54)
428 0, -- format 428 0, -- format
429 "\x19\x93\r\n\x1a\n", -- data 429 "\x19\x93\r\n\x1a\n", -- data
430 4, -- size of instruction 430 4, -- size of instruction
431 string.packsize("j"), -- sizeof(lua integer) 431 string.packsize("j"), -- sizeof(lua integer)
432 string.packsize("n"), -- sizeof(lua number) 432 string.packsize("n") -- sizeof(lua number)
433 0x5678 -- LUAC_INT
434 -- LUAC_NUM may not have a unique binary representation (padding...)
435 ) 433 )
436 local c = string.dump(function () local a = 1; local b = 3; return a+b*3 end) 434 local c = string.dump(function ()
435 local a = 1; local b = 3;
436 local f = function () return a + b + _ENV.c; end -- upvalues
437 local s1 = "a constant"
438 local s2 = "another constant"
439 return a + b * 3
440 end)
437 441
442 assert(assert(load(c))() == 10)
443
444 -- check header
438 assert(string.sub(c, 1, #header) == header) 445 assert(string.sub(c, 1, #header) == header)
446 -- check LUAC_INT and LUAC_NUM
447 local ci, cn = string.unpack("jn", c, #header + 1)
448 assert(ci == 0x5678 and cn == 370.5)
439 449
440 -- corrupted header 450 -- corrupted header
441 for i = 1, #header do 451 for i = 1, #header do
@@ -451,7 +461,6 @@ do
451 local st, msg = load(string.sub(c, 1, i)) 461 local st, msg = load(string.sub(c, 1, i))
452 assert(not st and string.find(msg, "truncated")) 462 assert(not st and string.find(msg, "truncated"))
453 end 463 end
454 assert(assert(load(c))() == 10)
455end 464end
456 465
457print('OK') 466print('OK')