lua

A copy of the Lua development repository
Log | Files | Refs | README

commit f9e35627ed26dff4114a1d01ff113d8b4cc91ab5
parent ceac82f78be8baeddfa8536472d8b08df2eb7d49
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date:   Wed, 26 Feb 2025 11:30:43 -0300

'lua_State.nci' must be an integer

Lua can easily overflow an unsigned short counting nested calls.
(The limit to this value is the maximum stack size, LUAI_MAXSTACK,
which is currently 1e6.)

Diffstat:
Mlstate.h | 2+-
Mltests.h | 7+++++--
Mtestes/coroutine.lua | 12++++++++++++
3 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/lstate.h b/lstate.h @@ -290,7 +290,6 @@ struct lua_State { CommonHeader; lu_byte allowhook; TStatus status; - unsigned short nci; /* number of items in 'ci' list */ StkIdRel top; /* first free slot in the stack */ struct global_State *l_G; CallInfo *ci; /* call info for current function */ @@ -306,6 +305,7 @@ struct lua_State { ptrdiff_t errfunc; /* current error handling function (stack index) */ l_uint32 nCcalls; /* number of nested non-yieldable or C calls */ int oldpc; /* last pc traced */ + int nci; /* number of items in 'ci' list */ int basehookcount; int hookcount; volatile l_signalT hookmask; diff --git a/ltests.h b/ltests.h @@ -152,9 +152,12 @@ LUA_API void *debug_realloc (void *ud, void *block, */ -/* make stack-overflow tests run faster */ +/* +** Reduce maximum stack size to make stack-overflow tests run faster. +** (But value is still large enough to overflow smaller integers.) +*/ #undef LUAI_MAXSTACK -#define LUAI_MAXSTACK 50000 +#define LUAI_MAXSTACK 68000 /* test mode uses more stack space */ diff --git a/testes/coroutine.lua b/testes/coroutine.lua @@ -127,6 +127,18 @@ assert(#a == 22 and a[#a] == 79) x, a = nil +do -- "bug" in 5.4.2 + local function foo () foo () end -- just create a stack overflow + local co = coroutine.create(foo) + -- running this coroutine would overflow the unsigned short 'nci', the + -- counter of CallInfo structures available to the thread. + -- (The issue only manifests in an 'assert'.) + local st, msg = coroutine.resume(co) + assert(string.find(msg, "stack overflow")) + assert(coroutine.status(co) == "dead") +end + + print("to-be-closed variables in coroutines") local function func2close (f)