From b2f7b3b79f3117885b265575f6c5dbf934757797 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 21 Dec 2022 12:04:59 -0300 Subject: Control variables in for loops are read only --- lparser.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'lparser.c') diff --git a/lparser.c b/lparser.c index 24668c24..79b2317b 100644 --- a/lparser.c +++ b/lparser.c @@ -187,10 +187,10 @@ static int registerlocalvar (LexState *ls, FuncState *fs, TString *varname) { /* -** Create a new local variable with the given 'name'. Return its index -** in the function. +** Create a new local variable with the given 'name' and given 'kind'. +** Return its index in the function. */ -static int new_localvar (LexState *ls, TString *name) { +static int new_localvarkind (LexState *ls, TString *name, int kind) { lua_State *L = ls->L; FuncState *fs = ls->fs; Dyndata *dyd = ls->dyd; @@ -200,11 +200,19 @@ static int new_localvar (LexState *ls, TString *name) { luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, dyd->actvar.size, Vardesc, USHRT_MAX, "local variables"); var = &dyd->actvar.arr[dyd->actvar.n++]; - var->vd.kind = VDKREG; /* default */ + var->vd.kind = kind; /* default */ var->vd.name = name; return dyd->actvar.n - 1 - fs->firstlocal; } + +/* +** Create a new local variable with the given 'name' and regular kind. +*/ +static int new_localvar (LexState *ls, TString *name) { + return new_localvarkind(ls, name, VDKREG); +} + #define new_localvarliteral(ls,v) \ new_localvar(ls, \ luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char)) - 1)); @@ -1573,7 +1581,7 @@ static void fornum (LexState *ls, TString *varname, int line) { new_localvarliteral(ls, "(for state)"); new_localvarliteral(ls, "(for state)"); new_localvarliteral(ls, "(for state)"); - new_localvar(ls, varname); + new_localvarkind(ls, varname, RDKCONST); /* control variable */ checknext(ls, '='); exp1(ls); /* initial value */ checknext(ls, ','); @@ -1601,8 +1609,8 @@ static void forlist (LexState *ls, TString *indexname) { new_localvarliteral(ls, "(for state)"); new_localvarliteral(ls, "(for state)"); new_localvarliteral(ls, "(for state)"); - /* create declared variables */ - new_localvar(ls, indexname); + new_localvarkind(ls, indexname, RDKCONST); /* control variable */ + /* other declared variables */ while (testnext(ls, ',')) { new_localvar(ls, str_checkname(ls)); nvars++; @@ -1728,14 +1736,14 @@ static void localstat (LexState *ls) { FuncState *fs = ls->fs; int toclose = -1; /* index of to-be-closed variable (if any) */ Vardesc *var; /* last variable */ - int vidx, kind; /* index and kind of last variable */ + int vidx; /* index of last variable */ int nvars = 0; int nexps; expdesc e; do { - vidx = new_localvar(ls, str_checkname(ls)); - kind = getlocalattribute(ls); - getlocalvardesc(fs, vidx)->vd.kind = kind; + TString *vname = str_checkname(ls); + int kind = getlocalattribute(ls); + vidx = new_localvarkind(ls, vname, kind); if (kind == RDKTOCLOSE) { /* to-be-closed? */ if (toclose != -1) /* one already present? */ luaK_semerror(ls, "multiple to-be-closed variables in local list"); -- cgit v1.2.3-55-g6feb