Skip to content

Commit 4365a45

Browse files
committed
Checks for read-only globals
1 parent be81209 commit 4365a45

4 files changed

Lines changed: 33 additions & 9 deletions

File tree

lcode.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1315,8 +1315,8 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
13151315
luaK_exp2anyreg(fs, t); /* put it in a register */
13161316
if (t->k == VUPVAL) {
13171317
lu_byte temp = cast_byte(t->u.info); /* upvalue index */
1318-
lua_assert(isKstr(fs, k));
13191318
t->u.ind.t = temp; /* (can't do a direct assignment; values overlap) */
1319+
lua_assert(isKstr(fs, k));
13201320
t->u.ind.idx = cast(short, k->u.info); /* literal short string */
13211321
t->k = VINDEXUP;
13221322
}
@@ -1336,6 +1336,7 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
13361336
t->k = VINDEXED;
13371337
}
13381338
}
1339+
t->u.ind.vidx = -1; /* by default, not a declared global */
13391340
}
13401341

13411342

lparser.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ static int new_varkind (LexState *ls, TString *name, lu_byte kind) {
200200
luaY_checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal,
201201
MAXVARS, "local variables");
202202
luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1,
203-
dyd->actvar.size, Vardesc, SHRT_MAX, "local variables");
203+
dyd->actvar.size, Vardesc, SHRT_MAX, "variable declarationss");
204204
var = &dyd->actvar.arr[dyd->actvar.n++];
205205
var->vd.kind = kind; /* default */
206206
var->vd.name = name;
@@ -276,7 +276,7 @@ static LocVar *localdebuginfo (FuncState *fs, int vidx) {
276276
static void init_var (FuncState *fs, expdesc *e, int vidx) {
277277
e->f = e->t = NO_JUMP;
278278
e->k = VLOCAL;
279-
e->u.var.vidx = cast(unsigned short, vidx);
279+
e->u.var.vidx = cast(short, vidx);
280280
e->u.var.ridx = getlocalvardesc(fs, vidx)->vd.ridx;
281281
}
282282

@@ -304,8 +304,16 @@ static void check_readonly (LexState *ls, expdesc *e) {
304304
varname = up->name;
305305
break;
306306
}
307+
case VINDEXUP: case VINDEXSTR: case VINDEXED: {
308+
int vidx = e->u.ind.vidx;
309+
/* is it a read-only declared global? */
310+
if (vidx != -1 && ls->dyd->actvar.arr[vidx].vd.kind == GDKCONST)
311+
varname = ls->dyd->actvar.arr[vidx].vd.name;
312+
break;
313+
}
307314
default:
308-
return; /* other cases cannot be read-only */
315+
lua_assert(e->k == VINDEXI); /* this one doesn't need any check */
316+
return; /* integer index cannot be read-only */
309317
}
310318
if (varname)
311319
luaK_semerror(ls, "attempt to assign to const variable '%s'",
@@ -391,7 +399,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) {
391399

392400

393401
/*
394-
** Look for an active local variable with the name 'n' in the
402+
** Look for an active variable with the name 'n' in the
395403
** function 'fs'. If found, initialize 'var' with it and return
396404
** its expression kind; otherwise return -1.
397405
*/
@@ -403,7 +411,7 @@ static int searchvar (FuncState *fs, TString *n, expdesc *var) {
403411
if (vd->vd.kind == RDKCTC) /* compile-time constant? */
404412
init_exp(var, VCONST, fs->firstlocal + i);
405413
else if (vd->vd.kind == GDKREG || vd->vd.kind == GDKCONST)
406-
init_exp(var, VGLOBAL, i);
414+
init_exp(var, VGLOBAL, fs->firstlocal + i);
407415
else /* local variable */
408416
init_var(fs, var, i);
409417
return cast_int(var->k);
@@ -475,8 +483,11 @@ static void singlevar (LexState *ls, expdesc *var) {
475483
singlevaraux(fs, varname, var, 1);
476484
if (var->k == VGLOBAL) { /* global name? */
477485
expdesc key;
486+
int info = var->u.info;
487+
lua_assert(info == -1 ||
488+
eqstr(ls->dyd->actvar.arr[info].vd.name, varname));
478489
/* global by default in the scope of a global declaration? */
479-
if (var->u.info == -1 && fs->bl->globdec)
490+
if (info == -1 && fs->bl->globdec)
480491
luaK_semerror(ls, "variable '%s' not declared", getstr(varname));
481492
singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
482493
if (var->k == VGLOBAL)
@@ -485,6 +496,7 @@ static void singlevar (LexState *ls, expdesc *var) {
485496
luaK_exp2anyregup(fs, var); /* but could be a constant */
486497
codestring(&key, varname); /* key is variable name */
487498
luaK_indexed(fs, var, &key); /* env[varname] */
499+
var->u.ind.vidx = cast(short, info); /* mark it as a declared global */
488500
}
489501
}
490502

lparser.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,12 @@ typedef struct expdesc {
7777
int info; /* for generic use */
7878
struct { /* for indexed variables */
7979
short idx; /* index (R or "long" K) */
80+
short vidx; /* index in 'actvar.arr' or -1 if not a declared global */
8081
lu_byte t; /* table (register or upvalue) */
8182
} ind;
8283
struct { /* for local variables */
8384
lu_byte ridx; /* register holding the variable */
84-
unsigned short vidx; /* compiler index (in 'actvar.arr') */
85+
short vidx; /* index in 'actvar.arr' */
8586
} var;
8687
} u;
8788
int t; /* patch list of 'exit when true' */
@@ -101,7 +102,7 @@ typedef struct expdesc {
101102
#define varinreg(v) ((v)->vd.kind <= RDKTOCLOSE)
102103

103104

104-
/* description of an active local variable */
105+
/* description of an active variable */
105106
typedef union Vardesc {
106107
struct {
107108
TValuefields; /* constant value (if it is a compile-time constant) */

testes/locals.lua

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ A = nil
178178

179179

180180
do -- constants
181+
global assert<const>, load, string, X
182+
X = 1 -- not a constant
181183
local a<const>, b, c<const> = 10, 20, 30
182184
b = a + c + b -- 'b' is not constant
183185
assert(a == 10 and b == 60 and c == 30)
@@ -191,6 +193,9 @@ do -- constants
191193
checkro("z", "local x <const>, y, z <const> = 10, 20, 30; y = 10; z = 11")
192194
checkro("foo", "local foo <const> = 10; function foo() end")
193195
checkro("foo", "local foo <const> = {}; function foo() end")
196+
checkro("foo", "global foo <const>; function foo() end")
197+
checkro("XX", "global XX <const>; XX = 10")
198+
checkro("XX", "local _ENV; global XX <const>; XX = 10")
194199

195200
checkro("z", [[
196201
local a, z <const>, b = 10;
@@ -201,6 +206,11 @@ do -- constants
201206
local a, var1 <const> = 10;
202207
function foo() a = 20; z = function () var1 = 12; end end
203208
]])
209+
210+
checkro("var1", [[
211+
global a, var1 <const>, z;
212+
local function foo() a = 20; z = function () var1 = 12; end end
213+
]])
204214
end
205215

206216

0 commit comments

Comments
 (0)