aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto I <roberto@inf.puc-rio.br>2025-08-27 10:30:54 -0300
committerRoberto I <roberto@inf.puc-rio.br>2025-08-27 10:30:54 -0300
commitf87416f1a3e47aa69ed8d27e7406ec6b7848da9a (patch)
tree223c07bf1f2c39ca692f74015b52b8670eb6ad52
parent03a3473687ef0df86fc6d31de7d46158a0436666 (diff)
downloadlua-f87416f1a3e47aa69ed8d27e7406ec6b7848da9a.tar.gz
lua-f87416f1a3e47aa69ed8d27e7406ec6b7848da9a.tar.bz2
lua-f87416f1a3e47aa69ed8d27e7406ec6b7848da9a.zip
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.
Diffstat (limited to '')
-rw-r--r--lparser.c21
-rw-r--r--lvm.c2
2 files changed, 19 insertions, 4 deletions
diff --git a/lparser.c b/lparser.c
index 73dad6d7..5abcd407 100644
--- a/lparser.c
+++ b/lparser.c
@@ -905,6 +905,19 @@ typedef struct ConsControl {
905} ConsControl; 905} ConsControl;
906 906
907 907
908/*
909** Maximum number of elements in a constructor, to control the following:
910** * counter overflows;
911** * overflows in 'extra' for OP_NEWTABLE and OP_SETLIST;
912** * overflows when adding multiple returns in OP_SETLIST.
913*/
914#define MAX_CNST (INT_MAX/2)
915#if MAX_CNST/(MAXARG_vC + 1) > MAXARG_Ax
916#undef MAX_CNST
917#define MAX_CNST (MAXARG_Ax * (MAXARG_vC + 1))
918#endif
919
920
908static void recfield (LexState *ls, ConsControl *cc) { 921static void recfield (LexState *ls, ConsControl *cc) {
909 /* recfield -> (NAME | '['exp']') = exp */ 922 /* recfield -> (NAME | '['exp']') = exp */
910 FuncState *fs = ls->fs; 923 FuncState *fs = ls->fs;
@@ -925,7 +938,7 @@ static void recfield (LexState *ls, ConsControl *cc) {
925 938
926 939
927static void closelistfield (FuncState *fs, ConsControl *cc) { 940static void closelistfield (FuncState *fs, ConsControl *cc) {
928 if (cc->v.k == VVOID) return; /* there is no list item */ 941 lua_assert(cc->tostore > 0);
929 luaK_exp2nextreg(fs, &cc->v); 942 luaK_exp2nextreg(fs, &cc->v);
930 cc->v.k = VVOID; 943 cc->v.k = VVOID;
931 if (cc->tostore >= cc->maxtostore) { 944 if (cc->tostore >= cc->maxtostore) {
@@ -1013,10 +1026,12 @@ static void constructor (LexState *ls, expdesc *t) {
1013 checknext(ls, '{' /*}*/); 1026 checknext(ls, '{' /*}*/);
1014 cc.maxtostore = maxtostore(fs); 1027 cc.maxtostore = maxtostore(fs);
1015 do { 1028 do {
1016 lua_assert(cc.v.k == VVOID || cc.tostore > 0);
1017 if (ls->t.token == /*{*/ '}') break; 1029 if (ls->t.token == /*{*/ '}') break;
1018 closelistfield(fs, &cc); 1030 if (cc.v.k != VVOID) /* is there a previous list item? */
1031 closelistfield(fs, &cc); /* close it */
1019 field(ls, &cc); 1032 field(ls, &cc);
1033 luaY_checklimit(fs, cc.tostore + cc.na + cc.nh, MAX_CNST,
1034 "items in a constructor");
1020 } while (testnext(ls, ',') || testnext(ls, ';')); 1035 } while (testnext(ls, ',') || testnext(ls, ';'));
1021 check_match(ls, /*{*/ '}', '{' /*}*/, line); 1036 check_match(ls, /*{*/ '}', '{' /*}*/, line);
1022 lastlistfield(fs, &cc); 1037 lastlistfield(fs, &cc);
diff --git a/lvm.c b/lvm.c
index a9de5cbc..d0a1c05d 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1888,7 +1888,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1888 vmcase(OP_SETLIST) { 1888 vmcase(OP_SETLIST) {
1889 StkId ra = RA(i); 1889 StkId ra = RA(i);
1890 unsigned n = cast_uint(GETARG_vB(i)); 1890 unsigned n = cast_uint(GETARG_vB(i));
1891 unsigned int last = cast_uint(GETARG_vC(i)); 1891 unsigned last = cast_uint(GETARG_vC(i));
1892 Table *h = hvalue(s2v(ra)); 1892 Table *h = hvalue(s2v(ra));
1893 if (n == 0) 1893 if (n == 0)
1894 n = cast_uint(L->top.p - ra) - 1; /* get up to the top */ 1894 n = cast_uint(L->top.p - ra) - 1; /* get up to the top */