Initialization of too many locals break assertion

The check for limit of local variables is made after generating code to
initialize them. If there are too many local variables not initialized,
the coding of instruction OP_LOADNIL could overflow an argument.
This commit is contained in:
Roberto I
2025-10-10 13:22:19 -03:00
parent 25c54fe60e
commit 3347c9d32d
2 changed files with 13 additions and 7 deletions

View File

@@ -547,6 +547,7 @@ static void singlevar (LexState *ls, expdesc *var) {
static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
int needed = nvars - nexps; /* extra values needed */ int needed = nvars - nexps; /* extra values needed */
luaK_checkstack(fs, needed);
if (hasmultret(e->k)) { /* last expression has multiple returns? */ if (hasmultret(e->k)) { /* last expression has multiple returns? */
int extra = needed + 1; /* discount last expression itself */ int extra = needed + 1; /* discount last expression itself */
if (extra < 0) if (extra < 0)

View File

@@ -689,21 +689,26 @@ end
-- testing syntax limits -- testing syntax limits
local function testrep (init, rep, close, repc, finalresult) local function testrep (init, rep, close, repc, finalresult)
local s = init .. string.rep(rep, 100) .. close .. string.rep(repc, 100) local function gencode (n)
local res, msg = load(s) return init .. string.rep(rep, n) .. close .. string.rep(repc, n)
assert(res) -- 100 levels is OK end
local res, msg = load(gencode(100)) -- 100 levels is OK
assert(res)
if (finalresult) then if (finalresult) then
assert(res() == finalresult) assert(res() == finalresult)
end end
s = init .. string.rep(rep, 500) local res, msg = load(gencode(500)) -- 500 levels not ok
local res, msg = load(s) -- 500 levels not ok
assert(not res and (string.find(msg, "too many") or assert(not res and (string.find(msg, "too many") or
string.find(msg, "overflow"))) string.find(msg, "overflow")))
end end
testrep("local a", ",a", ";", "") -- local variables
testrep("local a", ",a", "= 1", ",1") -- local variables initialized
testrep("local a", ",a", "= f()", "") -- local variables initialized
testrep("local a; a", ",a", "= 1", ",1") -- multiple assignment testrep("local a; a", ",a", "= 1", ",1") -- multiple assignment
testrep("local a; a=", "{", "0", "}") testrep("local a; a=", "{", "0", "}") -- constructors
testrep("return ", "(", "2", ")", 2) testrep("return ", "(", "2", ")", 2) -- parentheses
-- nested calls (a(a(a(a(...)))))
testrep("local function a (x) return x end; return ", "a(", "2.2", ")", 2.2) testrep("local function a (x) return x end; return ", "a(", "2.2", ")", 2.2)
testrep("", "do ", "", " end") testrep("", "do ", "", " end")
testrep("", "while a do ", "", " end") testrep("", "while a do ", "", " end")