Added limit to number of elements in a constructor

The reasoning in commit 519c57d5 is wrong: A sequence of nils generates
several fields with just one OP_LOADNIL.
This commit is contained in:
Roberto I
2025-08-27 10:30:54 -03:00
parent 03a3473687
commit f87416f1a3
2 changed files with 19 additions and 4 deletions

View File

@@ -905,6 +905,19 @@ typedef struct ConsControl {
} ConsControl;
/*
** Maximum number of elements in a constructor, to control the following:
** * counter overflows;
** * overflows in 'extra' for OP_NEWTABLE and OP_SETLIST;
** * overflows when adding multiple returns in OP_SETLIST.
*/
#define MAX_CNST (INT_MAX/2)
#if MAX_CNST/(MAXARG_vC + 1) > MAXARG_Ax
#undef MAX_CNST
#define MAX_CNST (MAXARG_Ax * (MAXARG_vC + 1))
#endif
static void recfield (LexState *ls, ConsControl *cc) {
/* recfield -> (NAME | '['exp']') = exp */
FuncState *fs = ls->fs;
@@ -925,7 +938,7 @@ static void recfield (LexState *ls, ConsControl *cc) {
static void closelistfield (FuncState *fs, ConsControl *cc) {
if (cc->v.k == VVOID) return; /* there is no list item */
lua_assert(cc->tostore > 0);
luaK_exp2nextreg(fs, &cc->v);
cc->v.k = VVOID;
if (cc->tostore >= cc->maxtostore) {
@@ -1013,10 +1026,12 @@ static void constructor (LexState *ls, expdesc *t) {
checknext(ls, '{' /*}*/);
cc.maxtostore = maxtostore(fs);
do {
lua_assert(cc.v.k == VVOID || cc.tostore > 0);
if (ls->t.token == /*{*/ '}') break;
closelistfield(fs, &cc);
if (cc.v.k != VVOID) /* is there a previous list item? */
closelistfield(fs, &cc); /* close it */
field(ls, &cc);
luaY_checklimit(fs, cc.tostore + cc.na + cc.nh, MAX_CNST,
"items in a constructor");
} while (testnext(ls, ',') || testnext(ls, ';'));
check_match(ls, /*{*/ '}', '{' /*}*/, line);
lastlistfield(fs, &cc);