fix Segmentation fault

(cherry picked from commit ce0052987074899905de4be63c7c8ddc9de9e60e)
This commit is contained in:
markeryang 2024-01-18 10:46:50 +08:00 committed by openeuler-sync-bot
parent 4b2072ec5e
commit 360d5180b8
4 changed files with 437 additions and 1 deletions

View File

@ -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

View 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

View File

@ -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

View File

@ -6,7 +6,7 @@
Name: lua Name: lua
Version: 5.4.3 Version: 5.4.3
Release: 12 Release: 13
Summary: A powerful, efficient, lightweight, embeddable scripting language Summary: A powerful, efficient, lightweight, embeddable scripting language
License: MIT License: MIT
URL: http://www.lua.org/ 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 Patch6012: backport-Removed-goto-s-in-luaD_precall.patch
Patch6013: backport-More-uniform-implementation-for-tail-calls.patch Patch6013: backport-More-uniform-implementation-for-tail-calls.patch
Patch6014: backport-CVE-2021-45985.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 BuildRequires: automake autoconf libtool readline-devel ncurses-devel
@ -85,6 +88,9 @@ mv src/luaconf.h src/luaconf.h.template.in
%patch6012 -p1 %patch6012 -p1
%patch6013 -p1 %patch6013 -p1
%patch6014 -p1 %patch6014 -p1
%patch6015 -p1
%patch6016 -p1
%patch6017 -p1
# Put proper version in configure.ac, patch0 hardcodes 5.3.0 # Put proper version in configure.ac, patch0 hardcodes 5.3.0
sed -i 's|5.3.0|%{version}|g' configure.ac 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* %{_mandir}/man1/lua*.1*
%changelog %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 * Tue Aug 22 2023 panchenbo <panchenbo@kylinsec.com.cn> - 5.4.3-12
- add sw_64 support - add sw_64 support