diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-07-26 13:27:43 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-07-26 13:27:43 -0300 |
commit | e70f275f32a5339a86be6f8b9d08c20cb874b205 (patch) | |
tree | 4ef2a00ab5ac8dffa8a6ee5e8af33a0c0380f1b0 /lparser.c | |
parent | 9a37dc0ce64c51fd57f5e658a5af8f3671a26b0a (diff) | |
download | lua-e70f275f32a5339a86be6f8b9d08c20cb874b205.tar.gz lua-e70f275f32a5339a86be6f8b9d08c20cb874b205.tar.bz2 lua-e70f275f32a5339a86be6f8b9d08c20cb874b205.zip |
Bug: 'Vardesc' array can be reallocated in 'localstat'
A reference to a 'Vardesc*' (as done by 'localstat') can be
invalidated by the creation of any new variable.
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 27 |
1 files changed, 15 insertions, 12 deletions
@@ -187,9 +187,10 @@ static int registerlocalvar (LexState *ls, FuncState *fs, TString *varname) { | |||
187 | 187 | ||
188 | 188 | ||
189 | /* | 189 | /* |
190 | ** Create a new local variable with the given 'name'. | 190 | ** Create a new local variable with the given 'name'. Return its index |
191 | ** in the function. | ||
191 | */ | 192 | */ |
192 | static Vardesc *new_localvar (LexState *ls, TString *name) { | 193 | static int new_localvar (LexState *ls, TString *name, int kind) { |
193 | lua_State *L = ls->L; | 194 | lua_State *L = ls->L; |
194 | FuncState *fs = ls->fs; | 195 | FuncState *fs = ls->fs; |
195 | Dyndata *dyd = ls->dyd; | 196 | Dyndata *dyd = ls->dyd; |
@@ -199,13 +200,14 @@ static Vardesc *new_localvar (LexState *ls, TString *name) { | |||
199 | luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, | 200 | luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, |
200 | dyd->actvar.size, Vardesc, USHRT_MAX, "local variables"); | 201 | dyd->actvar.size, Vardesc, USHRT_MAX, "local variables"); |
201 | var = &dyd->actvar.arr[dyd->actvar.n++]; | 202 | var = &dyd->actvar.arr[dyd->actvar.n++]; |
202 | var->vd.kind = VDKREG; /* default is a regular variable */ | 203 | var->vd.kind = kind; |
203 | var->vd.name = name; | 204 | var->vd.name = name; |
204 | return var; | 205 | return dyd->actvar.n - 1 - fs->firstlocal; |
205 | } | 206 | } |
206 | 207 | ||
207 | #define new_localvarliteral(ls,v) \ | 208 | #define new_localvarliteral(ls,v) \ |
208 | new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char)) - 1)); | 209 | new_localvar(ls, \ |
210 | luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char)) - 1), VDKREG); | ||
209 | 211 | ||
210 | 212 | ||
211 | 213 | ||
@@ -945,7 +947,7 @@ static void parlist (LexState *ls) { | |||
945 | do { | 947 | do { |
946 | switch (ls->t.token) { | 948 | switch (ls->t.token) { |
947 | case TK_NAME: { /* param -> NAME */ | 949 | case TK_NAME: { /* param -> NAME */ |
948 | new_localvar(ls, str_checkname(ls)); | 950 | new_localvar(ls, str_checkname(ls), VDKREG); |
949 | nparams++; | 951 | nparams++; |
950 | break; | 952 | break; |
951 | } | 953 | } |
@@ -1551,7 +1553,7 @@ static void fornum (LexState *ls, TString *varname, int line) { | |||
1551 | new_localvarliteral(ls, "(for state)"); | 1553 | new_localvarliteral(ls, "(for state)"); |
1552 | new_localvarliteral(ls, "(for state)"); | 1554 | new_localvarliteral(ls, "(for state)"); |
1553 | new_localvarliteral(ls, "(for state)"); | 1555 | new_localvarliteral(ls, "(for state)"); |
1554 | new_localvar(ls, varname); | 1556 | new_localvar(ls, varname, VDKREG); |
1555 | checknext(ls, '='); | 1557 | checknext(ls, '='); |
1556 | exp1(ls); /* initial value */ | 1558 | exp1(ls); /* initial value */ |
1557 | checknext(ls, ','); | 1559 | checknext(ls, ','); |
@@ -1580,9 +1582,9 @@ static void forlist (LexState *ls, TString *indexname) { | |||
1580 | new_localvarliteral(ls, "(for state)"); | 1582 | new_localvarliteral(ls, "(for state)"); |
1581 | new_localvarliteral(ls, "(for state)"); | 1583 | new_localvarliteral(ls, "(for state)"); |
1582 | /* create declared variables */ | 1584 | /* create declared variables */ |
1583 | new_localvar(ls, indexname); | 1585 | new_localvar(ls, indexname, VDKREG); |
1584 | while (testnext(ls, ',')) { | 1586 | while (testnext(ls, ',')) { |
1585 | new_localvar(ls, str_checkname(ls)); | 1587 | new_localvar(ls, str_checkname(ls), VDKREG); |
1586 | nvars++; | 1588 | nvars++; |
1587 | } | 1589 | } |
1588 | checknext(ls, TK_IN); | 1590 | checknext(ls, TK_IN); |
@@ -1706,7 +1708,7 @@ static void localfunc (LexState *ls) { | |||
1706 | expdesc b; | 1708 | expdesc b; |
1707 | FuncState *fs = ls->fs; | 1709 | FuncState *fs = ls->fs; |
1708 | int fvar = fs->nactvar; /* function's variable index */ | 1710 | int fvar = fs->nactvar; /* function's variable index */ |
1709 | new_localvar(ls, str_checkname(ls)); /* new local variable */ | 1711 | new_localvar(ls, str_checkname(ls), VDKREG); /* new local variable */ |
1710 | adjustlocalvars(ls, 1); /* enter its scope */ | 1712 | adjustlocalvars(ls, 1); /* enter its scope */ |
1711 | body(ls, &b, 0, ls->linenumber); /* function created in next register */ | 1713 | body(ls, &b, 0, ls->linenumber); /* function created in next register */ |
1712 | /* debug information will only see the variable after this point! */ | 1714 | /* debug information will only see the variable after this point! */ |
@@ -1746,13 +1748,13 @@ static void localstat (LexState *ls) { | |||
1746 | FuncState *fs = ls->fs; | 1748 | FuncState *fs = ls->fs; |
1747 | int toclose = -1; /* index of to-be-closed variable (if any) */ | 1749 | int toclose = -1; /* index of to-be-closed variable (if any) */ |
1748 | Vardesc *var; /* last variable */ | 1750 | Vardesc *var; /* last variable */ |
1751 | int ivar; /* index of last variable */ | ||
1749 | int nvars = 0; | 1752 | int nvars = 0; |
1750 | int nexps; | 1753 | int nexps; |
1751 | expdesc e; | 1754 | expdesc e; |
1752 | do { | 1755 | do { |
1753 | int kind = getlocalattribute(ls); | 1756 | int kind = getlocalattribute(ls); |
1754 | var = new_localvar(ls, str_checkname(ls)); | 1757 | ivar = new_localvar(ls, str_checkname(ls), kind); |
1755 | var->vd.kind = kind; | ||
1756 | if (kind == RDKTOCLOSE) { /* to-be-closed? */ | 1758 | if (kind == RDKTOCLOSE) { /* to-be-closed? */ |
1757 | if (toclose != -1) /* one already present? */ | 1759 | if (toclose != -1) /* one already present? */ |
1758 | luaK_semerror(ls, "multiple to-be-closed variables in local list"); | 1760 | luaK_semerror(ls, "multiple to-be-closed variables in local list"); |
@@ -1766,6 +1768,7 @@ static void localstat (LexState *ls) { | |||
1766 | e.k = VVOID; | 1768 | e.k = VVOID; |
1767 | nexps = 0; | 1769 | nexps = 0; |
1768 | } | 1770 | } |
1771 | var = getlocalvardesc(fs, ivar); /* get last variable */ | ||
1769 | if (nvars == nexps && /* no adjustments? */ | 1772 | if (nvars == nexps && /* no adjustments? */ |
1770 | var->vd.kind == RDKCONST && /* last variable is const? */ | 1773 | var->vd.kind == RDKCONST && /* last variable is const? */ |
1771 | luaK_exp2const(fs, &e, &var->k)) { /* compile-time constant? */ | 1774 | luaK_exp2const(fs, &e, &var->k)) { /* compile-time constant? */ |