diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-05-06 15:54:05 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-05-06 15:54:05 -0300 |
commit | 4365a45d681b4e71e3c39148489bb8eae538ccf7 (patch) | |
tree | ea22f0836f252edd7bc7279772158f2b7e549b1e /lparser.c | |
parent | be8120906304a8658fab998587b969e0e42f5650 (diff) | |
download | lua-4365a45d681b4e71e3c39148489bb8eae538ccf7.tar.gz lua-4365a45d681b4e71e3c39148489bb8eae538ccf7.tar.bz2 lua-4365a45d681b4e71e3c39148489bb8eae538ccf7.zip |
Checks for read-only globals
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 24 |
1 files changed, 18 insertions, 6 deletions
@@ -200,7 +200,7 @@ static int new_varkind (LexState *ls, TString *name, lu_byte kind) { | |||
200 | luaY_checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, | 200 | luaY_checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, |
201 | MAXVARS, "local variables"); | 201 | MAXVARS, "local variables"); |
202 | luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, | 202 | 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"); |
204 | var = &dyd->actvar.arr[dyd->actvar.n++]; | 204 | var = &dyd->actvar.arr[dyd->actvar.n++]; |
205 | var->vd.kind = kind; /* default */ | 205 | var->vd.kind = kind; /* default */ |
206 | var->vd.name = name; | 206 | var->vd.name = name; |
@@ -276,7 +276,7 @@ static LocVar *localdebuginfo (FuncState *fs, int vidx) { | |||
276 | static void init_var (FuncState *fs, expdesc *e, int vidx) { | 276 | static void init_var (FuncState *fs, expdesc *e, int vidx) { |
277 | e->f = e->t = NO_JUMP; | 277 | e->f = e->t = NO_JUMP; |
278 | e->k = VLOCAL; | 278 | e->k = VLOCAL; |
279 | e->u.var.vidx = cast(unsigned short, vidx); | 279 | e->u.var.vidx = cast(short, vidx); |
280 | e->u.var.ridx = getlocalvardesc(fs, vidx)->vd.ridx; | 280 | e->u.var.ridx = getlocalvardesc(fs, vidx)->vd.ridx; |
281 | } | 281 | } |
282 | 282 | ||
@@ -304,8 +304,16 @@ static void check_readonly (LexState *ls, expdesc *e) { | |||
304 | varname = up->name; | 304 | varname = up->name; |
305 | break; | 305 | break; |
306 | } | 306 | } |
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 | } | ||
307 | default: | 314 | 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 */ | ||
309 | } | 317 | } |
310 | if (varname) | 318 | if (varname) |
311 | luaK_semerror(ls, "attempt to assign to const variable '%s'", | 319 | luaK_semerror(ls, "attempt to assign to const variable '%s'", |
@@ -391,7 +399,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) { | |||
391 | 399 | ||
392 | 400 | ||
393 | /* | 401 | /* |
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 |
395 | ** function 'fs'. If found, initialize 'var' with it and return | 403 | ** function 'fs'. If found, initialize 'var' with it and return |
396 | ** its expression kind; otherwise return -1. | 404 | ** its expression kind; otherwise return -1. |
397 | */ | 405 | */ |
@@ -403,7 +411,7 @@ static int searchvar (FuncState *fs, TString *n, expdesc *var) { | |||
403 | if (vd->vd.kind == RDKCTC) /* compile-time constant? */ | 411 | if (vd->vd.kind == RDKCTC) /* compile-time constant? */ |
404 | init_exp(var, VCONST, fs->firstlocal + i); | 412 | init_exp(var, VCONST, fs->firstlocal + i); |
405 | else if (vd->vd.kind == GDKREG || vd->vd.kind == GDKCONST) | 413 | else if (vd->vd.kind == GDKREG || vd->vd.kind == GDKCONST) |
406 | init_exp(var, VGLOBAL, i); | 414 | init_exp(var, VGLOBAL, fs->firstlocal + i); |
407 | else /* local variable */ | 415 | else /* local variable */ |
408 | init_var(fs, var, i); | 416 | init_var(fs, var, i); |
409 | return cast_int(var->k); | 417 | return cast_int(var->k); |
@@ -475,8 +483,11 @@ static void singlevar (LexState *ls, expdesc *var) { | |||
475 | singlevaraux(fs, varname, var, 1); | 483 | singlevaraux(fs, varname, var, 1); |
476 | if (var->k == VGLOBAL) { /* global name? */ | 484 | if (var->k == VGLOBAL) { /* global name? */ |
477 | expdesc key; | 485 | expdesc key; |
486 | int info = var->u.info; | ||
487 | lua_assert(info == -1 || | ||
488 | eqstr(ls->dyd->actvar.arr[info].vd.name, varname)); | ||
478 | /* global by default in the scope of a global declaration? */ | 489 | /* 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) |
480 | luaK_semerror(ls, "variable '%s' not declared", getstr(varname)); | 491 | luaK_semerror(ls, "variable '%s' not declared", getstr(varname)); |
481 | singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ | 492 | singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ |
482 | if (var->k == VGLOBAL) | 493 | if (var->k == VGLOBAL) |
@@ -485,6 +496,7 @@ static void singlevar (LexState *ls, expdesc *var) { | |||
485 | luaK_exp2anyregup(fs, var); /* but could be a constant */ | 496 | luaK_exp2anyregup(fs, var); /* but could be a constant */ |
486 | codestring(&key, varname); /* key is variable name */ | 497 | codestring(&key, varname); /* key is variable name */ |
487 | luaK_indexed(fs, var, &key); /* env[varname] */ | 498 | luaK_indexed(fs, var, &key); /* env[varname] */ |
499 | var->u.ind.vidx = cast(short, info); /* mark it as a declared global */ | ||
488 | } | 500 | } |
489 | } | 501 | } |
490 | 502 | ||