upgrade to version 5.4.6 for 22.03-LTS-Next version because 5.4.3 released 2 years ago

This commit is contained in:
ziyangc 2023-10-30 10:04:38 +08:00
parent 9788b313db
commit d738b7e376
22 changed files with 22 additions and 1815 deletions

View File

@ -1,117 +0,0 @@
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

View File

@ -1,68 +0,0 @@
From 74d99057a5146755e737c479850f87fd0e3b6868 Mon Sep 17 00:00:00 2001
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Wed, 3 Nov 2021 15:04:18 -0300
Subject: [PATCH] Bug: C stack overflow with coroutines
'coroutine.resume' did not increment counter of C calls when
continuing execution after a protected error (that is,
while running 'precover').
---
lua-5.4.3-tests/cstack.lua | 14 ++++++++++++++
src/ldo.c | 6 ++++--
2 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/lua-5.4.3-tests/cstack.lua b/lua-5.4.3-tests/cstack.lua
index 213d15d..ca76c87 100644
--- a/lua-5.4.3-tests/cstack.lua
+++ b/lua-5.4.3-tests/cstack.lua
@@ -103,6 +103,20 @@ do
end
+do -- bug in 5.4.2
+ print("nesting coroutines running after recoverable errors")
+ local count = 0
+ local function foo()
+ count = count + 1
+ pcall(1) -- create an error
+ -- running now inside 'precover' ("protected recover")
+ coroutine.wrap(foo)() -- call another coroutine
+ end
+ checkerror("C stack overflow", foo)
+ print("final count: ", count)
+end
+
+
if T then
print("testing stack recovery")
local N = 0 -- trace number of calls
diff --git a/src/ldo.c b/src/ldo.c
index 7135079..ca558fd 100644
--- a/src/ldo.c
+++ b/src/ldo.c
@@ -728,11 +728,10 @@ static void resume (lua_State *L, void *ud) {
StkId firstArg = L->top - n; /* first argument */
CallInfo *ci = L->ci;
if (L->status == LUA_OK) /* starting a coroutine? */
- ccall(L, firstArg - 1, LUA_MULTRET, 1); /* just call its body */
+ ccall(L, firstArg - 1, LUA_MULTRET, 0); /* just call its body */
else { /* resuming from previous yield */
lua_assert(L->status == LUA_YIELD);
L->status = LUA_OK; /* mark that it is running (again) */
- luaE_incCstack(L); /* control the C stack */
if (isLua(ci)) { /* yielded inside a hook? */
L->top = firstArg; /* discard arguments */
luaV_execute(L, ci); /* just continue running Lua code */
@@ -783,6 +782,9 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs,
else if (L->status != LUA_YIELD) /* ended with errors? */
return resume_error(L, "cannot resume dead coroutine", nargs);
L->nCcalls = (from) ? getCcalls(from) : 0;
+ if (getCcalls(L) >= LUAI_MAXCCALLS)
+ return resume_error(L, "C stack overflow", nargs);
+ L->nCcalls++;
luai_userstateresume(L, nargs);
api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
status = luaD_rawrunprotected(L, resume, &nargs);
--
1.8.3.1

View File

@ -1,24 +0,0 @@
From 1de95e97ef65632a88e08b6184bd9d1ceba7ec2f Mon Sep 17 00:00:00 2001
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Fri, 10 Dec 2021 10:53:54 -0300
Subject: [PATCH] Bug: Lua stack still active when closing a state
---
src/lstate.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/lstate.c b/src/lstate.c
index c5e3b43..38da773 100644
--- a/src/lstate.c
+++ b/src/lstate.c
@@ -271,6 +271,7 @@ static void close_state (lua_State *L) {
if (!completestate(g)) /* closing a partially built state? */
luaC_freeallobjects(L); /* jucst collect its objects */
else { /* closing a fully built state */
+ L->ci = &L->base_ci; /* unwind CallInfo list */
luaD_closeprotected(L, 1, LUA_OK); /* close all upvalues */
luaC_freeallobjects(L); /* collect all objects */
luai_userstateclose(L);
--
1.8.3.1

View File

@ -1,297 +0,0 @@
From 0bfc572e51d9035a615ef6e9523f736c9ffa8e57 Mon Sep 17 00:00:00 2001
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Mon, 13 Dec 2021 10:41:17 -0300
Subject: [PATCH] Bug: GC is not reentrant
As the GC is not reentrant, finalizers should not be able to invoke it.
---
lua-5.4.3-tests/api.lua | 5 ++---
lua-5.4.3-tests/gc.lua | 6 ++++--
src/lapi.c | 17 +++++++++--------
src/lbaselib.c | 19 +++++++++++++++++--
src/lgc.c | 11 +++++++----
src/lgc.h | 9 +++++++++
src/lstate.c | 4 ++--
src/lstate.h | 2 +-
8 files changed, 51 insertions(+), 22 deletions(-)
diff --git a/lua-5.4.3-tests/api.lua b/lua-5.4.3-tests/api.lua
index c1bcb4b..bd85a92 100644
--- a/lua-5.4.3-tests/api.lua
+++ b/lua-5.4.3-tests/api.lua
@@ -804,15 +804,14 @@ F = function (x)
d = nil
assert(debug.getmetatable(x).__gc == F)
assert(load("table.insert({}, {})"))() -- create more garbage
- collectgarbage() -- force a GC during GC
- assert(debug.getmetatable(x).__gc == F) -- previous GC did not mess this?
+ assert(not collectgarbage()) -- GC during GC (no op)
local dummy = {} -- create more garbage during GC
if A ~= nil then
assert(type(A) == "userdata")
assert(T.udataval(A) == B)
debug.getmetatable(A) -- just access it
end
- A = x -- ressucita userdata
+ A = x -- ressurect userdata
B = udval
return 1,2,3
end
diff --git a/lua-5.4.3-tests/gc.lua b/lua-5.4.3-tests/gc.lua
index 2332c93..d865cb2 100644
--- a/lua-5.4.3-tests/gc.lua
+++ b/lua-5.4.3-tests/gc.lua
@@ -676,11 +676,13 @@ end
-- just to make sure
assert(collectgarbage'isrunning')
-do -- check that the collector is reentrant in incremental mode
+do -- check that the collector is not reentrant in incremental mode
+ local res = true
setmetatable({}, {__gc = function ()
- collectgarbage()
+ res = collectgarbage()
end})
collectgarbage()
+ assert(not res)
end
diff --git a/src/lapi.c b/src/lapi.c
index f8f70cd..7b96979 100644
--- a/src/lapi.c
+++ b/src/lapi.c
@@ -1126,18 +1126,19 @@ LUA_API int lua_status (lua_State *L) {
LUA_API int lua_gc (lua_State *L, int what, ...) {
va_list argp;
int res = 0;
- global_State *g;
+ global_State *g = G(L);
+ if (g->gcstp & GCSTPGC) /* internal stop? */
+ return -1; /* all options are invalid when stopped */
lua_lock(L);
- g = G(L);
va_start(argp, what);
switch (what) {
case LUA_GCSTOP: {
- g->gcrunning = 0;
+ g->gcstp = GCSTPUSR; /* stopeed by the user */
break;
}
case LUA_GCRESTART: {
luaE_setdebt(g, 0);
- g->gcrunning = 1;
+ g->gcstp = 0; /* (GCSTPGC must be already zero here) */
break;
}
case LUA_GCCOLLECT: {
@@ -1156,8 +1157,8 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
case LUA_GCSTEP: {
int data = va_arg(argp, int);
l_mem debt = 1; /* =1 to signal that it did an actual step */
- lu_byte oldrunning = g->gcrunning;
- g->gcrunning = 1; /* allow GC to run */
+ lu_byte oldstp = g->gcstp;
+ g->gcstp = 0; /* allow GC to run (GCSTPGC must be zero here) */
if (data == 0) {
luaE_setdebt(g, 0); /* do a basic step */
luaC_step(L);
@@ -1167,7 +1168,7 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
luaE_setdebt(g, debt);
luaC_checkGC(L);
}
- g->gcrunning = oldrunning; /* restore previous state */
+ g->gcstp = oldstp; /* restore previous state */
if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */
res = 1; /* signal it */
break;
@@ -1185,7 +1186,7 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
break;
}
case LUA_GCISRUNNING: {
- res = g->gcrunning;
+ res = gcrunning(g);
break;
}
case LUA_GCGEN: {
diff --git a/src/lbaselib.c b/src/lbaselib.c
index 83ad306..82abd94 100644
--- a/src/lbaselib.c
+++ b/src/lbaselib.c
@@ -182,12 +182,20 @@ static int luaB_rawset (lua_State *L) {
static int pushmode (lua_State *L, int oldmode) {
- lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental"
- : "generational");
+ if (oldmode == -1)
+ luaL_pushfail(L); /* invalid call to 'lua_gc' */
+ else
+ lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental"
+ : "generational");
return 1;
}
+/*
+** check whether call to 'lua_gc' was valid (not inside a finalizer)
+*/
+#define checkvalres(res) { if (res == -1) break; }
+
static int luaB_collectgarbage (lua_State *L) {
static const char *const opts[] = {"stop", "restart", "collect",
"count", "step", "setpause", "setstepmul",
@@ -200,12 +208,14 @@ static int luaB_collectgarbage (lua_State *L) {
case LUA_GCCOUNT: {
int k = lua_gc(L, o);
int b = lua_gc(L, LUA_GCCOUNTB);
+ checkvalres(k);
lua_pushnumber(L, (lua_Number)k + ((lua_Number)b/1024));
return 1;
}
case LUA_GCSTEP: {
int step = (int)luaL_optinteger(L, 2, 0);
int res = lua_gc(L, o, step);
+ checkvalres(res);
lua_pushboolean(L, res);
return 1;
}
@@ -213,11 +223,13 @@ static int luaB_collectgarbage (lua_State *L) {
case LUA_GCSETSTEPMUL: {
int p = (int)luaL_optinteger(L, 2, 0);
int previous = lua_gc(L, o, p);
+ checkvalres(previous);
lua_pushinteger(L, previous);
return 1;
}
case LUA_GCISRUNNING: {
int res = lua_gc(L, o);
+ checkvalres(res);
lua_pushboolean(L, res);
return 1;
}
@@ -234,10 +246,13 @@ static int luaB_collectgarbage (lua_State *L) {
}
default: {
int res = lua_gc(L, o);
+ checkvalres(res);
lua_pushinteger(L, res);
return 1;
}
}
+ luaL_pushfail(L); /* invalid call (inside a finalizer) */
+ return 1;
}
diff --git a/src/lgc.c b/src/lgc.c
index b360eed..7d0b5e4 100644
--- a/src/lgc.c
+++ b/src/lgc.c
@@ -906,16 +906,16 @@ static void GCTM (lua_State *L) {
if (!notm(tm)) { /* is there a finalizer? */
int status;
lu_byte oldah = L->allowhook;
- int running = g->gcrunning;
+ int oldgcstp = g->gcstp;
+ g->gcstp = GCSTPGC; /* avoid GC steps */
L->allowhook = 0; /* stop debug hooks during GC metamethod */
- g->gcrunning = 0; /* avoid GC steps */
setobj2s(L, L->top++, tm); /* push finalizer... */
setobj2s(L, L->top++, &v); /* ... and its argument */
L->ci->callstatus |= CIST_FIN; /* will run a finalizer */
status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0);
L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */
L->allowhook = oldah; /* restore hooks */
- g->gcrunning = running; /* restore state */
+ g->gcstp = oldgcstp; /* restore state */
if (l_unlikely(status != LUA_OK)) { /* error while running __gc? */
luaE_warnerror(L, "__gc metamethod");
L->top--; /* pops error object */
@@ -1502,9 +1502,11 @@ static void deletelist (lua_State *L, GCObject *p, GCObject *limit) {
*/
void luaC_freeallobjects (lua_State *L) {
global_State *g = G(L);
+ g->gcstp = GCSTPGC;
luaC_changemode(L, KGC_INC);
separatetobefnz(g, 1); /* separate all objects with finalizers */
lua_assert(g->finobj == NULL);
+ g->gcstp = 0;
callallpendingfinalizers(L);
deletelist(L, g->allgc, obj2gco(g->mainthread));
deletelist(L, g->finobj, NULL);
@@ -1647,6 +1649,7 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
}
+
/*
** Performs a basic incremental step. The debt and step size are
** converted from bytes to "units of work"; then the function loops
@@ -1678,7 +1681,7 @@ static void incstep (lua_State *L, global_State *g) {
void luaC_step (lua_State *L) {
global_State *g = G(L);
lua_assert(!g->gcemergency);
- if (g->gcrunning) { /* running? */
+ if (gcrunning(g)) { /* running? */
if(isdecGCmodegen(g))
genstep(L, g);
else
diff --git a/src/lgc.h b/src/lgc.h
index 073e2a4..024a432 100644
--- a/src/lgc.h
+++ b/src/lgc.h
@@ -148,6 +148,15 @@
*/
#define isdecGCmodegen(g) (g->gckind == KGC_GEN || g->lastatomic != 0)
+
+/*
+** Control when GC is running:
+*/
+#define GCSTPUSR 1 /* bit true when GC stopped by user */
+#define GCSTPGC 2 /* bit true when GC stopped by itself */
+#define gcrunning(g) ((g)->gcstp == 0)
+
+
/*
** Does one step of collection when debt becomes positive. 'pre'/'pos'
** allows some adjustments to be done only when needed. macro
diff --git a/src/lstate.c b/src/lstate.c
index 38da773..59b4f21 100644
--- a/src/lstate.c
+++ b/src/lstate.c
@@ -236,7 +236,7 @@ static void f_luaopen (lua_State *L, void *ud) {
luaS_init(L);
luaT_init(L);
luaX_init(L);
- g->gcrunning = 1; /* allow gc */
+ g->gcstp = 0; /* allow gc */
setnilvalue(&g->nilvalue); /* now state is complete */
luai_userstateopen(L);
}
@@ -373,7 +373,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g->ud_warn = NULL;
g->mainthread = L;
g->seed = luai_makeseed(L);
- g->gcrunning = 0; /* no GC while building state */
+ g->gcstp = GCSTPGC; /* no GC while building state */
g->strt.size = g->strt.nuse = 0;
g->strt.hash = NULL;
setnilvalue(&g->l_registry);
diff --git a/src/lstate.h b/src/lstate.h
index c1283bb..0d2099f 100644
--- a/src/lstate.h
+++ b/src/lstate.h
@@ -263,7 +263,7 @@ typedef struct global_State {
lu_byte gcstopem; /* stops emergency collections */
lu_byte genminormul; /* control for minor generational collections */
lu_byte genmajormul; /* control for major generational collections */
- lu_byte gcrunning; /* true if GC is running */
+ lu_byte gcstp; /* control whether GC is running */
lu_byte gcemergency; /* true if this is an emergency collection */
lu_byte gcpause; /* size of pause between successive GCs */
lu_byte gcstepmul; /* GC "speed" */
--
2.33.0

View File

@ -1,34 +0,0 @@
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

View File

@ -1,46 +0,0 @@
From 1f3c6f4534c6411313361697d98d1145a1f030fa Mon Sep 17 00:00:00 2001
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Tue, 15 Feb 2022 12:28:46 -0300
Subject: [PATCH] Bug: Lua can generate wrong code when _ENV is <const>
---
lua-5.4.3-tests/attrib.lua | 10 ++++++++++
src/lparser.c | 1 +
2 files changed, 11 insertions(+)
diff --git a/lua-5.4.3-tests/attrib.lua b/lua-5.4.3-tests/attrib.lua
index b1076c7..83821c0 100644
--- a/lua-5.4.3-tests/attrib.lua
+++ b/lua-5.4.3-tests/attrib.lua
@@ -434,6 +434,16 @@ a.aVeryLongName012345678901234567890123456789012345678901234567890123456789 ==
10)
+do
+ -- _ENV constant
+ local function foo ()
+ local _ENV <const> = 11
+ X = "hi"
+ end
+ local st, msg = pcall(foo)
+ assert(not st and string.find(msg, "number"))
+end
+
-- test of large float/integer indices
diff --git a/src/lparser.c b/src/lparser.c
index 284ef1f..0626833 100644
--- a/src/lparser.c
+++ b/src/lparser.c
@@ -457,6 +457,7 @@ static void singlevar (LexState *ls, expdesc *var) {
expdesc key;
singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
lua_assert(var->k != VVOID); /* this one must exist */
+ luaK_exp2anyregup(fs, var); /* but could be a constant */
codestring(&key, varname); /* key is variable name */
luaK_indexed(fs, var, &key); /* env[varname] */
}
--
1.8.3.1

View File

@ -1,62 +0,0 @@
From 42d40581dd919fb134c07027ca1ce0844c670daf Mon Sep 17 00:00:00 2001
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Fri, 20 May 2022 13:14:33 -0300
Subject: [PATCH] Save stack space while handling errors
Because error handling (luaG_errormsg) uses slots from EXTRA_STACK,
and some errors can recur (e.g., string overflow while creating an
error message in 'luaG_runerror', or a C-stack overflow before calling
the message handler), the code should use stack slots with parsimony.
This commit fixes the bug "Lua-stack overflow when C stack overflows
while handling an error".
---
src/ldebug.c | 5 ++++-
src/lvm.c | 6 ++++--
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/ldebug.c b/src/ldebug.c
index 1feaab2..5524fae 100644
--- a/src/ldebug.c
+++ b/src/ldebug.c
@@ -783,8 +783,11 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
va_start(argp, fmt);
msg = luaO_pushvfstring(L, fmt, argp); /* format message */
va_end(argp);
- if (isLua(ci)) /* if Lua function, add source:line information */
+ if (isLua(ci)) { /* if Lua function, add source:line information */
luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci));
+ setobjs2s(L, L->top - 2, L->top - 1); /* remove 'msg' from the stack */
+ L->top--;
+ }
luaG_errormsg(L);
}
diff --git a/src/lvm.c b/src/lvm.c
index c9729bc..a965087 100644
--- a/src/lvm.c
+++ b/src/lvm.c
@@ -656,8 +656,10 @@ void luaV_concat (lua_State *L, int total) {
/* collect total length and number of strings */
for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) {
size_t l = vslen(s2v(top - n - 1));
- if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl))
+ if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl)) {
+ L->top = top - total; /* pop strings to avoid wasting stack */
luaG_runerror(L, "string length overflow");
+ }
tl += l;
}
if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */
@@ -672,7 +674,7 @@ void luaV_concat (lua_State *L, int total) {
setsvalue2s(L, top - n, ts); /* create result */
}
total -= n-1; /* got 'n' strings to create 1 new */
- L->top -= n-1; /* popped 'n' strings and pushed one */
+ L->top = top - (n - 1); /* popped 'n' strings and pushed one */
} while (total > 1); /* repeat until only 1 result left */
}
--
2.33.0

View File

@ -1,203 +0,0 @@
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

View File

@ -1,107 +0,0 @@
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

View File

@ -1,172 +0,0 @@
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

View File

@ -1,139 +0,0 @@
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

View File

@ -1,189 +0,0 @@
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

View File

@ -1,183 +0,0 @@
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

View File

@ -1,90 +0,0 @@
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

View File

@ -1,37 +0,0 @@
From 603b2c64add5fbf4b7343525cf109af0c7077695 Mon Sep 17 00:00:00 2001
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Mon, 23 May 2022 17:50:47 -0300
Subject: [PATCH] 'luaV_concat' can use invalidated pointer to stack
Bug introduced in commit 42d40581.
---
src/lvm.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/lvm.c b/src/lvm.c
index cd992aa..614df05 100644
--- a/src/lvm.c
+++ b/src/lvm.c
@@ -643,7 +643,7 @@ void luaV_concat (lua_State *L, int total) {
int n = 2; /* number of elements handled in this pass (at least 2) */
if (!(ttisstring(s2v(top - 2)) || cvt2str(s2v(top - 2))) ||
!tostring(L, s2v(top - 1)))
- luaT_tryconcatTM(L);
+ luaT_tryconcatTM(L); /* may invalidate 'top' */
else if (isemptystr(s2v(top - 1))) /* second operand is empty? */
cast_void(tostring(L, s2v(top - 2))); /* result is first operand */
else if (isemptystr(s2v(top - 2))) { /* first operand is empty string? */
@@ -673,8 +673,8 @@ void luaV_concat (lua_State *L, int total) {
}
setsvalue2s(L, top - n, ts); /* create result */
}
- total -= n-1; /* got 'n' strings to create 1 new */
- L->top = top - (n - 1); /* popped 'n' strings and pushed one */
+ total -= n - 1; /* got 'n' strings to create one new */
+ L->top -= n - 1; /* popped 'n' strings and pushed one */
} while (total > 1); /* repeat until only 1 result left */
}
--
1.8.3.1

View File

@ -1,12 +0,0 @@
diff -up lua-5.3.0/src/luaconf.h.template.in.idsize lua-5.3.0/src/luaconf.h.template.in
--- lua-5.3.0/src/luaconf.h.template.in.idsize 2015-01-15 10:23:20.515801344 -0500
+++ lua-5.3.0/src/luaconf.h.template.in 2015-01-15 10:23:48.955651916 -0500
@@ -693,7 +693,7 @@
@@ of a function in debug information.
** CHANGE it if you want a different size.
*/
-#define LUA_IDSIZE 60
+#define LUA_IDSIZE 512
/*

Binary file not shown.

Binary file not shown.

14
lua-5.4.6-idsize.patch Normal file
View File

@ -0,0 +1,14 @@
diff --git a/src/luaconf.h.template.in b/src/luaconf.h.template.in
index 1e32333..601d10e 100644
--- a/src/luaconf.h.template.in
+++ b/src/luaconf.h.template.in
@@ -762,7 +762,7 @@
** of a function in debug information.
** CHANGE it if you want a different size.
*/
-#define LUA_IDSIZE 60
+#define LUA_IDSIZE 512
/*

BIN
lua-5.4.6-tests.tar.gz Normal file

Binary file not shown.

BIN
lua-5.4.6.tar.gz Normal file

Binary file not shown.

View File

@ -1,12 +1,12 @@
%global major_version 5.4
# test version is still 5.4.3
%global test_version 5.4.3
# test version is still 5.4.6
%global test_version 5.4.6
# Place rpm-macros into proper location.
%global macrosdir %(d=%{_rpmconfigdir}/macros.d; [ -d $d ] || d=%{_sysconfdir}/rpm; echo $d)
Name: lua
Version: 5.4.3
Release: 11
Version: 5.4.6
Release: 1
Summary: A powerful, efficient, lightweight, embeddable scripting language
License: MIT
URL: http://www.lua.org/
@ -20,24 +20,9 @@ Source3: mit.txt
# rpm-macro
Source1000: macros.lua
Patch0: lua-5.4.0-beta-autotoolize.patch
Patch1: lua-5.3.0-idsize.patch
Patch1: lua-5.4.6-idsize.patch
Patch2: lua-5.2.2-configure-linux.patch
Patch3: lua-5.3.0-configure-compat-module.patch
Patch6000: backport-CVE-2021-43519.patch
Patch6001: backport-CVE-2021-44647.patch
Patch6002: backport-CVE-2022-28805.patch
Patch6003: backport-CVE-2022-33099.patch
Patch6004: backport-CVE-2021-44964.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
BuildRequires: automake autoconf libtool readline-devel ncurses-devel
@ -70,21 +55,6 @@ mv src/luaconf.h src/luaconf.h.template.in
%patch1 -p1 -z .idsize
%patch2 -p1 -z .configure-linux
%patch3 -p1 -z .configure-compat-all
%patch6000 -p1
%patch6001 -p1
%patch6002 -p1
%patch6003 -p1
%patch6004 -p1
%patch6005 -p1
%patch6006 -p1
%patch6007 -p1
%patch6008 -p1
%patch6009 -p1
%patch6010 -p1
%patch6011 -p1
%patch6012 -p1
%patch6013 -p1
%patch6014 -p1
# Put proper version in configure.ac, patch0 hardcodes 5.3.0
sed -i 's|5.3.0|%{version}|g' configure.ac
@ -159,6 +129,9 @@ LD_LIBRARY_PATH=$RPM_BUILD_ROOT/%{_libdir} $RPM_BUILD_ROOT/%{_bindir}/lua -e"_U=
%{_mandir}/man1/lua*.1*
%changelog
* Mon Oct 30 2023 chenziyang <chenziyang4@huawei.com> - 5.4.6-1
- upgrade to version 5.4.6 for 22.03-LTS-Next version because 5.4.3 released 2 years ago
* 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