!53 revert version to 5.4.3
From: @markeryang Reviewed-by: @ziyangc Signed-off-by: @ziyangc
This commit is contained in:
commit
d83a59c3a1
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
|
||||||
|
|
||||||
68
backport-CVE-2021-43519.patch
Normal file
68
backport-CVE-2021-43519.patch
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
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
|
||||||
|
|
||||||
24
backport-CVE-2021-44647.patch
Normal file
24
backport-CVE-2021-44647.patch
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
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
|
||||||
|
|
||||||
297
backport-CVE-2021-44964.patch
Normal file
297
backport-CVE-2021-44964.patch
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
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
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
46
backport-CVE-2022-28805.patch
Normal file
46
backport-CVE-2022-28805.patch
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
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
|
||||||
|
|
||||||
62
backport-CVE-2022-33099.patch
Normal file
62
backport-CVE-2022-33099.patch
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
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
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
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
|
||||||
|
|
||||||
12
lua-5.3.0-idsize.patch
Normal file
12
lua-5.3.0-idsize.patch
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
BIN
lua-5.4.3-tests.tar.gz
Normal file
BIN
lua-5.4.3-tests.tar.gz
Normal file
Binary file not shown.
BIN
lua-5.4.3.tar.gz
Normal file
BIN
lua-5.4.3.tar.gz
Normal file
Binary file not shown.
@ -1,14 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
Binary file not shown.
BIN
lua-5.4.6.tar.gz
BIN
lua-5.4.6.tar.gz
Binary file not shown.
43
lua.spec
43
lua.spec
@ -1,12 +1,12 @@
|
|||||||
%global major_version 5.4
|
%global major_version 5.4
|
||||||
# test version is still 5.4.6
|
# test version is still 5.4.3
|
||||||
%global test_version 5.4.6
|
%global test_version 5.4.3
|
||||||
# Place rpm-macros into proper location.
|
# Place rpm-macros into proper location.
|
||||||
%global macrosdir %(d=%{_rpmconfigdir}/macros.d; [ -d $d ] || d=%{_sysconfdir}/rpm; echo $d)
|
%global macrosdir %(d=%{_rpmconfigdir}/macros.d; [ -d $d ] || d=%{_sysconfdir}/rpm; echo $d)
|
||||||
|
|
||||||
Name: lua
|
Name: lua
|
||||||
Version: 5.4.6
|
Version: 5.4.3
|
||||||
Release: 1
|
Release: 11
|
||||||
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/
|
||||||
@ -20,9 +20,24 @@ Source3: mit.txt
|
|||||||
# rpm-macro
|
# rpm-macro
|
||||||
Source1000: macros.lua
|
Source1000: macros.lua
|
||||||
Patch0: lua-5.4.0-beta-autotoolize.patch
|
Patch0: lua-5.4.0-beta-autotoolize.patch
|
||||||
Patch1: lua-5.4.6-idsize.patch
|
Patch1: lua-5.3.0-idsize.patch
|
||||||
Patch2: lua-5.2.2-configure-linux.patch
|
Patch2: lua-5.2.2-configure-linux.patch
|
||||||
Patch3: lua-5.3.0-configure-compat-module.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
|
BuildRequires: automake autoconf libtool readline-devel ncurses-devel
|
||||||
|
|
||||||
@ -55,6 +70,21 @@ mv src/luaconf.h src/luaconf.h.template.in
|
|||||||
%patch1 -p1 -z .idsize
|
%patch1 -p1 -z .idsize
|
||||||
%patch2 -p1 -z .configure-linux
|
%patch2 -p1 -z .configure-linux
|
||||||
%patch3 -p1 -z .configure-compat-all
|
%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
|
# 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
|
||||||
@ -129,9 +159,6 @@ LD_LIBRARY_PATH=$RPM_BUILD_ROOT/%{_libdir} $RPM_BUILD_ROOT/%{_bindir}/lua -e"_U=
|
|||||||
%{_mandir}/man1/lua*.1*
|
%{_mandir}/man1/lua*.1*
|
||||||
|
|
||||||
%changelog
|
%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
|
* 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
|
- fix CVE-2021-45985 and other commits because CVE change heavily rely on these commits
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user