diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-05-13 13:10:35 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-05-13 13:10:35 -0300 |
commit | dfbde4c7d540f81f2cc539741a2c1f4c00f91c10 (patch) | |
tree | afb17d64bd9d7b5e61f94f373561c2fa98d5e713 | |
parent | de794a6527058e75b674118b35f39dcbb13e88b1 (diff) | |
download | lua-dfbde4c7d540f81f2cc539741a2c1f4c00f91c10.tar.gz lua-dfbde4c7d540f81f2cc539741a2c1f4c00f91c10.tar.bz2 lua-dfbde4c7d540f81f2cc539741a2c1f4c00f91c10.zip |
Bug: Active-lines for stripped vararg functions
Lua seg. faults when asked to create the 'activelines' table for a
vararg function with no debug information.
-rw-r--r-- | ldebug.c | 36 | ||||
-rw-r--r-- | manual/manual.of | 12 | ||||
-rw-r--r-- | testes/db.lua | 9 |
3 files changed, 34 insertions, 23 deletions
@@ -31,7 +31,7 @@ | |||
31 | 31 | ||
32 | 32 | ||
33 | 33 | ||
34 | #define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_VCCL) | 34 | #define LuaClosure(f) ((f) != NULL && (f)->c.tt == LUA_VLCL) |
35 | 35 | ||
36 | 36 | ||
37 | static const char *funcnamefromcall (lua_State *L, CallInfo *ci, | 37 | static const char *funcnamefromcall (lua_State *L, CallInfo *ci, |
@@ -254,7 +254,7 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { | |||
254 | 254 | ||
255 | 255 | ||
256 | static void funcinfo (lua_Debug *ar, Closure *cl) { | 256 | static void funcinfo (lua_Debug *ar, Closure *cl) { |
257 | if (noLuaClosure(cl)) { | 257 | if (!LuaClosure(cl)) { |
258 | ar->source = "=[C]"; | 258 | ar->source = "=[C]"; |
259 | ar->srclen = LL("=[C]"); | 259 | ar->srclen = LL("=[C]"); |
260 | ar->linedefined = -1; | 260 | ar->linedefined = -1; |
@@ -288,29 +288,31 @@ static int nextline (const Proto *p, int currentline, int pc) { | |||
288 | 288 | ||
289 | 289 | ||
290 | static void collectvalidlines (lua_State *L, Closure *f) { | 290 | static void collectvalidlines (lua_State *L, Closure *f) { |
291 | if (noLuaClosure(f)) { | 291 | if (!LuaClosure(f)) { |
292 | setnilvalue(s2v(L->top.p)); | 292 | setnilvalue(s2v(L->top.p)); |
293 | api_incr_top(L); | 293 | api_incr_top(L); |
294 | } | 294 | } |
295 | else { | 295 | else { |
296 | int i; | ||
297 | TValue v; | ||
298 | const Proto *p = f->l.p; | 296 | const Proto *p = f->l.p; |
299 | int currentline = p->linedefined; | 297 | int currentline = p->linedefined; |
300 | Table *t = luaH_new(L); /* new table to store active lines */ | 298 | Table *t = luaH_new(L); /* new table to store active lines */ |
301 | sethvalue2s(L, L->top.p, t); /* push it on stack */ | 299 | sethvalue2s(L, L->top.p, t); /* push it on stack */ |
302 | api_incr_top(L); | 300 | api_incr_top(L); |
303 | setbtvalue(&v); /* boolean 'true' to be the value of all indices */ | 301 | if (p->lineinfo != NULL) { /* proto with debug information? */ |
304 | if (!p->is_vararg) /* regular function? */ | 302 | int i; |
305 | i = 0; /* consider all instructions */ | 303 | TValue v; |
306 | else { /* vararg function */ | 304 | setbtvalue(&v); /* boolean 'true' to be the value of all indices */ |
307 | lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP); | 305 | if (!p->is_vararg) /* regular function? */ |
308 | currentline = nextline(p, currentline, 0); | 306 | i = 0; /* consider all instructions */ |
309 | i = 1; /* skip first instruction (OP_VARARGPREP) */ | 307 | else { /* vararg function */ |
310 | } | 308 | lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP); |
311 | for (; i < p->sizelineinfo; i++) { /* for each instruction */ | 309 | currentline = nextline(p, currentline, 0); |
312 | currentline = nextline(p, currentline, i); /* get its line */ | 310 | i = 1; /* skip first instruction (OP_VARARGPREP) */ |
313 | luaH_setint(L, t, currentline, &v); /* table[line] = true */ | 311 | } |
312 | for (; i < p->sizelineinfo; i++) { /* for each instruction */ | ||
313 | currentline = nextline(p, currentline, i); /* get its line */ | ||
314 | luaH_setint(L, t, currentline, &v); /* table[line] = true */ | ||
315 | } | ||
314 | } | 316 | } |
315 | } | 317 | } |
316 | } | 318 | } |
@@ -339,7 +341,7 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, | |||
339 | } | 341 | } |
340 | case 'u': { | 342 | case 'u': { |
341 | ar->nups = (f == NULL) ? 0 : f->c.nupvalues; | 343 | ar->nups = (f == NULL) ? 0 : f->c.nupvalues; |
342 | if (noLuaClosure(f)) { | 344 | if (!LuaClosure(f)) { |
343 | ar->isvararg = 1; | 345 | ar->isvararg = 1; |
344 | ar->nparams = 0; | 346 | ar->nparams = 0; |
345 | } | 347 | } |
diff --git a/manual/manual.of b/manual/manual.of index b68d41c9..c5c74696 100644 --- a/manual/manual.of +++ b/manual/manual.of | |||
@@ -8773,13 +8773,13 @@ The returned table can contain all the fields returned by @Lid{lua_getinfo}, | |||
8773 | with the string @id{what} describing which fields to fill in. | 8773 | with the string @id{what} describing which fields to fill in. |
8774 | The default for @id{what} is to get all information available, | 8774 | The default for @id{what} is to get all information available, |
8775 | except the table of valid lines. | 8775 | except the table of valid lines. |
8776 | If present, | 8776 | The option @Char{f} |
8777 | the option @Char{f} | ||
8778 | adds a field named @id{func} with the function itself. | 8777 | adds a field named @id{func} with the function itself. |
8779 | If present, | 8778 | The option @Char{L} adds a field named @id{activelines} |
8780 | the option @Char{L} | 8779 | with the table of valid lines, |
8781 | adds a field named @id{activelines} with the table of | 8780 | provided the function is a Lua function. |
8782 | valid lines. | 8781 | If the function has no debug information, |
8782 | the table is empty. | ||
8783 | 8783 | ||
8784 | For instance, the expression @T{debug.getinfo(1,"n").name} returns | 8784 | For instance, the expression @T{debug.getinfo(1,"n").name} returns |
8785 | a name for the current function, | 8785 | a name for the current function, |
diff --git a/testes/db.lua b/testes/db.lua index d3758c41..49ff8e3e 100644 --- a/testes/db.lua +++ b/testes/db.lua | |||
@@ -49,6 +49,15 @@ do | |||
49 | end | 49 | end |
50 | 50 | ||
51 | 51 | ||
52 | -- bug in 5.4.4-5.4.6: activelines in vararg functions | ||
53 | -- without debug information | ||
54 | do | ||
55 | local func = load(string.dump(load("print(10)"), true)) | ||
56 | local actl = debug.getinfo(func, "L").activelines | ||
57 | assert(#actl == 0) -- no line info | ||
58 | end | ||
59 | |||
60 | |||
52 | -- test file and string names truncation | 61 | -- test file and string names truncation |
53 | local a = "function f () end" | 62 | local a = "function f () end" |
54 | local function dostring (s, x) return load(s, x)() end | 63 | local function dostring (s, x) return load(s, x)() end |