CVE-2020-24369: NULL Pointer Dereference (CWE-476)
value: ldebug.c in Lua 5.4.0 attempts to access debug information via the line hook of a stripped function, leading to a NULL pointer dereference.
CWE description: The product dereferences a pointer that it expects to be valid but is NULL.
CVSS v3 base score: 7.5
Published: 2020-08-17T17:15Z
Repository: https://github.com/lua/lua
Language: C
Files changed: ldebug.c, testes/db.lua
Commit date: 2020-07-27 13:23:05 -0300
Commit message: Fixed bug: line hooks in stripped functions

Line-hook handling was accessing debug info. without checking whether
it was present.

Diff: diff --git a/ldebug.c b/ldebug.c
index 9ff7edeb2..8cb00e51a 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -781,15 +781,17 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
 /*
 ** Check whether new instruction 'newpc' is in a different line from
 ** previous instruction 'oldpc'.
 */
 static int changedline (const Proto *p, int oldpc, int newpc) {
+  if (p->lineinfo == NULL)  /* no debug information? */
+    return 0;
   while (oldpc++ < newpc) {
     if (p->lineinfo[oldpc] != 0)
       return (luaG_getfuncline(p, oldpc - 1) != luaG_getfuncline(p, newpc));
   }
-  return 0;  /* no line changes in the way */
+  return 0;  /* no line changes between positions */
 }
 
 
 /*
 ** Traces the execution of a Lua function. Called before the execution
diff --git a/testes/db.lua b/testes/db.lua
index 941283f7a..5377f6ec0 100644
--- a/testes/db.lua
+++ b/testes/db.lua
@@ -882,11 +882,11 @@ do
 
 end
 
 
 print("testing debug functions on chunk without debug info")
-prog = [[-- program to be loaded without debug information
+prog = [[-- program to be loaded without debug information (strip)
 local debug = require'debug'
 local a = 12  -- a local variable
 
 local n, v = debug.getlocal(1, 1)
 assert(n == "(temporary)" and v == debug)   -- unkown name but known value
@@ -925,10 +925,27 @@ return a
 -- load 'prog' without debug info
 local f = assert(load(string.dump(load(prog), true)))
 
 assert(f() == 13)
 
+do   -- bug in 5.4.0: line hooks in stripped code
+  local function foo ()
+    local a = 1
+    local b = 2
+    return b
+  end
+
+  local s = load(string.dump(foo, true))
+  local line = true
+  debug.sethook(function (e, l)
+    assert(e == "line")
+    line = l
+  end, "l")
+  assert(s() == 2); debug.sethook(nil)
+  assert(line == nil)  -- hook called withoug debug info for 1st instruction
+end
+
 do   -- tests for 'source' in binary dumps
   local prog = [[
     return function (x)
       return function (y) 
         return x + y

Vulnerable code:   return 0;  /* no line changes in the way */
prog = [[-- program to be loaded without debug information
Fixed code:   if (p->lineinfo == NULL)  /* no debug information? */
    return 0;
  return 0;  /* no line changes between positions */
prog = [[-- program to be loaded without debug information (strip)
do   -- bug in 5.4.0: line hooks in stripped code
  local function foo ()
    local a = 1
    local b = 2
    return b
  end

  local s = load(string.dump(foo, true))
  local line = true
  debug.sethook(function (e, l)
    assert(e == "line")
    line = l
  end, "l")
  assert(s() == 2); debug.sethook(nil)
  assert(line == nil)  -- hook called withoug debug info for 1st instruction
end