commit bdc85357aa41a9610498232c2cffe7aa191e5cf6
parent b291008cc2a63eb19918d4cce7e58118f4154b03
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Tue, 4 Jun 2024 17:26:46 -0300
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.
Diffstat:
3 files changed, 34 insertions(+), 23 deletions(-)
diff --git a/ldebug.c b/ldebug.c
@@ -31,7 +31,7 @@
-#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_VCCL)
+#define LuaClosure(f) ((f) != NULL && (f)->c.tt == LUA_VLCL)
static const char *funcnamefromcall (lua_State *L, CallInfo *ci,
@@ -255,7 +255,7 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
static void funcinfo (lua_Debug *ar, Closure *cl) {
- if (noLuaClosure(cl)) {
+ if (!LuaClosure(cl)) {
ar->source = "=[C]";
ar->srclen = LL("=[C]");
ar->linedefined = -1;
@@ -288,29 +288,31 @@ static int nextline (const Proto *p, int currentline, int pc) {
static void collectvalidlines (lua_State *L, Closure *f) {
- if (noLuaClosure(f)) {
+ if (!LuaClosure(f)) {
setnilvalue(s2v(L->top.p));
api_incr_top(L);
}
else {
- int i;
- TValue v;
const Proto *p = f->l.p;
int currentline = p->linedefined;
Table *t = luaH_new(L); /* new table to store active lines */
sethvalue2s(L, L->top.p, t); /* push it on stack */
api_incr_top(L);
- setbtvalue(&v); /* boolean 'true' to be the value of all indices */
- if (!(p->flag & PF_ISVARARG)) /* regular function? */
- i = 0; /* consider all instructions */
- else { /* vararg function */
- lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP);
- currentline = nextline(p, currentline, 0);
- i = 1; /* skip first instruction (OP_VARARGPREP) */
- }
- for (; i < p->sizelineinfo; i++) { /* for each instruction */
- currentline = nextline(p, currentline, i); /* get its line */
- luaH_setint(L, t, currentline, &v); /* table[line] = true */
+ if (p->lineinfo != NULL) { /* proto with debug information? */
+ int i;
+ TValue v;
+ setbtvalue(&v); /* boolean 'true' to be the value of all indices */
+ if (!(p->flag & PF_ISVARARG)) /* regular function? */
+ i = 0; /* consider all instructions */
+ else { /* vararg function */
+ lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP);
+ currentline = nextline(p, currentline, 0);
+ i = 1; /* skip first instruction (OP_VARARGPREP) */
+ }
+ for (; i < p->sizelineinfo; i++) { /* for each instruction */
+ currentline = nextline(p, currentline, i); /* get its line */
+ luaH_setint(L, t, currentline, &v); /* table[line] = true */
+ }
}
}
}
@@ -339,7 +341,7 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
}
case 'u': {
ar->nups = (f == NULL) ? 0 : f->c.nupvalues;
- if (noLuaClosure(f)) {
+ if (!LuaClosure(f)) {
ar->isvararg = 1;
ar->nparams = 0;
}
diff --git a/manual/manual.of b/manual/manual.of
@@ -8942,13 +8942,13 @@ The returned table can contain all the fields returned by @Lid{lua_getinfo},
with the string @id{what} describing which fields to fill in.
The default for @id{what} is to get all information available,
except the table of valid lines.
-If present,
-the option @Char{f}
+The option @Char{f}
adds a field named @id{func} with the function itself.
-If present,
-the option @Char{L}
-adds a field named @id{activelines} with the table of
-valid lines.
+The option @Char{L} adds a field named @id{activelines}
+with the table of valid lines,
+provided the function is a Lua function.
+If the function has no debug information,
+the table is empty.
For instance, the expression @T{debug.getinfo(1,"n").name} returns
a name for the current function,
diff --git a/testes/db.lua b/testes/db.lua
@@ -49,6 +49,15 @@ do
end
+-- bug in 5.4.4-5.4.6: activelines in vararg functions
+-- without debug information
+do
+ local func = load(string.dump(load("print(10)"), true))
+ local actl = debug.getinfo(func, "L").activelines
+ assert(#actl == 0) -- no line info
+end
+
+
-- test file and string names truncation
local a = "function f () end"
local function dostring (s, x) return load(s, x)() end