fix CVE-2021-45985

(cherry picked from commit 89c61e7fa4b57456285e2cde7143c2cdf053d79e)
This commit is contained in:
Chen Ziyang 2023-04-18 21:48:32 +08:00 committed by openeuler-sync-bot
parent 6d88b9c460
commit b07366fdc6
10 changed files with 1257 additions and 1 deletions

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@ -6,7 +6,7 @@
Name: lua
Version: 5.4.3
Release: 10
Release: 11
Summary: A powerful, efficient, lightweight, embeddable scripting language
License: MIT
URL: http://www.lua.org/
@ -29,6 +29,15 @@ 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
@ -67,6 +76,15 @@ mv src/luaconf.h src/luaconf.h.template.in
%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
@ -141,6 +159,9 @@ LD_LIBRARY_PATH=$RPM_BUILD_ROOT/%{_libdir} $RPM_BUILD_ROOT/%{_bindir}/lua -e"_U=
%{_mandir}/man1/lua*.1*
%changelog
* Tue Apr 18 2023 chenziyang <chenziyang4@huawei.com> - 5.4.3-11
- fix CVE-2021-45985 and other commits because CVE change heavily rely on these commits
* Mon Dec 26 2022 liyanan <liyanan32@h-partners.com> - 5.4.3-10
- add support for LoongArch
@ -185,3 +206,4 @@ LD_LIBRARY_PATH=$RPM_BUILD_ROOT/%{_libdir} $RPM_BUILD_ROOT/%{_bindir}/lua -e"_U=
* Tue Sep 10 2019 openEuler Buildteam <buildteam@openeuler.org> - 5.3.5-3
- Package init