fix Segmentation fault
(cherry picked from commit ce0052987074899905de4be63c7c8ddc9de9e60e)
This commit is contained in:
parent
4b2072ec5e
commit
360d5180b8
@ -0,0 +1,79 @@
|
||||
From ab859fe59b464a038a45552921cb2b23892343af Mon Sep 17 00:00:00 2001
|
||||
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
|
||||
Date: Fri, 17 Mar 2023 15:52:09 -0300
|
||||
Subject: [PATCH] Bug: Loading a corrupted binary file can segfault
|
||||
|
||||
The size of the list of upvalue names are stored separated from the
|
||||
size of the list of upvalues, but they share the same array.
|
||||
---
|
||||
lua-5.4.3-tests/calls.lua | 14 ++++++++++++++
|
||||
src/ldump.c | 8 ++++++--
|
||||
src/lundump.c | 2 ++
|
||||
3 files changed, 22 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/lua-5.4.3-tests/calls.lua b/lua-5.4.3-tests/calls.lua
|
||||
index ff72d8f..65b6858 100644
|
||||
--- a/lua-5.4.3-tests/calls.lua
|
||||
+++ b/lua-5.4.3-tests/calls.lua
|
||||
@@ -327,6 +327,20 @@ do -- another bug (in 5.4.0)
|
||||
end
|
||||
|
||||
|
||||
+do -- another bug (since 5.2)
|
||||
+ -- corrupted binary dump: list of upvalue names is larger than number
|
||||
+ -- of upvalues, overflowing the array of upvalues.
|
||||
+ local code =
|
||||
+ "\x1b\x4c\x75\x61\x54\x00\x19\x93\x0d\x0a\x1a\x0a\x04\x08\x08\x78\x56\z
|
||||
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x28\x77\x40\x00\x86\x40\z
|
||||
+ \x74\x65\x6d\x70\x81\x81\x01\x00\x02\x82\x48\x00\x02\x00\xc7\x00\x01\z
|
||||
+ \x00\x80\x80\x80\x82\x00\x00\x80\x81\x82\x78\x80\x82\x81\x86\x40\x74\z
|
||||
+ \x65\x6d\x70"
|
||||
+
|
||||
+ assert(load(code)) -- segfaults in previous versions
|
||||
+end
|
||||
+
|
||||
+
|
||||
x = string.dump(load("x = 1; return x"))
|
||||
a = assert(load(read1(x), nil, "b"))
|
||||
assert(a() == 1 and _G.x == 1)
|
||||
diff --git a/src/ldump.c b/src/ldump.c
|
||||
index f848b66..f231691 100644
|
||||
--- a/src/ldump.c
|
||||
+++ b/src/ldump.c
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
+#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "lua.h"
|
||||
@@ -55,8 +56,11 @@ static void dumpByte (DumpState *D, int y) {
|
||||
}
|
||||
|
||||
|
||||
-/* dumpInt Buff Size */
|
||||
-#define DIBS ((sizeof(size_t) * 8 / 7) + 1)
|
||||
+/*
|
||||
+** 'dumpSize' buffer size: each byte can store up to 7 bits. (The "+6"
|
||||
+** rounds up the division.)
|
||||
+*/
|
||||
+#define DIBS ((sizeof(size_t) * CHAR_BIT + 6) / 7)
|
||||
|
||||
static void dumpSize (DumpState *D, size_t x) {
|
||||
lu_byte buff[DIBS];
|
||||
diff --git a/src/lundump.c b/src/lundump.c
|
||||
index 5aa55c4..8013e66 100644
|
||||
--- a/src/lundump.c
|
||||
+++ b/src/lundump.c
|
||||
@@ -248,6 +248,8 @@ static void loadDebug (LoadState *S, Proto *f) {
|
||||
f->locvars[i].endpc = loadInt(S);
|
||||
}
|
||||
n = loadInt(S);
|
||||
+ if (n != 0) /* does it have debug information? */
|
||||
+ n = f->sizeupvalues; /* must be this many */
|
||||
for (i = 0; i < n; i++)
|
||||
f->upvalues[i].name = loadStringN(S, f);
|
||||
}
|
||||
--
|
||||
2.33.0
|
||||
232
backport-Bug-Recursion-in-getobjname-can-stack-overflow.patch
Normal file
232
backport-Bug-Recursion-in-getobjname-can-stack-overflow.patch
Normal file
@ -0,0 +1,232 @@
|
||||
From 7923dbbf72da303ca1cca17efd24725668992f15 Mon Sep 17 00:00:00 2001
|
||||
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
|
||||
Date: Wed, 1 Nov 2023 12:00:54 -0300
|
||||
Subject: [PATCH] Bug: Recursion in 'getobjname' can stack overflow
|
||||
|
||||
'getobjname' now broken in two, a basic version that handles locals,
|
||||
upvalues, and constants, and a full version, which uses the basic
|
||||
version to handle table accesses (globals and fields).
|
||||
---
|
||||
lua-5.4.3-tests/errors.lua | 3 +
|
||||
src/ldebug.c | 154 ++++++++++++++++++++-----------------
|
||||
2 files changed, 87 insertions(+), 70 deletions(-)
|
||||
|
||||
diff --git a/lua-5.4.3-tests/errors.lua b/lua-5.4.3-tests/errors.lua
|
||||
index a3d0676..5cef9e1 100644
|
||||
--- a/lua-5.4.3-tests/errors.lua
|
||||
+++ b/lua-5.4.3-tests/errors.lua
|
||||
@@ -121,6 +121,9 @@ assert(not string.find(doit"a={13}; local bbbb=1; a[bbbb](3)", "'bbbb'"))
|
||||
checkmessage("a={13}; local bbbb=1; a[bbbb](3)", "number")
|
||||
checkmessage("a=(1)..{}", "a table value")
|
||||
|
||||
+-- bug in 5.4.6
|
||||
+checkmessage("a = {_ENV = {}}; print(a._ENV.x + 1)", "field 'x'")
|
||||
+
|
||||
-- calls
|
||||
checkmessage("local a; a(13)", "local 'a'")
|
||||
checkmessage([[
|
||||
diff --git a/src/ldebug.c b/src/ldebug.c
|
||||
index 5524fae..c605a8a 100644
|
||||
--- a/src/ldebug.c
|
||||
+++ b/src/ldebug.c
|
||||
@@ -416,41 +416,6 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
-static const char *getobjname (const Proto *p, int lastpc, int reg,
|
||||
- const char **name);
|
||||
-
|
||||
-
|
||||
-/*
|
||||
-** Find a "name" for the constant 'c'.
|
||||
-*/
|
||||
-static void kname (const Proto *p, int c, const char **name) {
|
||||
- TValue *kvalue = &p->k[c];
|
||||
- *name = (ttisstring(kvalue)) ? svalue(kvalue) : "?";
|
||||
-}
|
||||
-
|
||||
-
|
||||
-/*
|
||||
-** Find a "name" for the register 'c'.
|
||||
-*/
|
||||
-static void rname (const Proto *p, int pc, int c, const char **name) {
|
||||
- const char *what = getobjname(p, pc, c, name); /* search for 'c' */
|
||||
- if (!(what && *what == 'c')) /* did not find a constant name? */
|
||||
- *name = "?";
|
||||
-}
|
||||
-
|
||||
-
|
||||
-/*
|
||||
-** Find a "name" for a 'C' value in an RK instruction.
|
||||
-*/
|
||||
-static void rkname (const Proto *p, int pc, Instruction i, const char **name) {
|
||||
- int c = GETARG_C(i); /* key index */
|
||||
- if (GETARG_k(i)) /* is 'c' a constant? */
|
||||
- kname(p, c, name);
|
||||
- else /* 'c' is a register */
|
||||
- rname(p, pc, c, name);
|
||||
-}
|
||||
-
|
||||
-
|
||||
static int filterpc (int pc, int jmptarget) {
|
||||
if (pc < jmptarget) /* is code conditional (inside a jump)? */
|
||||
return -1; /* cannot know who sets that register */
|
||||
@@ -508,28 +473,29 @@ static int findsetreg (const Proto *p, int lastpc, int reg) {
|
||||
|
||||
|
||||
/*
|
||||
-** Check whether table being indexed by instruction 'i' is the
|
||||
-** environment '_ENV'
|
||||
+** Find a "name" for the constant 'c'.
|
||||
*/
|
||||
-static const char *gxf (const Proto *p, int pc, Instruction i, int isup) {
|
||||
- int t = GETARG_B(i); /* table index */
|
||||
- const char *name; /* name of indexed variable */
|
||||
- if (isup) /* is an upvalue? */
|
||||
- name = upvalname(p, t);
|
||||
- else
|
||||
- getobjname(p, pc, t, &name);
|
||||
- return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field";
|
||||
+static const char *kname (const Proto *p, int index, const char **name) {
|
||||
+ TValue *kvalue = &p->k[index];
|
||||
+ if (ttisstring(kvalue)) {
|
||||
+ *name = getstr(tsvalue(kvalue));
|
||||
+ return "constant";
|
||||
+ }
|
||||
+ else {
|
||||
+ *name = "?";
|
||||
+ return NULL;
|
||||
+ }
|
||||
}
|
||||
|
||||
|
||||
-static const char *getobjname (const Proto *p, int lastpc, int reg,
|
||||
- const char **name) {
|
||||
- int pc;
|
||||
- *name = luaF_getlocalname(p, reg + 1, lastpc);
|
||||
+static const char *basicgetobjname (const Proto *p, int *ppc, int reg,
|
||||
+ const char **name) {
|
||||
+ int pc = *ppc;
|
||||
+ *name = luaF_getlocalname(p, reg + 1, pc);
|
||||
if (*name) /* is a local? */
|
||||
return "local";
|
||||
/* else try symbolic execution */
|
||||
- pc = findsetreg(p, lastpc, reg);
|
||||
+ *ppc = pc = findsetreg(p, pc, reg);
|
||||
if (pc != -1) { /* could find instruction? */
|
||||
Instruction i = p->code[pc];
|
||||
OpCode op = GET_OPCODE(i);
|
||||
@@ -537,18 +503,80 @@ static const char *getobjname (const Proto *p, int lastpc, int reg,
|
||||
case OP_MOVE: {
|
||||
int b = GETARG_B(i); /* move from 'b' to 'a' */
|
||||
if (b < GETARG_A(i))
|
||||
- return getobjname(p, pc, b, name); /* get name for 'b' */
|
||||
+ return basicgetobjname(p, ppc, b, name); /* get name for 'b' */
|
||||
break;
|
||||
}
|
||||
+ case OP_GETUPVAL: {
|
||||
+ *name = upvalname(p, GETARG_B(i));
|
||||
+ return "upvalue";
|
||||
+ }
|
||||
+ case OP_LOADK: return kname(p, GETARG_Bx(i), name);
|
||||
+ case OP_LOADKX: return kname(p, GETARG_Ax(p->code[pc + 1]), name);
|
||||
+ default: break;
|
||||
+ }
|
||||
+ }
|
||||
+ return NULL; /* could not find reasonable name */
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+** Find a "name" for the register 'c'.
|
||||
+*/
|
||||
+static void rname (const Proto *p, int pc, int c, const char **name) {
|
||||
+ const char *what = basicgetobjname(p, &pc, c, name); /* search for 'c' */
|
||||
+ if (!(what && *what == 'c')) /* did not find a constant name? */
|
||||
+ *name = "?";
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+** Find a "name" for a 'C' value in an RK instruction.
|
||||
+*/
|
||||
+static void rkname (const Proto *p, int pc, Instruction i, const char **name) {
|
||||
+ int c = GETARG_C(i); /* key index */
|
||||
+ if (GETARG_k(i)) /* is 'c' a constant? */
|
||||
+ kname(p, c, name);
|
||||
+ else /* 'c' is a register */
|
||||
+ rname(p, pc, c, name);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+** Check whether table being indexed by instruction 'i' is the
|
||||
+** environment '_ENV'
|
||||
+*/
|
||||
+static const char *isEnv (const Proto *p, int pc, Instruction i, int isup) {
|
||||
+ int t = GETARG_B(i); /* table index */
|
||||
+ const char *name; /* name of indexed variable */
|
||||
+ if (isup) /* is 't' an upvalue? */
|
||||
+ name = upvalname(p, t);
|
||||
+ else /* 't' is a register */
|
||||
+ basicgetobjname(p, &pc, t, &name);
|
||||
+ return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field";
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+** Extend 'basicgetobjname' to handle table accesses
|
||||
+*/
|
||||
+static const char *getobjname (const Proto *p, int lastpc, int reg,
|
||||
+ const char **name) {
|
||||
+ const char *kind = basicgetobjname(p, &lastpc, reg, name);
|
||||
+ if (kind != NULL)
|
||||
+ return kind;
|
||||
+ else if (lastpc != -1) { /* could find instruction? */
|
||||
+ Instruction i = p->code[lastpc];
|
||||
+ OpCode op = GET_OPCODE(i);
|
||||
+ switch (op) {
|
||||
case OP_GETTABUP: {
|
||||
int k = GETARG_C(i); /* key index */
|
||||
kname(p, k, name);
|
||||
- return gxf(p, pc, i, 1);
|
||||
+ return isEnv(p, lastpc, i, 1);
|
||||
}
|
||||
case OP_GETTABLE: {
|
||||
int k = GETARG_C(i); /* key index */
|
||||
- rname(p, pc, k, name);
|
||||
- return gxf(p, pc, i, 0);
|
||||
+ rname(p, lastpc, k, name);
|
||||
+ return isEnv(p, lastpc, i, 0);
|
||||
}
|
||||
case OP_GETI: {
|
||||
*name = "integer index";
|
||||
@@ -557,24 +585,10 @@ static const char *getobjname (const Proto *p, int lastpc, int reg,
|
||||
case OP_GETFIELD: {
|
||||
int k = GETARG_C(i); /* key index */
|
||||
kname(p, k, name);
|
||||
- return gxf(p, pc, i, 0);
|
||||
- }
|
||||
- case OP_GETUPVAL: {
|
||||
- *name = upvalname(p, GETARG_B(i));
|
||||
- return "upvalue";
|
||||
- }
|
||||
- case OP_LOADK:
|
||||
- case OP_LOADKX: {
|
||||
- int b = (op == OP_LOADK) ? GETARG_Bx(i)
|
||||
- : GETARG_Ax(p->code[pc + 1]);
|
||||
- if (ttisstring(&p->k[b])) {
|
||||
- *name = svalue(&p->k[b]);
|
||||
- return "constant";
|
||||
- }
|
||||
- break;
|
||||
+ return isEnv(p, lastpc, i, 0);
|
||||
}
|
||||
case OP_SELF: {
|
||||
- rkname(p, pc, i, name);
|
||||
+ rkname(p, lastpc, i, name);
|
||||
return "method";
|
||||
}
|
||||
default: break; /* go through to return NULL */
|
||||
--
|
||||
2.33.0
|
||||
@ -0,0 +1,116 @@
|
||||
From 1e64c1391f9a14115b5cc82066dbf545ae73ee27 Mon Sep 17 00:00:00 2001
|
||||
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
|
||||
Date: Tue, 25 Oct 2022 16:44:06 -0300
|
||||
Subject: [PATCH] Bug: stack overflow with nesting of coroutine.close
|
||||
|
||||
---
|
||||
lua-5.4.3-tests/cstack.lua | 26 ++++++++++++++++++++++++++
|
||||
lua-5.4.3-tests/ltests/ltests.c | 2 +-
|
||||
src/lcorolib.c | 4 ++--
|
||||
src/lstate.c | 3 ++-
|
||||
src/lua.h | 2 +-
|
||||
5 files changed, 32 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/lua-5.4.3-tests/cstack.lua b/lua-5.4.3-tests/cstack.lua
|
||||
index ca76c87..97afe9f 100644
|
||||
--- a/lua-5.4.3-tests/cstack.lua
|
||||
+++ b/lua-5.4.3-tests/cstack.lua
|
||||
@@ -84,6 +84,32 @@ do -- bug in 5.4.0
|
||||
end
|
||||
|
||||
|
||||
+do -- bug since 5.4.0
|
||||
+ local count = 0
|
||||
+ print("chain of 'coroutine.close'")
|
||||
+ -- create N coroutines forming a list so that each one, when closed,
|
||||
+ -- closes the previous one. (With a large enough N, previous Lua
|
||||
+ -- versions crash in this test.)
|
||||
+ local coro = false
|
||||
+ for i = 1, 1000 do
|
||||
+ local previous = coro
|
||||
+ coro = coroutine.create(function()
|
||||
+ local cc <close> = setmetatable({}, {__close=function()
|
||||
+ count = count + 1
|
||||
+ if previous then
|
||||
+ assert(coroutine.close(previous))
|
||||
+ end
|
||||
+ end})
|
||||
+ coroutine.yield() -- leaves 'cc' pending to be closed
|
||||
+ end)
|
||||
+ assert(coroutine.resume(coro)) -- start it and run until it yields
|
||||
+ end
|
||||
+ local st, msg = coroutine.close(coro)
|
||||
+ assert(not st and string.find(msg, "C stack overflow"))
|
||||
+ print("final count: ", count)
|
||||
+end
|
||||
+
|
||||
+
|
||||
do
|
||||
print("nesting of resuming yielded coroutines")
|
||||
local count = 0
|
||||
diff --git a/lua-5.4.3-tests/ltests/ltests.c b/lua-5.4.3-tests/ltests/ltests.c
|
||||
index a50f783..ef6168b 100644
|
||||
--- a/lua-5.4.3-tests/ltests/ltests.c
|
||||
+++ b/lua-5.4.3-tests/ltests/ltests.c
|
||||
@@ -1533,7 +1533,7 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) {
|
||||
lua_newthread(L1);
|
||||
}
|
||||
else if EQ("resetthread") {
|
||||
- lua_pushinteger(L1, lua_resetthread(L1));
|
||||
+ lua_pushinteger(L1, lua_resetthread(L1, L));
|
||||
}
|
||||
else if EQ("newuserdata") {
|
||||
lua_newuserdata(L1, getnum);
|
||||
diff --git a/src/lcorolib.c b/src/lcorolib.c
|
||||
index fedbebe..c62acf2 100644
|
||||
--- a/src/lcorolib.c
|
||||
+++ b/src/lcorolib.c
|
||||
@@ -76,7 +76,7 @@ static int luaB_auxwrap (lua_State *L) {
|
||||
if (l_unlikely(r < 0)) { /* error? */
|
||||
int stat = lua_status(co);
|
||||
if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */
|
||||
- stat = lua_resetthread(co); /* close its tbc variables */
|
||||
+ stat = lua_resetthread(co, L); /* close its tbc variables */
|
||||
lua_assert(stat != LUA_OK);
|
||||
lua_xmove(co, L, 1); /* copy error message */
|
||||
}
|
||||
@@ -172,7 +172,7 @@ static int luaB_close (lua_State *L) {
|
||||
int status = auxstatus(L, co);
|
||||
switch (status) {
|
||||
case COS_DEAD: case COS_YIELD: {
|
||||
- status = lua_resetthread(co);
|
||||
+ status = lua_resetthread(co, L);
|
||||
if (status == LUA_OK) {
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
diff --git a/src/lstate.c b/src/lstate.c
|
||||
index 59b4f21..4df1fd7 100644
|
||||
--- a/src/lstate.c
|
||||
+++ b/src/lstate.c
|
||||
@@ -343,9 +343,10 @@ int luaE_resetthread (lua_State *L, int status) {
|
||||
}
|
||||
|
||||
|
||||
-LUA_API int lua_resetthread (lua_State *L) {
|
||||
+LUA_API int lua_resetthread (lua_State *L, lua_State *from) {
|
||||
int status;
|
||||
lua_lock(L);
|
||||
+ L->nCcalls = (from) ? getCcalls(from) : 0;
|
||||
status = luaE_resetthread(L, L->status);
|
||||
lua_unlock(L);
|
||||
return status;
|
||||
diff --git a/src/lua.h b/src/lua.h
|
||||
index 820535b..17ecfe5 100644
|
||||
--- a/src/lua.h
|
||||
+++ b/src/lua.h
|
||||
@@ -153,7 +153,7 @@ extern const char lua_ident[];
|
||||
LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
|
||||
LUA_API void (lua_close) (lua_State *L);
|
||||
LUA_API lua_State *(lua_newthread) (lua_State *L);
|
||||
-LUA_API int (lua_resetthread) (lua_State *L);
|
||||
+LUA_API int (lua_resetthread) (lua_State *L, lua_State *from);
|
||||
|
||||
LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
|
||||
|
||||
--
|
||||
2.33.0
|
||||
11
lua.spec
11
lua.spec
@ -6,7 +6,7 @@
|
||||
|
||||
Name: lua
|
||||
Version: 5.4.3
|
||||
Release: 12
|
||||
Release: 13
|
||||
Summary: A powerful, efficient, lightweight, embeddable scripting language
|
||||
License: MIT
|
||||
URL: http://www.lua.org/
|
||||
@ -38,6 +38,9 @@ Patch6011: backport-Using-inline-in-some-functions.patch
|
||||
Patch6012: backport-Removed-goto-s-in-luaD_precall.patch
|
||||
Patch6013: backport-More-uniform-implementation-for-tail-calls.patch
|
||||
Patch6014: backport-CVE-2021-45985.patch
|
||||
Patch6015: backport-Bug-stack-overflow-with-nesting-of-coroutine.close.patch
|
||||
Patch6016: backport-Bug-Loading-a-corrupted-binary-file-can-segfault.patch
|
||||
Patch6017: backport-Bug-Recursion-in-getobjname-can-stack-overflow.patch
|
||||
|
||||
BuildRequires: automake autoconf libtool readline-devel ncurses-devel
|
||||
|
||||
@ -85,6 +88,9 @@ mv src/luaconf.h src/luaconf.h.template.in
|
||||
%patch6012 -p1
|
||||
%patch6013 -p1
|
||||
%patch6014 -p1
|
||||
%patch6015 -p1
|
||||
%patch6016 -p1
|
||||
%patch6017 -p1
|
||||
|
||||
# Put proper version in configure.ac, patch0 hardcodes 5.3.0
|
||||
sed -i 's|5.3.0|%{version}|g' configure.ac
|
||||
@ -159,6 +165,9 @@ LD_LIBRARY_PATH=$RPM_BUILD_ROOT/%{_libdir} $RPM_BUILD_ROOT/%{_bindir}/lua -e"_U=
|
||||
%{_mandir}/man1/lua*.1*
|
||||
|
||||
%changelog
|
||||
* Thu Jan 18 2024 yanglongkang <yanglongkang@h-partners.com> - 5.4.3-13
|
||||
- fix Segmentation fault
|
||||
|
||||
* Tue Aug 22 2023 panchenbo <panchenbo@kylinsec.com.cn> - 5.4.3-12
|
||||
- add sw_64 support
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user