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 | |
| 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.
| -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? */ |
