Compare commits
10 Commits
508d7afc7d
...
b0e619426d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0e619426d | ||
|
|
06777b4ffc | ||
|
|
8148fa61b6 | ||
|
|
ea404f7ebf | ||
|
|
135922521d | ||
|
|
db11036d1a | ||
|
|
9788b313db | ||
|
|
b07366fdc6 | ||
|
|
6d88b9c460 | ||
|
|
b46f3dc542 |
@ -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
|
||||||
117
backport-C-functions-can-be-tail-called-too.patch
Normal file
117
backport-C-functions-can-be-tail-called-too.patch
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
From 04e19712a5d48b84869f9942836ff8314fb0be8e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
|
||||||
|
Date: Mon, 14 Jun 2021 13:28:21 -0300
|
||||||
|
Subject: [PATCH] C functions can be tail called, too
|
||||||
|
|
||||||
|
A tail call to a C function can have the behavior of a "real" tail
|
||||||
|
call, reusing the stack frame of the caller.
|
||||||
|
|
||||||
|
---
|
||||||
|
src/ldo.c | 43 +++++++++++++++++++++++++------------------
|
||||||
|
src/lvm.c | 9 +--------
|
||||||
|
4 files changed, 29 insertions(+), 29 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/ldo.c b/src/ldo.c
|
||||||
|
index a410461b..38540561 100644
|
||||||
|
--- a/src/ldo.c
|
||||||
|
+++ b/src/ldo.c
|
||||||
|
@@ -478,12 +478,31 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) {
|
||||||
|
** (This is done only when no more errors can occur before entering the
|
||||||
|
** new function, to keep debug information always consistent.)
|
||||||
|
*/
|
||||||
|
-static void moveparams (lua_State *L, StkId prevf, StkId func, int narg) {
|
||||||
|
+static void moveparams (lua_State *L, StkId prevf, StkId func) {
|
||||||
|
int i;
|
||||||
|
- narg++; /* function itself will be moved, too */
|
||||||
|
- for (i = 0; i < narg; i++) /* move down function and arguments */
|
||||||
|
+ for (i = 0; func + i < L->top; i++) /* move down function and arguments */
|
||||||
|
setobjs2s(L, prevf + i, func + i);
|
||||||
|
- L->top = prevf + narg; /* correct top */
|
||||||
|
+ L->top = prevf + i; /* correct top */
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static CallInfo *prepCallInfo (lua_State *L, StkId func, int nresults,
|
||||||
|
+ int delta1, int mask) {
|
||||||
|
+ CallInfo *ci;
|
||||||
|
+ if (delta1) { /* tail call? */
|
||||||
|
+ ci = L->ci; /* reuse stack frame */
|
||||||
|
+ ci->func -= delta1 - 1; /* correct 'func' */
|
||||||
|
+
|
||||||
|
+ ci->callstatus |= mask | CIST_TAIL;
|
||||||
|
+ moveparams(L, ci->func, func);
|
||||||
|
+ }
|
||||||
|
+ else { /* regular call */
|
||||||
|
+ ci = L->ci = next_ci(L); /* new frame */
|
||||||
|
+ ci->func = func;
|
||||||
|
+ ci->nresults = nresults;
|
||||||
|
+ ci->callstatus = mask;
|
||||||
|
+ }
|
||||||
|
+ return ci;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -512,11 +531,8 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults, int delta1) {
|
||||||
|
int n; /* number of returns */
|
||||||
|
CallInfo *ci;
|
||||||
|
checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
|
||||||
|
- L->ci = ci = next_ci(L);
|
||||||
|
- ci->nresults = nresults;
|
||||||
|
- ci->callstatus = CIST_C;
|
||||||
|
+ ci = prepCallInfo(L, func, nresults, delta1, CIST_C);
|
||||||
|
ci->top = L->top + LUA_MINSTACK;
|
||||||
|
- ci->func = func;
|
||||||
|
lua_assert(ci->top <= L->stack_last);
|
||||||
|
if (l_unlikely(L->hookmask & LUA_MASKCALL)) {
|
||||||
|
int narg = cast_int(L->top - func) - 1;
|
||||||
|
@@ -536,16 +552,7 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults, int delta1) {
|
||||||
|
int nfixparams = p->numparams;
|
||||||
|
int fsize = p->maxstacksize; /* frame size */
|
||||||
|
checkstackGCp(L, fsize, func);
|
||||||
|
- if (delta1) { /* tail call? */
|
||||||
|
- ci = L->ci; /* reuse stack frame */
|
||||||
|
- ci->func -= delta1 - 1; /* correct 'func' */
|
||||||
|
- moveparams(L, ci->func, func, narg);
|
||||||
|
- }
|
||||||
|
- else { /* regular call */
|
||||||
|
- L->ci = ci = next_ci(L); /* new frame */
|
||||||
|
- ci->func = func;
|
||||||
|
- ci->nresults = nresults;
|
||||||
|
- }
|
||||||
|
+ ci = prepCallInfo(L, func, nresults, delta1, 0);
|
||||||
|
ci->u.l.savedpc = p->code; /* starting point */
|
||||||
|
ci->top = func + 1 + fsize;
|
||||||
|
for (; narg < nfixparams; narg++)
|
||||||
|
diff --git a/src/lvm.c b/src/lvm.c
|
||||||
|
index 485b9caa..62ff70da 100644
|
||||||
|
--- a/src/lvm.c
|
||||||
|
+++ b/src/lvm.c
|
||||||
|
@@ -1636,7 +1636,6 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
|
updatetrap(ci); /* C call; nothing else to be done */
|
||||||
|
else { /* Lua call: run function in this same C frame */
|
||||||
|
ci = newci;
|
||||||
|
- ci->callstatus = 0;
|
||||||
|
goto startfunc;
|
||||||
|
}
|
||||||
|
vmbreak;
|
||||||
|
@@ -1655,16 +1654,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
|
lua_assert(L->tbclist < base); /* no pending tbc variables */
|
||||||
|
lua_assert(base == ci->func + 1);
|
||||||
|
}
|
||||||
|
- if (luaD_precall(L, ra, LUA_MULTRET, delta + 1)) { /* Lua function? */
|
||||||
|
- ci->callstatus |= CIST_TAIL;
|
||||||
|
+ if (luaD_precall(L, ra, LUA_MULTRET, delta + 1)) /* Lua function? */
|
||||||
|
goto startfunc; /* execute the callee */
|
||||||
|
- }
|
||||||
|
else { /* C function */
|
||||||
|
updatetrap(ci);
|
||||||
|
- updatestack(ci); /* stack may have been relocated */
|
||||||
|
- ci->func -= delta; /* restore 'func' (if vararg) */
|
||||||
|
- luaD_poscall(L, ci, cast_int(L->top - ra)); /* finish caller */
|
||||||
|
- updatetrap(ci); /* 'luaD_poscall' can change hooks */
|
||||||
|
goto ret; /* caller returns after the tail call */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
34
backport-CVE-2021-45985.patch
Normal file
34
backport-CVE-2021-45985.patch
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
From cf613cdc6fa367257fc61c256f63d917350858b5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
|
||||||
|
Date: Wed, 15 Dec 2021 11:29:07 -0300
|
||||||
|
Subject: [PATCH] Bug: finalizers can be called with an invalid stack
|
||||||
|
|
||||||
|
The call to 'checkstackGC' can run finalizers, which will find an
|
||||||
|
inconsistent CallInfo, as 'ci' is half updated at the point of call.
|
||||||
|
|
||||||
|
Reference:https://github.com/lua/lua/commit/cf613cdc6fa367257fc61c256f63d917350858b5
|
||||||
|
Conflict:NA
|
||||||
|
---
|
||||||
|
src/ldo.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/ldo.c b/src/ldo.c
|
||||||
|
index f282a773..a48e35f9 100644
|
||||||
|
--- a/src/ldo.c
|
||||||
|
+++ b/src/ldo.c
|
||||||
|
@@ -530,10 +530,10 @@ int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func,
|
||||||
|
int fsize = p->maxstacksize; /* frame size */
|
||||||
|
int nfixparams = p->numparams;
|
||||||
|
int i;
|
||||||
|
+ checkstackGCp(L, fsize - delta, func);
|
||||||
|
ci->func -= delta; /* restore 'func' (if vararg) */
|
||||||
|
for (i = 0; i < narg1; i++) /* move down function and arguments */
|
||||||
|
setobjs2s(L, ci->func + i, func + i);
|
||||||
|
- checkstackGC(L, fsize);
|
||||||
|
func = ci->func; /* moved-down function */
|
||||||
|
for (; narg1 <= nfixparams; narg1++)
|
||||||
|
setnilvalue(s2v(func + narg1)); /* complete missing arguments */
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
|
|
||||||
95
backport-Emergency-new-version-5.4.6.patch
Normal file
95
backport-Emergency-new-version-5.4.6.patch
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
From 6443185167c77adcc8552a3fee7edab7895db1a9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
|
||||||
|
Date: Tue, 2 May 2023 16:41:43 -0300
|
||||||
|
Subject: [PATCH] "Emergency" new version 5.4.6
|
||||||
|
|
||||||
|
'lua_resetthread' is back to its original signature, to avoid
|
||||||
|
incompatibilities in the ABI between releases of the same version.
|
||||||
|
New function 'lua_closethread' added with the "correct" signature.
|
||||||
|
---
|
||||||
|
src/lcorolib.c | 4 ++--
|
||||||
|
src/lstate.c | 10 +++++++++-
|
||||||
|
lua-5.4.3-tests/ltests/ltests.c | 2 +-
|
||||||
|
src/lua.h | 3 ++-
|
||||||
|
4 files changed, 13 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/lcorolib.c b/src/lcorolib.c
|
||||||
|
index 40b880b1..c64adf08 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, L); /* close its tbc variables */
|
||||||
|
+ stat = lua_closethread(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, L);
|
||||||
|
+ status = lua_closethread(co, L);
|
||||||
|
if (status == LUA_OK) {
|
||||||
|
lua_pushboolean(L, 1);
|
||||||
|
return 1;
|
||||||
|
diff --git a/src/lstate.c b/src/lstate.c
|
||||||
|
index 1fbefb4b..1e925e5a 100644
|
||||||
|
--- a/src/lstate.c
|
||||||
|
+++ b/src/lstate.c
|
||||||
|
@@ -339,7 +339,7 @@ int luaE_resetthread (lua_State *L, int status) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-LUA_API int lua_resetthread (lua_State *L, lua_State *from) {
|
||||||
|
+LUA_API int lua_closethread (lua_State *L, lua_State *from) {
|
||||||
|
int status;
|
||||||
|
lua_lock(L);
|
||||||
|
L->nCcalls = (from) ? getCcalls(from) : 0;
|
||||||
|
@@ -349,6 +349,14 @@ LUA_API int lua_resetthread (lua_State *L, lua_State *from) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+** Deprecated! Use 'lua_closethread' instead.
|
||||||
|
+*/
|
||||||
|
+LUA_API int lua_resetthread (lua_State *L) {
|
||||||
|
+ return lua_closethread(L, NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
|
||||||
|
int i;
|
||||||
|
lua_State *L;
|
||||||
|
diff --git a/lua-5.4.3-tests/ltests/ltests.c b/lua-5.4.3-tests/ltests/ltests.c
|
||||||
|
index 4a0a6af1..7d184c0d 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, L));
|
||||||
|
+ lua_pushinteger(L1, lua_resetthread(L1)); /* deprecated */
|
||||||
|
}
|
||||||
|
else if EQ("newuserdata") {
|
||||||
|
lua_newuserdata(L1, getnum);
|
||||||
|
diff --git a/src/lua.h b/src/lua.h
|
||||||
|
index 01927c6d..fd16cf80 100644
|
||||||
|
--- a/src/lua.h
|
||||||
|
+++ b/src/lua.h
|
||||||
|
@@ -163,7 +163,8 @@ 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_State *from);
|
||||||
|
+LUA_API int (lua_closethread) (lua_State *L, lua_State *from);
|
||||||
|
+LUA_API int (lua_resetthread) (lua_State *L); /* Deprecated! */
|
||||||
|
|
||||||
|
LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
203
backport-More-uniform-implementation-for-tail-calls.patch
Normal file
203
backport-More-uniform-implementation-for-tail-calls.patch
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
From 1fce5bea817de50e055a84c153a975f25bfcf493 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
|
||||||
|
Date: Fri, 29 Oct 2021 13:41:24 -0300
|
||||||
|
Subject: [PATCH] More uniform implementation for tail calls
|
||||||
|
|
||||||
|
'luaD_pretailcall' mimics 'luaD_precall', handling call metamethods
|
||||||
|
and calling C functions directly. That makes the code in the
|
||||||
|
interpreter loop simpler.
|
||||||
|
|
||||||
|
This commit also goes back to emulating the tail call in 'luaD_precall'
|
||||||
|
with a goto, as C compilers may not do proper tail calls and the C
|
||||||
|
stack can overflow much sooner than the Lua stack (which grows as the
|
||||||
|
metamethod is added to it).
|
||||||
|
|
||||||
|
Reference:https://github.com/lua/lua/commit/1fce5bea817de50e055a84c153a975f25bfcf493
|
||||||
|
Conflict:NA
|
||||||
|
---
|
||||||
|
src/ldo.c | 81 ++++++++++++++++++++++++++++++++++++++---------------------
|
||||||
|
src/ldo.h | 2 +-
|
||||||
|
src/lvm.c | 19 ++++----------
|
||||||
|
3 files changed, 58 insertions(+), 44 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/ldo.c b/src/ldo.c
|
||||||
|
index 0ac12e74..d0edc8b4 100644
|
||||||
|
--- a/src/ldo.c
|
||||||
|
+++ b/src/ldo.c
|
||||||
|
@@ -475,30 +475,6 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) {
|
||||||
|
#define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L))
|
||||||
|
|
||||||
|
|
||||||
|
-/*
|
||||||
|
-** Prepare a function for a tail call, building its call info on top
|
||||||
|
-** of the current call info. 'narg1' is the number of arguments plus 1
|
||||||
|
-** (so that it includes the function itself).
|
||||||
|
-*/
|
||||||
|
-void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) {
|
||||||
|
- Proto *p = clLvalue(s2v(func))->p;
|
||||||
|
- int fsize = p->maxstacksize; /* frame size */
|
||||||
|
- int nfixparams = p->numparams;
|
||||||
|
- int i;
|
||||||
|
- for (i = 0; i < narg1; i++) /* move down function and arguments */
|
||||||
|
- setobjs2s(L, ci->func + i, func + i);
|
||||||
|
- checkstackGC(L, fsize);
|
||||||
|
- func = ci->func; /* moved-down function */
|
||||||
|
- for (; narg1 <= nfixparams; narg1++)
|
||||||
|
- setnilvalue(s2v(func + narg1)); /* complete missing arguments */
|
||||||
|
- ci->top = func + 1 + fsize; /* top for new function */
|
||||||
|
- lua_assert(ci->top <= L->stack_last);
|
||||||
|
- ci->u.l.savedpc = p->code; /* starting point */
|
||||||
|
- ci->callstatus |= CIST_TAIL;
|
||||||
|
- L->top = func + narg1; /* set top */
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret,
|
||||||
|
int mask, StkId top) {
|
||||||
|
CallInfo *ci = L->ci = next_ci(L); /* new frame */
|
||||||
|
@@ -513,7 +489,7 @@ l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret,
|
||||||
|
/*
|
||||||
|
** precall for C functions
|
||||||
|
*/
|
||||||
|
-l_sinline CallInfo *precallC (lua_State *L, StkId func, int nresults,
|
||||||
|
+l_sinline int precallC (lua_State *L, StkId func, int nresults,
|
||||||
|
lua_CFunction f) {
|
||||||
|
int n; /* number of returns */
|
||||||
|
CallInfo *ci;
|
||||||
|
@@ -530,7 +506,50 @@ l_sinline CallInfo *precallC (lua_State *L, StkId func, int nresults,
|
||||||
|
lua_lock(L);
|
||||||
|
api_checknelems(L, n);
|
||||||
|
luaD_poscall(L, ci, n);
|
||||||
|
- return NULL;
|
||||||
|
+ return n;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+** Prepare a function for a tail call, building its call info on top
|
||||||
|
+** of the current call info. 'narg1' is the number of arguments plus 1
|
||||||
|
+** (so that it includes the function itself). Return the number of
|
||||||
|
+** results, if it was a C function, or -1 for a Lua function.
|
||||||
|
+*/
|
||||||
|
+int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func,
|
||||||
|
+ int narg1, int delta) {
|
||||||
|
+ retry:
|
||||||
|
+ switch (ttypetag(s2v(func))) {
|
||||||
|
+ case LUA_VCCL: /* C closure */
|
||||||
|
+ return precallC(L, func, LUA_MULTRET, clCvalue(s2v(func))->f);
|
||||||
|
+ case LUA_VLCF: /* light C function */
|
||||||
|
+ return precallC(L, func, LUA_MULTRET, fvalue(s2v(func)));
|
||||||
|
+ case LUA_VLCL: { /* Lua function */
|
||||||
|
+ Proto *p = clLvalue(s2v(func))->p;
|
||||||
|
+ int fsize = p->maxstacksize; /* frame size */
|
||||||
|
+ int nfixparams = p->numparams;
|
||||||
|
+ int i;
|
||||||
|
+ ci->func -= delta; /* restore 'func' (if vararg) */
|
||||||
|
+ for (i = 0; i < narg1; i++) /* move down function and arguments */
|
||||||
|
+ setobjs2s(L, ci->func + i, func + i);
|
||||||
|
+ checkstackGC(L, fsize);
|
||||||
|
+ func = ci->func; /* moved-down function */
|
||||||
|
+ for (; narg1 <= nfixparams; narg1++)
|
||||||
|
+ setnilvalue(s2v(func + narg1)); /* complete missing arguments */
|
||||||
|
+ ci->top = func + 1 + fsize; /* top for new function */
|
||||||
|
+ lua_assert(ci->top <= L->stack_last);
|
||||||
|
+ ci->u.l.savedpc = p->code; /* starting point */
|
||||||
|
+ ci->callstatus |= CIST_TAIL;
|
||||||
|
+ L->top = func + narg1; /* set top */
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ default: { /* not a function */
|
||||||
|
+ func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
|
||||||
|
+ /* return luaD_pretailcall(L, ci, func, narg1 + 1, delta); */
|
||||||
|
+ narg1++;
|
||||||
|
+ goto retry; /* try again */
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -543,11 +562,14 @@ l_sinline CallInfo *precallC (lua_State *L, StkId func, int nresults,
|
||||||
|
** original function position.
|
||||||
|
*/
|
||||||
|
CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||||
|
+ retry:
|
||||||
|
switch (ttypetag(s2v(func))) {
|
||||||
|
case LUA_VCCL: /* C closure */
|
||||||
|
- return precallC(L, func, nresults, clCvalue(s2v(func))->f);
|
||||||
|
+ precallC(L, func, nresults, clCvalue(s2v(func))->f);
|
||||||
|
+ return NULL;
|
||||||
|
case LUA_VLCF: /* light C function */
|
||||||
|
- return precallC(L, func, nresults, fvalue(s2v(func)));
|
||||||
|
+ precallC(L, func, nresults, fvalue(s2v(func)));
|
||||||
|
+ return NULL;
|
||||||
|
case LUA_VLCL: { /* Lua function */
|
||||||
|
CallInfo *ci;
|
||||||
|
Proto *p = clLvalue(s2v(func))->p;
|
||||||
|
@@ -564,7 +586,8 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||||
|
}
|
||||||
|
default: { /* not a function */
|
||||||
|
func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
|
||||||
|
- return luaD_precall(L, func, nresults); /* try again with metamethod */
|
||||||
|
+ /* return luaD_precall(L, func, nresults); */
|
||||||
|
+ goto retry; /* try again with metamethod */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/src/ldo.h b/src/ldo.h
|
||||||
|
index 9fb772fe..911e67f6 100644
|
||||||
|
--- a/src/ldo.h
|
||||||
|
+++ b/src/ldo.h
|
||||||
|
@@ -58,7 +58,7 @@ LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
|
||||||
|
LUAI_FUNC void luaD_hook (lua_State *L, int event, int line,
|
||||||
|
int fTransfer, int nTransfer);
|
||||||
|
LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci);
|
||||||
|
-LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n);
|
||||||
|
+LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1, int delta);
|
||||||
|
LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults);
|
||||||
|
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
|
||||||
|
LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
|
||||||
|
diff --git a/src/lvm.c b/src/lvm.c
|
||||||
|
index 49ed3ddf..2ec34400 100644
|
||||||
|
--- a/src/lvm.c
|
||||||
|
+++ b/src/lvm.c
|
||||||
|
@@ -1643,6 +1643,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
|
}
|
||||||
|
vmcase(OP_TAILCALL) {
|
||||||
|
int b = GETARG_B(i); /* number of arguments + 1 (function) */
|
||||||
|
+ int n; /* number of results when calling a C function */
|
||||||
|
int nparams1 = GETARG_C(i);
|
||||||
|
/* delta is virtual 'func' - real 'func' (vararg functions) */
|
||||||
|
int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0;
|
||||||
|
@@ -1656,24 +1657,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
|
lua_assert(L->tbclist < base); /* no pending tbc variables */
|
||||||
|
lua_assert(base == ci->func + 1);
|
||||||
|
}
|
||||||
|
- while (!ttisfunction(s2v(ra))) { /* not a function? */
|
||||||
|
- ra = luaD_tryfuncTM(L, ra); /* try '__call' metamethod */
|
||||||
|
- b++; /* there is now one extra argument */
|
||||||
|
- }
|
||||||
|
- if (!ttisLclosure(s2v(ra))) { /* C function? */
|
||||||
|
- luaD_precall(L, ra, LUA_MULTRET); /* call it */
|
||||||
|
- updatetrap(ci);
|
||||||
|
- updatestack(ci); /* stack may have been relocated */
|
||||||
|
+ if ((n = luaD_pretailcall(L, ci, ra, b, delta)) < 0) /* Lua function? */
|
||||||
|
+ goto startfunc; /* execute the callee */
|
||||||
|
+ else { /* C function? */
|
||||||
|
ci->func -= delta; /* restore 'func' (if vararg) */
|
||||||
|
- luaD_poscall(L, ci, cast_int(L->top - ra)); /* finish caller */
|
||||||
|
+ luaD_poscall(L, ci, n); /* finish caller */
|
||||||
|
updatetrap(ci); /* 'luaD_poscall' can change hooks */
|
||||||
|
goto ret; /* caller returns after the tail call */
|
||||||
|
}
|
||||||
|
- else { /* Lua function */
|
||||||
|
- ci->func -= delta; /* restore 'func' (if vararg) */
|
||||||
|
- luaD_pretailcall(L, ci, ra, b); /* prepare call frame */
|
||||||
|
- goto startfunc; /* execute the callee */
|
||||||
|
- }
|
||||||
|
}
|
||||||
|
vmcase(OP_RETURN) {
|
||||||
|
int n = GETARG_B(i) - 1; /* number of results */
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
|
|
||||||
107
backport-Removed-goto-s-in-luaD_precall.patch
Normal file
107
backport-Removed-goto-s-in-luaD_precall.patch
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
From 3699446aaf5c7a07af028b1ae43cf52d2d4dda59 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
|
||||||
|
Date: Mon, 18 Oct 2021 11:58:40 -0300
|
||||||
|
Subject: [PATCH] Removed goto's in 'luaD_precall'
|
||||||
|
|
||||||
|
(plus a detail in src/lauxlib.h.)
|
||||||
|
---
|
||||||
|
src/lauxlib.h | 2 +-
|
||||||
|
src/ldo.c | 51 +++++++++++++++++++++++++++------------------------
|
||||||
|
2 files changed, 28 insertions(+), 25 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/lauxlib.h b/src/lauxlib.h
|
||||||
|
index 6f9695e8..5b977e2a 100644
|
||||||
|
--- a/src/lauxlib.h
|
||||||
|
+++ b/src/lauxlib.h
|
||||||
|
@@ -102,7 +102,7 @@ LUALIB_API lua_State *(luaL_newstate) (void);
|
||||||
|
|
||||||
|
LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx);
|
||||||
|
|
||||||
|
-LUALIB_API void luaL_addgsub (luaL_Buffer *b, const char *s,
|
||||||
|
+LUALIB_API void (luaL_addgsub) (luaL_Buffer *b, const char *s,
|
||||||
|
const char *p, const char *r);
|
||||||
|
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s,
|
||||||
|
const char *p, const char *r);
|
||||||
|
diff --git a/src/ldo.c b/src/ldo.c
|
||||||
|
index 88b20f95..0ac12e74 100644
|
||||||
|
--- a/src/ldo.c
|
||||||
|
+++ b/src/ldo.c
|
||||||
|
@@ -510,6 +510,30 @@ l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+** precall for C functions
|
||||||
|
+*/
|
||||||
|
+l_sinline CallInfo *precallC (lua_State *L, StkId func, int nresults,
|
||||||
|
+ lua_CFunction f) {
|
||||||
|
+ int n; /* number of returns */
|
||||||
|
+ CallInfo *ci;
|
||||||
|
+ checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
|
||||||
|
+ L->ci = ci = prepCallInfo(L, func, nresults, CIST_C,
|
||||||
|
+ L->top + LUA_MINSTACK);
|
||||||
|
+ lua_assert(ci->top <= L->stack_last);
|
||||||
|
+ if (l_unlikely(L->hookmask & LUA_MASKCALL)) {
|
||||||
|
+ int narg = cast_int(L->top - func) - 1;
|
||||||
|
+ luaD_hook(L, LUA_HOOKCALL, -1, 1, narg);
|
||||||
|
+ }
|
||||||
|
+ lua_unlock(L);
|
||||||
|
+ n = (*f)(L); /* do the actual call */
|
||||||
|
+ lua_lock(L);
|
||||||
|
+ api_checknelems(L, n);
|
||||||
|
+ luaD_poscall(L, ci, n);
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
** Prepares the call to a function (C or Lua). For C functions, also do
|
||||||
|
** the call. The function to be called is at '*func'. The arguments
|
||||||
|
@@ -519,32 +543,11 @@ l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret,
|
||||||
|
** original function position.
|
||||||
|
*/
|
||||||
|
CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||||
|
- lua_CFunction f;
|
||||||
|
- retry:
|
||||||
|
switch (ttypetag(s2v(func))) {
|
||||||
|
case LUA_VCCL: /* C closure */
|
||||||
|
- f = clCvalue(s2v(func))->f;
|
||||||
|
- goto Cfunc;
|
||||||
|
+ return precallC(L, func, nresults, clCvalue(s2v(func))->f);
|
||||||
|
case LUA_VLCF: /* light C function */
|
||||||
|
- f = fvalue(s2v(func));
|
||||||
|
- Cfunc: {
|
||||||
|
- int n; /* number of returns */
|
||||||
|
- CallInfo *ci;
|
||||||
|
- checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
|
||||||
|
- L->ci = ci = prepCallInfo(L, func, nresults, CIST_C,
|
||||||
|
- L->top + LUA_MINSTACK);
|
||||||
|
- lua_assert(ci->top <= L->stack_last);
|
||||||
|
- if (l_unlikely(L->hookmask & LUA_MASKCALL)) {
|
||||||
|
- int narg = cast_int(L->top - func) - 1;
|
||||||
|
- luaD_hook(L, LUA_HOOKCALL, -1, 1, narg);
|
||||||
|
- }
|
||||||
|
- lua_unlock(L);
|
||||||
|
- n = (*f)(L); /* do the actual call */
|
||||||
|
- lua_lock(L);
|
||||||
|
- api_checknelems(L, n);
|
||||||
|
- luaD_poscall(L, ci, n);
|
||||||
|
- return NULL;
|
||||||
|
- }
|
||||||
|
+ return precallC(L, func, nresults, fvalue(s2v(func)));
|
||||||
|
case LUA_VLCL: { /* Lua function */
|
||||||
|
CallInfo *ci;
|
||||||
|
Proto *p = clLvalue(s2v(func))->p;
|
||||||
|
@@ -561,7 +564,7 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||||
|
}
|
||||||
|
default: { /* not a function */
|
||||||
|
func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
|
||||||
|
- goto retry; /* try again with metamethod */
|
||||||
|
+ return luaD_precall(L, func, nresults); /* try again with metamethod */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
|
|
||||||
172
backport-Simpler-implementation-for-tail-calls.patch
Normal file
172
backport-Simpler-implementation-for-tail-calls.patch
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
From 901d76009346d76996679c02deee708bf225e91e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
|
||||||
|
Date: Fri, 11 Jun 2021 13:41:07 -0300
|
||||||
|
Subject: [PATCH] Simpler implementation for tail calls
|
||||||
|
|
||||||
|
Tail calls handled by 'luaD_precall', like regular calls, to avoid
|
||||||
|
code duplication.
|
||||||
|
---
|
||||||
|
src/ldo.c | 48 ++++++++++++++++++++++++------------------------
|
||||||
|
src/ldo.h | 4 ++--
|
||||||
|
src/lvm.c | 20 +++++++-------------
|
||||||
|
3 files changed, 33 insertions(+), 39 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/ldo.c b/src/ldo.c
|
||||||
|
index 7135079b..a410461b 100644
|
||||||
|
--- a/src/ldo.c
|
||||||
|
+++ b/src/ldo.c
|
||||||
|
@@ -474,26 +474,16 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) {
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
-** Prepare a function for a tail call, building its call info on top
|
||||||
|
-** of the current call info. 'narg1' is the number of arguments plus 1
|
||||||
|
-** (so that it includes the function itself).
|
||||||
|
+** In a tail call, move function and parameters to previous call frame.
|
||||||
|
+** (This is done only when no more errors can occur before entering the
|
||||||
|
+** new function, to keep debug information always consistent.)
|
||||||
|
*/
|
||||||
|
-void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) {
|
||||||
|
- Proto *p = clLvalue(s2v(func))->p;
|
||||||
|
- int fsize = p->maxstacksize; /* frame size */
|
||||||
|
- int nfixparams = p->numparams;
|
||||||
|
+static void moveparams (lua_State *L, StkId prevf, StkId func, int narg) {
|
||||||
|
int i;
|
||||||
|
- for (i = 0; i < narg1; i++) /* move down function and arguments */
|
||||||
|
- setobjs2s(L, ci->func + i, func + i);
|
||||||
|
- checkstackGC(L, fsize);
|
||||||
|
- func = ci->func; /* moved-down function */
|
||||||
|
- for (; narg1 <= nfixparams; narg1++)
|
||||||
|
- setnilvalue(s2v(func + narg1)); /* complete missing arguments */
|
||||||
|
- ci->top = func + 1 + fsize; /* top for new function */
|
||||||
|
- lua_assert(ci->top <= L->stack_last);
|
||||||
|
- ci->u.l.savedpc = p->code; /* starting point */
|
||||||
|
- ci->callstatus |= CIST_TAIL;
|
||||||
|
- L->top = func + narg1; /* set top */
|
||||||
|
+ narg++; /* function itself will be moved, too */
|
||||||
|
+ for (i = 0; i < narg; i++) /* move down function and arguments */
|
||||||
|
+ setobjs2s(L, prevf + i, func + i);
|
||||||
|
+ L->top = prevf + narg; /* correct top */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -504,8 +494,12 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) {
|
||||||
|
** to be executed, if it was a Lua function. Otherwise (a C function)
|
||||||
|
** returns NULL, with all the results on the stack, starting at the
|
||||||
|
** original function position.
|
||||||
|
+** For regular calls, 'delta1' is 0. For tail calls, 'delta1' is the
|
||||||
|
+** 'delta' (correction of base for vararg functions) plus 1, so that it
|
||||||
|
+** cannot be zero. Like 'moveparams', this correction can only be done
|
||||||
|
+** when no more errors can occur in the call.
|
||||||
|
*/
|
||||||
|
-CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||||
|
+CallInfo *luaD_precall (lua_State *L, StkId func, int nresults, int delta1) {
|
||||||
|
lua_CFunction f;
|
||||||
|
retry:
|
||||||
|
switch (ttypetag(s2v(func))) {
|
||||||
|
@@ -542,12 +536,18 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||||
|
int nfixparams = p->numparams;
|
||||||
|
int fsize = p->maxstacksize; /* frame size */
|
||||||
|
checkstackGCp(L, fsize, func);
|
||||||
|
- L->ci = ci = next_ci(L);
|
||||||
|
- ci->nresults = nresults;
|
||||||
|
+ if (delta1) { /* tail call? */
|
||||||
|
+ ci = L->ci; /* reuse stack frame */
|
||||||
|
+ ci->func -= delta1 - 1; /* correct 'func' */
|
||||||
|
+ moveparams(L, ci->func, func, narg);
|
||||||
|
+ }
|
||||||
|
+ else { /* regular call */
|
||||||
|
+ L->ci = ci = next_ci(L); /* new frame */
|
||||||
|
+ ci->func = func;
|
||||||
|
+ ci->nresults = nresults;
|
||||||
|
+ }
|
||||||
|
ci->u.l.savedpc = p->code; /* starting point */
|
||||||
|
ci->top = func + 1 + fsize;
|
||||||
|
- ci->func = func;
|
||||||
|
- L->ci = ci;
|
||||||
|
for (; narg < nfixparams; narg++)
|
||||||
|
setnilvalue(s2v(L->top++)); /* complete missing arguments */
|
||||||
|
lua_assert(ci->top <= L->stack_last);
|
||||||
|
@@ -572,7 +572,7 @@ static void ccall (lua_State *L, StkId func, int nResults, int inc) {
|
||||||
|
L->nCcalls += inc;
|
||||||
|
if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS))
|
||||||
|
luaE_checkcstack(L);
|
||||||
|
- if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */
|
||||||
|
+ if ((ci = luaD_precall(L, func, nResults, 0)) != NULL) { /* Lua function? */
|
||||||
|
ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */
|
||||||
|
luaV_execute(L, ci); /* call it */
|
||||||
|
}
|
||||||
|
diff --git a/src/ldo.h b/src/ldo.h
|
||||||
|
index 6bf0ed86..6edc4450 100644
|
||||||
|
--- a/src/ldo.h
|
||||||
|
+++ b/src/ldo.h
|
||||||
|
@@ -58,8 +58,8 @@ LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
|
||||||
|
LUAI_FUNC void luaD_hook (lua_State *L, int event, int line,
|
||||||
|
int fTransfer, int nTransfer);
|
||||||
|
LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci);
|
||||||
|
-LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n);
|
||||||
|
-LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults);
|
||||||
|
+LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nresults,
|
||||||
|
+ int delta1);
|
||||||
|
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
|
||||||
|
LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
|
||||||
|
LUAI_FUNC void luaD_tryfuncTM (lua_State *L, StkId func);
|
||||||
|
diff --git a/src/lvm.c b/src/lvm.c
|
||||||
|
index e4b1903e..485b9caa 100644
|
||||||
|
--- a/src/lvm.c
|
||||||
|
+++ b/src/lvm.c
|
||||||
|
@@ -1632,11 +1632,11 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
|
L->top = ra + b; /* top signals number of arguments */
|
||||||
|
/* else previous instruction set top */
|
||||||
|
savepc(L); /* in case of errors */
|
||||||
|
- if ((newci = luaD_precall(L, ra, nresults)) == NULL)
|
||||||
|
+ if ((newci = luaD_precall(L, ra, nresults, 0)) == NULL)
|
||||||
|
updatetrap(ci); /* C call; nothing else to be done */
|
||||||
|
else { /* Lua call: run function in this same C frame */
|
||||||
|
ci = newci;
|
||||||
|
- ci->callstatus = 0; /* call re-uses 'luaV_execute' */
|
||||||
|
+ ci->callstatus = 0;
|
||||||
|
goto startfunc;
|
||||||
|
}
|
||||||
|
vmbreak;
|
||||||
|
@@ -1648,21 +1648,18 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
|
int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0;
|
||||||
|
if (b != 0)
|
||||||
|
L->top = ra + b;
|
||||||
|
- else /* previous instruction set top */
|
||||||
|
- b = cast_int(L->top - ra);
|
||||||
|
+ /* else previous instruction set top */
|
||||||
|
savepc(ci); /* several calls here can raise errors */
|
||||||
|
if (TESTARG_k(i)) {
|
||||||
|
luaF_closeupval(L, base); /* close upvalues from current call */
|
||||||
|
lua_assert(L->tbclist < base); /* no pending tbc variables */
|
||||||
|
lua_assert(base == ci->func + 1);
|
||||||
|
}
|
||||||
|
- while (!ttisfunction(s2v(ra))) { /* not a function? */
|
||||||
|
- luaD_tryfuncTM(L, ra); /* try '__call' metamethod */
|
||||||
|
- b++; /* there is now one extra argument */
|
||||||
|
- checkstackGCp(L, 1, ra);
|
||||||
|
+ if (luaD_precall(L, ra, LUA_MULTRET, delta + 1)) { /* Lua function? */
|
||||||
|
+ ci->callstatus |= CIST_TAIL;
|
||||||
|
+ goto startfunc; /* execute the callee */
|
||||||
|
}
|
||||||
|
- if (!ttisLclosure(s2v(ra))) { /* C function? */
|
||||||
|
- luaD_precall(L, ra, LUA_MULTRET); /* call it */
|
||||||
|
+ else { /* C function */
|
||||||
|
updatetrap(ci);
|
||||||
|
updatestack(ci); /* stack may have been relocated */
|
||||||
|
ci->func -= delta; /* restore 'func' (if vararg) */
|
||||||
|
@@ -1670,9 +1667,6 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
|
updatetrap(ci); /* 'luaD_poscall' can change hooks */
|
||||||
|
goto ret; /* caller returns after the tail call */
|
||||||
|
}
|
||||||
|
- ci->func -= delta; /* restore 'func' (if vararg) */
|
||||||
|
- luaD_pretailcall(L, ci, ra, b); /* prepare call frame */
|
||||||
|
- goto startfunc; /* execute the callee */
|
||||||
|
}
|
||||||
|
vmcase(OP_RETURN) {
|
||||||
|
int n = GETARG_B(i) - 1; /* number of results */
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
|
|
||||||
139
backport-Simplification-in-the-parameters-of-luaD_precall.patch
Normal file
139
backport-Simplification-in-the-parameters-of-luaD_precall.patch
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
From dbdc74dc5502c2e05e1c1e2ac894943f418c8431 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
|
||||||
|
Date: Wed, 30 Jun 2021 12:53:21 -0300
|
||||||
|
Subject: [PATCH] Simplification in the parameters of 'luaD_precall'
|
||||||
|
|
||||||
|
The parameters 'nresults' and 'delta1', in 'luaD_precall', were never
|
||||||
|
meaningful simultaneously. So, they were combined in a single parameter
|
||||||
|
'retdel'.
|
||||||
|
---
|
||||||
|
src/ldo.c | 19 +++++++++----------
|
||||||
|
src/ldo.h | 15 +++++++++++++--
|
||||||
|
src/lvm.c | 4 ++--
|
||||||
|
3 files changed, 24 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/ldo.c b/src/ldo.c
|
||||||
|
index 38540561..93fcbb1a 100644
|
||||||
|
--- a/src/ldo.c
|
||||||
|
+++ b/src/ldo.c
|
||||||
|
@@ -486,20 +486,19 @@ static void moveparams (lua_State *L, StkId prevf, StkId func) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-static CallInfo *prepCallInfo (lua_State *L, StkId func, int nresults,
|
||||||
|
- int delta1, int mask) {
|
||||||
|
+static CallInfo *prepCallInfo (lua_State *L, StkId func, int retdel,
|
||||||
|
+ int mask) {
|
||||||
|
CallInfo *ci;
|
||||||
|
- if (delta1) { /* tail call? */
|
||||||
|
+ if (isdelta(retdel)) { /* tail call? */
|
||||||
|
ci = L->ci; /* reuse stack frame */
|
||||||
|
- ci->func -= delta1 - 1; /* correct 'func' */
|
||||||
|
-
|
||||||
|
+ ci->func -= retdel2delta(retdel); /* correct 'func' */
|
||||||
|
ci->callstatus |= mask | CIST_TAIL;
|
||||||
|
moveparams(L, ci->func, func);
|
||||||
|
}
|
||||||
|
else { /* regular call */
|
||||||
|
ci = L->ci = next_ci(L); /* new frame */
|
||||||
|
ci->func = func;
|
||||||
|
- ci->nresults = nresults;
|
||||||
|
+ ci->nresults = retdel;
|
||||||
|
ci->callstatus = mask;
|
||||||
|
}
|
||||||
|
return ci;
|
||||||
|
@@ -518,7 +517,7 @@ static CallInfo *prepCallInfo (lua_State *L, StkId func, int nresults,
|
||||||
|
** cannot be zero. Like 'moveparams', this correction can only be done
|
||||||
|
** when no more errors can occur in the call.
|
||||||
|
*/
|
||||||
|
-CallInfo *luaD_precall (lua_State *L, StkId func, int nresults, int delta1) {
|
||||||
|
+CallInfo *luaD_precall (lua_State *L, StkId func, int retdel) {
|
||||||
|
lua_CFunction f;
|
||||||
|
retry:
|
||||||
|
switch (ttypetag(s2v(func))) {
|
||||||
|
@@ -531,7 +530,7 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults, int delta1) {
|
||||||
|
int n; /* number of returns */
|
||||||
|
CallInfo *ci;
|
||||||
|
checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
|
||||||
|
- ci = prepCallInfo(L, func, nresults, delta1, CIST_C);
|
||||||
|
+ ci = prepCallInfo(L, func, retdel, CIST_C);
|
||||||
|
ci->top = L->top + LUA_MINSTACK;
|
||||||
|
lua_assert(ci->top <= L->stack_last);
|
||||||
|
if (l_unlikely(L->hookmask & LUA_MASKCALL)) {
|
||||||
|
@@ -552,7 +551,7 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults, int delta1) {
|
||||||
|
int nfixparams = p->numparams;
|
||||||
|
int fsize = p->maxstacksize; /* frame size */
|
||||||
|
checkstackGCp(L, fsize, func);
|
||||||
|
- ci = prepCallInfo(L, func, nresults, delta1, 0);
|
||||||
|
+ ci = prepCallInfo(L, func, retdel, 0);
|
||||||
|
ci->u.l.savedpc = p->code; /* starting point */
|
||||||
|
ci->top = func + 1 + fsize;
|
||||||
|
for (; narg < nfixparams; narg++)
|
||||||
|
@@ -579,7 +578,7 @@ static void ccall (lua_State *L, StkId func, int nResults, int inc) {
|
||||||
|
L->nCcalls += inc;
|
||||||
|
if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS))
|
||||||
|
luaE_checkcstack(L);
|
||||||
|
- if ((ci = luaD_precall(L, func, nResults, 0)) != NULL) { /* Lua function? */
|
||||||
|
+ if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */
|
||||||
|
ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */
|
||||||
|
luaV_execute(L, ci); /* call it */
|
||||||
|
}
|
||||||
|
diff --git a/src/ldo.h b/src/ldo.h
|
||||||
|
index 6edc4450..49fbb492 100644
|
||||||
|
--- a/src/ldo.h
|
||||||
|
+++ b/src/ldo.h
|
||||||
|
@@ -49,6 +49,18 @@
|
||||||
|
luaD_checkstackaux(L, (fsize), luaC_checkGC(L), (void)0)
|
||||||
|
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+** 'luaD_precall' is used for regular calls, when it needs the
|
||||||
|
+** number of results, and in tail calls, when it needs the 'delta'
|
||||||
|
+** (correction of base for vararg functions). The argument 'retdel'
|
||||||
|
+** codes these two options. A number of results is represented by
|
||||||
|
+** itself, while a delta is represented by 'delta2retdel(delta)'
|
||||||
|
+*/
|
||||||
|
+#define delta2retdel(d) (-(d) + LUA_MULTRET - 1)
|
||||||
|
+#define retdel2delta(d) (-(d) + LUA_MULTRET - 1)
|
||||||
|
+#define isdelta(rd) ((rd) < LUA_MULTRET)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
/* type of protected functions, to be ran by 'runprotected' */
|
||||||
|
typedef void (*Pfunc) (lua_State *L, void *ud);
|
||||||
|
|
||||||
|
@@ -58,8 +70,7 @@ LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
|
||||||
|
LUAI_FUNC void luaD_hook (lua_State *L, int event, int line,
|
||||||
|
int fTransfer, int nTransfer);
|
||||||
|
LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci);
|
||||||
|
-LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nresults,
|
||||||
|
- int delta1);
|
||||||
|
+LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int retdel);
|
||||||
|
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
|
||||||
|
LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
|
||||||
|
LUAI_FUNC void luaD_tryfuncTM (lua_State *L, StkId func);
|
||||||
|
diff --git a/src/lvm.c b/src/lvm.c
|
||||||
|
index 62ff70da..ec83f415 100644
|
||||||
|
--- a/src/lvm.c
|
||||||
|
+++ b/src/lvm.c
|
||||||
|
@@ -1632,7 +1632,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
|
L->top = ra + b; /* top signals number of arguments */
|
||||||
|
/* else previous instruction set top */
|
||||||
|
savepc(L); /* in case of errors */
|
||||||
|
- if ((newci = luaD_precall(L, ra, nresults, 0)) == NULL)
|
||||||
|
+ if ((newci = luaD_precall(L, ra, nresults)) == NULL)
|
||||||
|
updatetrap(ci); /* C call; nothing else to be done */
|
||||||
|
else { /* Lua call: run function in this same C frame */
|
||||||
|
ci = newci;
|
||||||
|
@@ -1654,7 +1654,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
|
lua_assert(L->tbclist < base); /* no pending tbc variables */
|
||||||
|
lua_assert(base == ci->func + 1);
|
||||||
|
}
|
||||||
|
- if (luaD_precall(L, ra, LUA_MULTRET, delta + 1)) /* Lua function? */
|
||||||
|
+ if (luaD_precall(L, ra, delta2retdel(delta))) /* Lua function? */
|
||||||
|
goto startfunc; /* execute the callee */
|
||||||
|
else { /* C function */
|
||||||
|
updatetrap(ci);
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
|
|
||||||
189
backport-Undo-simplification-of-tail-calls-commit-901d760.patch
Normal file
189
backport-Undo-simplification-of-tail-calls-commit-901d760.patch
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
From dbdc74dc5502c2e05e1c1e2ac894943f418c8431 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
|
||||||
|
Date: Wed, 30 Jun 2021 12:53:21 -0300
|
||||||
|
Subject: [PATCH] Simplification in the parameters of 'luaD_precall'
|
||||||
|
---
|
||||||
|
src/ldo.c | 66 +++++++++++++++++++++++++++----------------------------
|
||||||
|
src/ldo.h | 15 ++-----------
|
||||||
|
src/lvm.c | 20 +++++++++++++----
|
||||||
|
3 files changed, 50 insertions(+), 51 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/ldo.c b/src/ldo.c
|
||||||
|
index 17fb398..e2af6dc 100644
|
||||||
|
--- a/src/ldo.c
|
||||||
|
+++ b/src/ldo.c
|
||||||
|
@@ -474,33 +474,36 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) {
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
-** In a tail call, move function and parameters to previous call frame.
|
||||||
|
-** (This is done only when no more errors can occur before entering the
|
||||||
|
-** new function, to keep debug information always consistent.)
|
||||||
|
+** Prepare a function for a tail call, building its call info on top
|
||||||
|
+** of the current call info. 'narg1' is the number of arguments plus 1
|
||||||
|
+** (so that it includes the function itself).
|
||||||
|
*/
|
||||||
|
-static void moveparams (lua_State *L, StkId prevf, StkId func) {
|
||||||
|
+void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) {
|
||||||
|
+ Proto *p = clLvalue(s2v(func))->p;
|
||||||
|
+ int fsize = p->maxstacksize; /* frame size */
|
||||||
|
+ int nfixparams = p->numparams;
|
||||||
|
int i;
|
||||||
|
- for (i = 0; func + i < L->top; i++) /* move down function and arguments */
|
||||||
|
- setobjs2s(L, prevf + i, func + i);
|
||||||
|
- L->top = prevf + i; /* correct top */
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-static CallInfo *prepCallInfo (lua_State *L, StkId func, int retdel,
|
||||||
|
- int mask) {
|
||||||
|
- CallInfo *ci;
|
||||||
|
- if (isdelta(retdel)) { /* tail call? */
|
||||||
|
- ci = L->ci; /* reuse stack frame */
|
||||||
|
- ci->func -= retdel2delta(retdel); /* correct 'func' */
|
||||||
|
- ci->callstatus |= mask | CIST_TAIL;
|
||||||
|
- moveparams(L, ci->func, func);
|
||||||
|
- }
|
||||||
|
- else { /* regular call */
|
||||||
|
- ci = L->ci = next_ci(L); /* new frame */
|
||||||
|
- ci->func = func;
|
||||||
|
- ci->nresults = retdel;
|
||||||
|
- ci->callstatus = mask;
|
||||||
|
- }
|
||||||
|
+ for (i = 0; i < narg1; i++) /* move down function and arguments */
|
||||||
|
+ setobjs2s(L, ci->func + i, func + i);
|
||||||
|
+ checkstackGC(L, fsize);
|
||||||
|
+ func = ci->func; /* moved-down function */
|
||||||
|
+ for (; narg1 <= nfixparams; narg1++)
|
||||||
|
+ setnilvalue(s2v(func + narg1)); /* complete missing arguments */
|
||||||
|
+ ci->top = func + 1 + fsize; /* top for new function */
|
||||||
|
+ lua_assert(ci->top <= L->stack_last);
|
||||||
|
+ ci->u.l.savedpc = p->code; /* starting point */
|
||||||
|
+ ci->callstatus |= CIST_TAIL;
|
||||||
|
+ L->top = func + narg1; /* set top */
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static CallInfo *prepCallInfo (lua_State *L, StkId func, int nret,
|
||||||
|
+ int mask, StkId top) {
|
||||||
|
+ CallInfo *ci = L->ci = next_ci(L); /* new frame */
|
||||||
|
+ ci->func = func;
|
||||||
|
+ ci->nresults = nret;
|
||||||
|
+ ci->callstatus = mask;
|
||||||
|
+ ci->top = top;
|
||||||
|
return ci;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -512,12 +515,8 @@ static CallInfo *prepCallInfo (lua_State *L, StkId func, int retdel,
|
||||||
|
** to be executed, if it was a Lua function. Otherwise (a C function)
|
||||||
|
** returns NULL, with all the results on the stack, starting at the
|
||||||
|
** original function position.
|
||||||
|
-** For regular calls, 'delta1' is 0. For tail calls, 'delta1' is the
|
||||||
|
-** 'delta' (correction of base for vararg functions) plus 1, so that it
|
||||||
|
-** cannot be zero. Like 'moveparams', this correction can only be done
|
||||||
|
-** when no more errors can occur in the call.
|
||||||
|
*/
|
||||||
|
-CallInfo *luaD_precall (lua_State *L, StkId func, int retdel) {
|
||||||
|
+CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||||
|
lua_CFunction f;
|
||||||
|
retry:
|
||||||
|
switch (ttypetag(s2v(func))) {
|
||||||
|
@@ -530,8 +529,8 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int retdel) {
|
||||||
|
int n; /* number of returns */
|
||||||
|
CallInfo *ci;
|
||||||
|
checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
|
||||||
|
- ci = prepCallInfo(L, func, retdel, CIST_C);
|
||||||
|
- ci->top = L->top + LUA_MINSTACK;
|
||||||
|
+ L->ci = ci = prepCallInfo(L, func, nresults, CIST_C,
|
||||||
|
+ L->top + LUA_MINSTACK);
|
||||||
|
lua_assert(ci->top <= L->stack_last);
|
||||||
|
if (l_unlikely(L->hookmask & LUA_MASKCALL)) {
|
||||||
|
int narg = cast_int(L->top - func) - 1;
|
||||||
|
@@ -551,9 +550,8 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int retdel) {
|
||||||
|
int nfixparams = p->numparams;
|
||||||
|
int fsize = p->maxstacksize; /* frame size */
|
||||||
|
checkstackGCp(L, fsize, func);
|
||||||
|
- ci = prepCallInfo(L, func, retdel, 0);
|
||||||
|
+ L->ci = ci = prepCallInfo(L, func, nresults, 0, func + 1 + fsize);
|
||||||
|
ci->u.l.savedpc = p->code; /* starting point */
|
||||||
|
- ci->top = func + 1 + fsize;
|
||||||
|
for (; narg < nfixparams; narg++)
|
||||||
|
setnilvalue(s2v(L->top++)); /* complete missing arguments */
|
||||||
|
lua_assert(ci->top <= L->stack_last);
|
||||||
|
diff --git a/src/ldo.h b/src/ldo.h
|
||||||
|
index 49fbb49..6bf0ed8 100644
|
||||||
|
--- a/src/ldo.h
|
||||||
|
+++ b/src/ldo.h
|
||||||
|
@@ -49,18 +49,6 @@
|
||||||
|
luaD_checkstackaux(L, (fsize), luaC_checkGC(L), (void)0)
|
||||||
|
|
||||||
|
|
||||||
|
-/*
|
||||||
|
-** 'luaD_precall' is used for regular calls, when it needs the
|
||||||
|
-** number of results, and in tail calls, when it needs the 'delta'
|
||||||
|
-** (correction of base for vararg functions). The argument 'retdel'
|
||||||
|
-** codes these two options. A number of results is represented by
|
||||||
|
-** itself, while a delta is represented by 'delta2retdel(delta)'
|
||||||
|
-*/
|
||||||
|
-#define delta2retdel(d) (-(d) + LUA_MULTRET - 1)
|
||||||
|
-#define retdel2delta(d) (-(d) + LUA_MULTRET - 1)
|
||||||
|
-#define isdelta(rd) ((rd) < LUA_MULTRET)
|
||||||
|
-
|
||||||
|
-
|
||||||
|
/* type of protected functions, to be ran by 'runprotected' */
|
||||||
|
typedef void (*Pfunc) (lua_State *L, void *ud);
|
||||||
|
|
||||||
|
@@ -70,7 +58,8 @@ LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
|
||||||
|
LUAI_FUNC void luaD_hook (lua_State *L, int event, int line,
|
||||||
|
int fTransfer, int nTransfer);
|
||||||
|
LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci);
|
||||||
|
-LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int retdel);
|
||||||
|
+LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n);
|
||||||
|
+LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults);
|
||||||
|
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
|
||||||
|
LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
|
||||||
|
LUAI_FUNC void luaD_tryfuncTM (lua_State *L, StkId func);
|
||||||
|
diff --git a/src/lvm.c b/src/lvm.c
|
||||||
|
index 4fb426c..1541c63 100644
|
||||||
|
--- a/src/lvm.c
|
||||||
|
+++ b/src/lvm.c
|
||||||
|
@@ -1638,19 +1638,31 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
|
int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0;
|
||||||
|
if (b != 0)
|
||||||
|
L->top = ra + b;
|
||||||
|
- /* else previous instruction set top */
|
||||||
|
+ else /* previous instruction set top */
|
||||||
|
+ b = cast_int(L->top - ra);
|
||||||
|
savepc(ci); /* several calls here can raise errors */
|
||||||
|
if (TESTARG_k(i)) {
|
||||||
|
luaF_closeupval(L, base); /* close upvalues from current call */
|
||||||
|
lua_assert(L->tbclist < base); /* no pending tbc variables */
|
||||||
|
lua_assert(base == ci->func + 1);
|
||||||
|
}
|
||||||
|
- if (luaD_precall(L, ra, delta2retdel(delta))) /* Lua function? */
|
||||||
|
- goto startfunc; /* execute the callee */
|
||||||
|
- else { /* C function */
|
||||||
|
+ while (!ttisfunction(s2v(ra))) { /* not a function? */
|
||||||
|
+ luaD_tryfuncTM(L, ra); /* try '__call' metamethod */
|
||||||
|
+ b++; /* there is now one extra argument */
|
||||||
|
+ checkstackGCp(L, 1, ra);
|
||||||
|
+ }
|
||||||
|
+ if (!ttisLclosure(s2v(ra))) { /* C function? */
|
||||||
|
+ luaD_precall(L, ra, LUA_MULTRET); /* call it */
|
||||||
|
updatetrap(ci);
|
||||||
|
+ updatestack(ci); /* stack may have been relocated */
|
||||||
|
+ ci->func -= delta; /* restore 'func' (if vararg) */
|
||||||
|
+ luaD_poscall(L, ci, cast_int(L->top - ra)); /* finish caller */
|
||||||
|
+ updatetrap(ci); /* 'luaD_poscall' can change hooks */
|
||||||
|
goto ret; /* caller returns after the tail call */
|
||||||
|
}
|
||||||
|
+ ci->func -= delta; /* restore 'func' (if vararg) */
|
||||||
|
+ luaD_pretailcall(L, ci, ra, b); /* prepare call frame */
|
||||||
|
+ goto startfunc; /* execute the callee */
|
||||||
|
}
|
||||||
|
vmcase(OP_RETURN) {
|
||||||
|
int n = GETARG_B(i) - 1; /* number of results */
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
|
|
||||||
183
backport-Using-inline-in-some-functions.patch
Normal file
183
backport-Using-inline-in-some-functions.patch
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
From 2ff34717227b8046b0fdcb96206f11f5e888664e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
|
||||||
|
Date: Wed, 15 Sep 2021 11:18:41 -0300
|
||||||
|
Subject: [PATCH] Using 'inline' in some functions
|
||||||
|
|
||||||
|
According to ISO C, "making a function an inline function suggests that
|
||||||
|
calls to the function be as fast as possible." (Not available in C89.)
|
||||||
|
---
|
||||||
|
src/lapi.c | 10 +++++-----
|
||||||
|
src/ldo.c | 8 ++++----
|
||||||
|
src/llimits.h | 14 ++++++++++++++
|
||||||
|
src/lvm.c | 12 ++++++------
|
||||||
|
4 files changed, 29 insertions(+), 15 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/lapi.c b/src/lapi.c
|
||||||
|
index 7b96979..2f59d3c 100644
|
||||||
|
--- a/src/lapi.c
|
||||||
|
+++ b/src/lapi.c
|
||||||
|
@@ -81,7 +81,7 @@ static TValue *index2value (lua_State *L, int idx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-static StkId index2stack (lua_State *L, int idx) {
|
||||||
|
+l_sinline StkId index2stack (lua_State *L, int idx) {
|
||||||
|
CallInfo *ci = L->ci;
|
||||||
|
if (idx > 0) {
|
||||||
|
StkId o = ci->func + idx;
|
||||||
|
@@ -218,7 +218,7 @@ LUA_API void lua_closeslot (lua_State *L, int idx) {
|
||||||
|
** Note that we move(copy) only the value inside the stack.
|
||||||
|
** (We do not move additional fields that may exist.)
|
||||||
|
*/
|
||||||
|
-static void reverse (lua_State *L, StkId from, StkId to) {
|
||||||
|
+l_sinline void reverse (lua_State *L, StkId from, StkId to) {
|
||||||
|
for (; from < to; from++, to--) {
|
||||||
|
TValue temp;
|
||||||
|
setobj(L, &temp, s2v(from));
|
||||||
|
@@ -438,7 +438,7 @@ LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-static void *touserdata (const TValue *o) {
|
||||||
|
+l_sinline void *touserdata (const TValue *o) {
|
||||||
|
switch (ttype(o)) {
|
||||||
|
case LUA_TUSERDATA: return getudatamem(uvalue(o));
|
||||||
|
case LUA_TLIGHTUSERDATA: return pvalue(o);
|
||||||
|
@@ -630,7 +630,7 @@ LUA_API int lua_pushthread (lua_State *L) {
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
-static int auxgetstr (lua_State *L, const TValue *t, const char *k) {
|
||||||
|
+l_sinline int auxgetstr (lua_State *L, const TValue *t, const char *k) {
|
||||||
|
const TValue *slot;
|
||||||
|
TString *str = luaS_new(L, k);
|
||||||
|
if (luaV_fastget(L, t, str, slot, luaH_getstr)) {
|
||||||
|
@@ -705,7 +705,7 @@ LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-static int finishrawget (lua_State *L, const TValue *val) {
|
||||||
|
+l_sinline int finishrawget (lua_State *L, const TValue *val) {
|
||||||
|
if (isempty(val)) /* avoid copying empty items to the stack */
|
||||||
|
setnilvalue(s2v(L->top));
|
||||||
|
else
|
||||||
|
diff --git a/src/ldo.c b/src/ldo.c
|
||||||
|
index 673b975..bf2d041 100644
|
||||||
|
--- a/src/ldo.c
|
||||||
|
+++ b/src/ldo.c
|
||||||
|
@@ -407,7 +407,7 @@ StkId luaD_tryfuncTM (lua_State *L, StkId func) {
|
||||||
|
** expressions, multiple results for tail calls/single parameters)
|
||||||
|
** separated.
|
||||||
|
*/
|
||||||
|
-static void moveresults (lua_State *L, StkId res, int nres, int wanted) {
|
||||||
|
+l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) {
|
||||||
|
StkId firstresult;
|
||||||
|
int i;
|
||||||
|
switch (wanted) { /* handle typical cases separately */
|
||||||
|
@@ -499,8 +499,8 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-static CallInfo *prepCallInfo (lua_State *L, StkId func, int nret,
|
||||||
|
- int mask, StkId top) {
|
||||||
|
+l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret,
|
||||||
|
+ int mask, StkId top) {
|
||||||
|
CallInfo *ci = L->ci = next_ci(L); /* new frame */
|
||||||
|
ci->func = func;
|
||||||
|
ci->nresults = nret;
|
||||||
|
@@ -572,7 +572,7 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||||
|
** number of recursive invocations in the C stack) or nyci (the same
|
||||||
|
** plus increment number of non-yieldable calls).
|
||||||
|
*/
|
||||||
|
-static void ccall (lua_State *L, StkId func, int nResults, int inc) {
|
||||||
|
+l_sinline void ccall (lua_State *L, StkId func, int nResults, int inc) {
|
||||||
|
CallInfo *ci;
|
||||||
|
L->nCcalls += inc;
|
||||||
|
if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS))
|
||||||
|
diff --git a/src/llimits.h b/src/llimits.h
|
||||||
|
index 025f1c8..6c56ba5 100644
|
||||||
|
--- a/src/llimits.h
|
||||||
|
+++ b/src/llimits.h
|
||||||
|
@@ -165,6 +165,20 @@ typedef LUAI_UACINT l_uacInt;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+** Inline functions
|
||||||
|
+*/
|
||||||
|
+#if !defined(LUA_USE_C89)
|
||||||
|
+#define l_inline inline
|
||||||
|
+#elif defined(__GNUC__)
|
||||||
|
+#define l_inline __inline__
|
||||||
|
+#else
|
||||||
|
+#define l_inline /* empty */
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#define l_sinline static l_inline
|
||||||
|
+
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
** type for virtual-machine instructions;
|
||||||
|
** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
|
||||||
|
diff --git a/src/lvm.c b/src/lvm.c
|
||||||
|
index c16c2c6..14af102 100644
|
||||||
|
--- a/src/lvm.c
|
||||||
|
+++ b/src/lvm.c
|
||||||
|
@@ -406,7 +406,7 @@ static int l_strcmp (const TString *ls, const TString *rs) {
|
||||||
|
** from float to int.)
|
||||||
|
** When 'f' is NaN, comparisons must result in false.
|
||||||
|
*/
|
||||||
|
-static int LTintfloat (lua_Integer i, lua_Number f) {
|
||||||
|
+l_sinline int LTintfloat (lua_Integer i, lua_Number f) {
|
||||||
|
if (l_intfitsf(i))
|
||||||
|
return luai_numlt(cast_num(i), f); /* compare them as floats */
|
||||||
|
else { /* i < f <=> i < ceil(f) */
|
||||||
|
@@ -423,7 +423,7 @@ static int LTintfloat (lua_Integer i, lua_Number f) {
|
||||||
|
** Check whether integer 'i' is less than or equal to float 'f'.
|
||||||
|
** See comments on previous function.
|
||||||
|
*/
|
||||||
|
-static int LEintfloat (lua_Integer i, lua_Number f) {
|
||||||
|
+l_sinline int LEintfloat (lua_Integer i, lua_Number f) {
|
||||||
|
if (l_intfitsf(i))
|
||||||
|
return luai_numle(cast_num(i), f); /* compare them as floats */
|
||||||
|
else { /* i <= f <=> i <= floor(f) */
|
||||||
|
@@ -440,7 +440,7 @@ static int LEintfloat (lua_Integer i, lua_Number f) {
|
||||||
|
** Check whether float 'f' is less than integer 'i'.
|
||||||
|
** See comments on previous function.
|
||||||
|
*/
|
||||||
|
-static int LTfloatint (lua_Number f, lua_Integer i) {
|
||||||
|
+l_sinline int LTfloatint (lua_Number f, lua_Integer i) {
|
||||||
|
if (l_intfitsf(i))
|
||||||
|
return luai_numlt(f, cast_num(i)); /* compare them as floats */
|
||||||
|
else { /* f < i <=> floor(f) < i */
|
||||||
|
@@ -457,7 +457,7 @@ static int LTfloatint (lua_Number f, lua_Integer i) {
|
||||||
|
** Check whether float 'f' is less than or equal to integer 'i'.
|
||||||
|
** See comments on previous function.
|
||||||
|
*/
|
||||||
|
-static int LEfloatint (lua_Number f, lua_Integer i) {
|
||||||
|
+l_sinline int LEfloatint (lua_Number f, lua_Integer i) {
|
||||||
|
if (l_intfitsf(i))
|
||||||
|
return luai_numle(f, cast_num(i)); /* compare them as floats */
|
||||||
|
else { /* f <= i <=> ceil(f) <= i */
|
||||||
|
@@ -473,7 +473,7 @@ static int LEfloatint (lua_Number f, lua_Integer i) {
|
||||||
|
/*
|
||||||
|
** Return 'l < r', for numbers.
|
||||||
|
*/
|
||||||
|
-static int LTnum (const TValue *l, const TValue *r) {
|
||||||
|
+l_sinline int LTnum (const TValue *l, const TValue *r) {
|
||||||
|
lua_assert(ttisnumber(l) && ttisnumber(r));
|
||||||
|
if (ttisinteger(l)) {
|
||||||
|
lua_Integer li = ivalue(l);
|
||||||
|
@@ -495,7 +495,7 @@ static int LTnum (const TValue *l, const TValue *r) {
|
||||||
|
/*
|
||||||
|
** Return 'l <= r', for numbers.
|
||||||
|
*/
|
||||||
|
-static int LEnum (const TValue *l, const TValue *r) {
|
||||||
|
+l_sinline int LEnum (const TValue *l, const TValue *r) {
|
||||||
|
lua_assert(ttisnumber(l) && ttisnumber(r));
|
||||||
|
if (ttisinteger(l)) {
|
||||||
|
lua_Integer li = ivalue(l);
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
|
|
||||||
90
backport-luaD_tryfuncTM-checks-stack-space-by-itself.patch
Normal file
90
backport-luaD_tryfuncTM-checks-stack-space-by-itself.patch
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
From 91673a8ec0ae55e188a790bd2dfdc99246adf20e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
|
||||||
|
Date: Wed, 18 Aug 2021 12:05:06 -0300
|
||||||
|
Subject: [PATCH] 'luaD_tryfuncTM' checks stack space by itself
|
||||||
|
---
|
||||||
|
src/ldo.c | 7 ++++---
|
||||||
|
src/ldo.h | 2 +-
|
||||||
|
src/lvm.c | 11 ++++++-----
|
||||||
|
3 files changed, 11 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/ldo.c b/src/ldo.c
|
||||||
|
index fa8d98b2..889cb34b 100644
|
||||||
|
--- a/src/ldo.c
|
||||||
|
+++ b/src/ldo.c
|
||||||
|
@@ -387,15 +387,17 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) {
|
||||||
|
** stack, below original 'func', so that 'luaD_precall' can call it. Raise
|
||||||
|
** an error if there is no '__call' metafield.
|
||||||
|
*/
|
||||||
|
-void luaD_tryfuncTM (lua_State *L, StkId func) {
|
||||||
|
+StkId luaD_tryfuncTM (lua_State *L, StkId func) {
|
||||||
|
const TValue *tm = luaT_gettmbyobj(L, s2v(func), TM_CALL);
|
||||||
|
StkId p;
|
||||||
|
+ checkstackGCp(L, 1, func); /* space for metamethod */
|
||||||
|
if (l_unlikely(ttisnil(tm)))
|
||||||
|
luaG_callerror(L, s2v(func)); /* nothing to call */
|
||||||
|
for (p = L->top; p > func; p--) /* open space for metamethod */
|
||||||
|
setobjs2s(L, p, p-1);
|
||||||
|
L->top++; /* stack space pre-allocated by the caller */
|
||||||
|
setobj2s(L, func, tm); /* metamethod is the new function to be called */
|
||||||
|
+ return func;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -558,8 +560,7 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||||
|
return ci;
|
||||||
|
}
|
||||||
|
default: { /* not a function */
|
||||||
|
- checkstackGCp(L, 1, func); /* space for metamethod */
|
||||||
|
- luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
|
||||||
|
+ func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
|
||||||
|
goto retry; /* try again with metamethod */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/src/ldo.h b/src/ldo.h
|
||||||
|
index 6bf0ed86..9fb772fe 100644
|
||||||
|
--- a/src/ldo.h
|
||||||
|
+++ b/src/ldo.h
|
||||||
|
@@ -62,7 +62,7 @@ LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n);
|
||||||
|
LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults);
|
||||||
|
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
|
||||||
|
LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
|
||||||
|
-LUAI_FUNC void luaD_tryfuncTM (lua_State *L, StkId func);
|
||||||
|
+LUAI_FUNC StkId luaD_tryfuncTM (lua_State *L, StkId func);
|
||||||
|
LUAI_FUNC int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status);
|
||||||
|
LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
|
||||||
|
ptrdiff_t oldtop, ptrdiff_t ef);
|
||||||
|
diff --git a/src/lvm.c b/src/lvm.c
|
||||||
|
index df1dec83..29a211c6 100644
|
||||||
|
--- a/src/lvm.c
|
||||||
|
+++ b/src/lvm.c
|
||||||
|
@@ -1657,9 +1657,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
|
lua_assert(base == ci->func + 1);
|
||||||
|
}
|
||||||
|
while (!ttisfunction(s2v(ra))) { /* not a function? */
|
||||||
|
- luaD_tryfuncTM(L, ra); /* try '__call' metamethod */
|
||||||
|
+ ra = luaD_tryfuncTM(L, ra); /* try '__call' metamethod */
|
||||||
|
b++; /* there is now one extra argument */
|
||||||
|
- checkstackGCp(L, 1, ra);
|
||||||
|
}
|
||||||
|
if (!ttisLclosure(s2v(ra))) { /* C function? */
|
||||||
|
luaD_precall(L, ra, LUA_MULTRET); /* call it */
|
||||||
|
@@ -1670,9 +1669,11 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
|
updatetrap(ci); /* 'luaD_poscall' can change hooks */
|
||||||
|
goto ret; /* caller returns after the tail call */
|
||||||
|
}
|
||||||
|
- ci->func -= delta; /* restore 'func' (if vararg) */
|
||||||
|
- luaD_pretailcall(L, ci, ra, b); /* prepare call frame */
|
||||||
|
- goto startfunc; /* execute the callee */
|
||||||
|
+ else { /* Lua function */
|
||||||
|
+ ci->func -= delta; /* restore 'func' (if vararg) */
|
||||||
|
+ luaD_pretailcall(L, ci, ra, b); /* prepare call frame */
|
||||||
|
+ goto startfunc; /* execute the callee */
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
vmcase(OP_RETURN) {
|
||||||
|
int n = GETARG_B(i) - 1; /* number of results */
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
|
|
||||||
44
lua.spec
44
lua.spec
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
Name: lua
|
Name: lua
|
||||||
Version: 5.4.3
|
Version: 5.4.3
|
||||||
Release: 9
|
Release: 14
|
||||||
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/
|
||||||
@ -29,6 +29,19 @@ Patch6002: backport-CVE-2022-28805.patch
|
|||||||
Patch6003: backport-CVE-2022-33099.patch
|
Patch6003: backport-CVE-2022-33099.patch
|
||||||
Patch6004: backport-CVE-2021-44964.patch
|
Patch6004: backport-CVE-2021-44964.patch
|
||||||
Patch6005: backport-luaV_concat-can-use-invalidated-pointer-to-stack.patch
|
Patch6005: backport-luaV_concat-can-use-invalidated-pointer-to-stack.patch
|
||||||
|
Patch6006: backport-Simpler-implementation-for-tail-calls.patch
|
||||||
|
Patch6007: backport-C-functions-can-be-tail-called-too.patch
|
||||||
|
Patch6008: backport-Simplification-in-the-parameters-of-luaD_precall.patch
|
||||||
|
Patch6009: backport-Undo-simplification-of-tail-calls-commit-901d760.patch
|
||||||
|
Patch6010: backport-luaD_tryfuncTM-checks-stack-space-by-itself.patch
|
||||||
|
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
|
||||||
|
Patch6018: backport-Emergency-new-version-5.4.6.patch
|
||||||
|
|
||||||
BuildRequires: automake autoconf libtool readline-devel ncurses-devel
|
BuildRequires: automake autoconf libtool readline-devel ncurses-devel
|
||||||
|
|
||||||
@ -67,6 +80,19 @@ mv src/luaconf.h src/luaconf.h.template.in
|
|||||||
%patch6003 -p1
|
%patch6003 -p1
|
||||||
%patch6004 -p1
|
%patch6004 -p1
|
||||||
%patch6005 -p1
|
%patch6005 -p1
|
||||||
|
%patch6006 -p1
|
||||||
|
%patch6007 -p1
|
||||||
|
%patch6008 -p1
|
||||||
|
%patch6009 -p1
|
||||||
|
%patch6010 -p1
|
||||||
|
%patch6011 -p1
|
||||||
|
%patch6012 -p1
|
||||||
|
%patch6013 -p1
|
||||||
|
%patch6014 -p1
|
||||||
|
%patch6015 -p1
|
||||||
|
%patch6016 -p1
|
||||||
|
%patch6017 -p1
|
||||||
|
%patch6018 -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
|
||||||
@ -141,6 +167,21 @@ LD_LIBRARY_PATH=$RPM_BUILD_ROOT/%{_libdir} $RPM_BUILD_ROOT/%{_bindir}/lua -e"_U=
|
|||||||
%{_mandir}/man1/lua*.1*
|
%{_mandir}/man1/lua*.1*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed May 08 2024 fuanan <fuanan3@h-partners.com> - 5.4.3-14
|
||||||
|
- add lua_closethread to adapt interfacechange
|
||||||
|
|
||||||
|
* 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
|
||||||
|
|
||||||
|
* Tue Apr 18 2023 chenziyang <chenziyang4@huawei.com> - 5.4.3-11
|
||||||
|
- fix CVE-2021-45985 and other commits because CVE change heavily rely on these commits
|
||||||
|
|
||||||
|
* Mon Dec 26 2022 liyanan <liyanan32@h-partners.com> - 5.4.3-10
|
||||||
|
- add support for LoongArch
|
||||||
|
|
||||||
* Wed Sep 21 2022 renhongxun <renhongxun@h-partners.com> - 5.4.3-9
|
* Wed Sep 21 2022 renhongxun <renhongxun@h-partners.com> - 5.4.3-9
|
||||||
- bugfix with upstream patch
|
- bugfix with upstream patch
|
||||||
|
|
||||||
@ -182,3 +223,4 @@ LD_LIBRARY_PATH=$RPM_BUILD_ROOT/%{_libdir} $RPM_BUILD_ROOT/%{_bindir}/lua -e"_U=
|
|||||||
|
|
||||||
* Tue Sep 10 2019 openEuler Buildteam <buildteam@openeuler.org> - 5.3.5-3
|
* Tue Sep 10 2019 openEuler Buildteam <buildteam@openeuler.org> - 5.3.5-3
|
||||||
- Package init
|
- Package init
|
||||||
|
|
||||||
|
|||||||
@ -38,6 +38,8 @@
|
|||||||
#include "luaconf-arm.h"
|
#include "luaconf-arm.h"
|
||||||
#elif defined(__alpha__)
|
#elif defined(__alpha__)
|
||||||
#include "luaconf-alpha.h"
|
#include "luaconf-alpha.h"
|
||||||
|
#elif defined(__sw_64)
|
||||||
|
#include "luaconf-sw_64.h"
|
||||||
#elif defined(__sparc__) && defined (__arch64__)
|
#elif defined(__sparc__) && defined (__arch64__)
|
||||||
#include "luaconf-sparc64.h"
|
#include "luaconf-sparc64.h"
|
||||||
#elif defined(__sparc__)
|
#elif defined(__sparc__)
|
||||||
@ -54,6 +56,8 @@
|
|||||||
#include "luaconf-mips.h"
|
#include "luaconf-mips.h"
|
||||||
#elif defined(__riscv)
|
#elif defined(__riscv)
|
||||||
#include "luaconf-riscv64.h"
|
#include "luaconf-riscv64.h"
|
||||||
|
#elif defined(__loongarch64)
|
||||||
|
#include "luaconf-loongarch64.h"
|
||||||
#else
|
#else
|
||||||
#error "The lua-devel package is not usable with the architecture."
|
#error "The lua-devel package is not usable with the architecture."
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user