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:
21
lparser.c
21
lparser.c
@@ -905,6 +905,19 @@ typedef struct ConsControl {
|
|||||||
} 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) {
|
static void recfield (LexState *ls, ConsControl *cc) {
|
||||||
/* recfield -> (NAME | '['exp']') = exp */
|
/* recfield -> (NAME | '['exp']') = exp */
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
@@ -925,7 +938,7 @@ static void recfield (LexState *ls, ConsControl *cc) {
|
|||||||
|
|
||||||
|
|
||||||
static void closelistfield (FuncState *fs, 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);
|
luaK_exp2nextreg(fs, &cc->v);
|
||||||
cc->v.k = VVOID;
|
cc->v.k = VVOID;
|
||||||
if (cc->tostore >= cc->maxtostore) {
|
if (cc->tostore >= cc->maxtostore) {
|
||||||
@@ -1013,10 +1026,12 @@ static void constructor (LexState *ls, expdesc *t) {
|
|||||||
checknext(ls, '{' /*}*/);
|
checknext(ls, '{' /*}*/);
|
||||||
cc.maxtostore = maxtostore(fs);
|
cc.maxtostore = maxtostore(fs);
|
||||||
do {
|
do {
|
||||||
lua_assert(cc.v.k == VVOID || cc.tostore > 0);
|
|
||||||
if (ls->t.token == /*{*/ '}') break;
|
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);
|
field(ls, &cc);
|
||||||
|
luaY_checklimit(fs, cc.tostore + cc.na + cc.nh, MAX_CNST,
|
||||||
|
"items in a constructor");
|
||||||
} while (testnext(ls, ',') || testnext(ls, ';'));
|
} while (testnext(ls, ',') || testnext(ls, ';'));
|
||||||
check_match(ls, /*{*/ '}', '{' /*}*/, line);
|
check_match(ls, /*{*/ '}', '{' /*}*/, line);
|
||||||
lastlistfield(fs, &cc);
|
lastlistfield(fs, &cc);
|
||||||
|
|||||||
2
lvm.c
2
lvm.c
@@ -1888,7 +1888,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
vmcase(OP_SETLIST) {
|
vmcase(OP_SETLIST) {
|
||||||
StkId ra = RA(i);
|
StkId ra = RA(i);
|
||||||
unsigned n = cast_uint(GETARG_vB(i));
|
unsigned n = cast_uint(GETARG_vB(i));
|
||||||
unsigned int last = cast_uint(GETARG_vC(i));
|
unsigned last = cast_uint(GETARG_vC(i));
|
||||||
Table *h = hvalue(s2v(ra));
|
Table *h = hvalue(s2v(ra));
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
n = cast_uint(L->top.p - ra) - 1; /* get up to the top */
|
n = cast_uint(L->top.p - ra) - 1; /* get up to the top */
|
||||||
|
|||||||
Reference in New Issue
Block a user