diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-11-22 14:35:20 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-11-22 14:35:20 -0200 |
commit | 04b143ddf931f5312209ddfc1d8d14ede6997afd (patch) | |
tree | 3a06772a43d0b966e62e0e96a1ff729f8db4f921 | |
parent | 007f229568ec47a2b6659ef3049b9ed03ccac72d (diff) | |
download | lua-04b143ddf931f5312209ddfc1d8d14ede6997afd.tar.gz lua-04b143ddf931f5312209ddfc1d8d14ede6997afd.tar.bz2 lua-04b143ddf931f5312209ddfc1d8d14ede6997afd.zip |
avoid C stack overflow during parsing
-rw-r--r-- | llex.h | 3 | ||||
-rw-r--r-- | llimits.h | 8 | ||||
-rw-r--r-- | lparser.c | 15 |
3 files changed, 22 insertions, 4 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: llex.h,v 1.44 2002/09/03 11:57:38 roberto Exp roberto $ | 2 | ** $Id: llex.h,v 1.45 2002/10/08 18:46:08 roberto Exp roberto $ |
3 | ** Lexical Analyzer | 3 | ** Lexical Analyzer |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -59,6 +59,7 @@ typedef struct LexState { | |||
59 | ZIO *z; /* input stream */ | 59 | ZIO *z; /* input stream */ |
60 | Mbuffer *buff; /* buffer for tokens */ | 60 | Mbuffer *buff; /* buffer for tokens */ |
61 | TString *source; /* current source name */ | 61 | TString *source; /* current source name */ |
62 | int nestlevel; /* level of nested non-terminals */ | ||
62 | } LexState; | 63 | } LexState; |
63 | 64 | ||
64 | 65 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: llimits.h,v 1.46 2002/10/08 18:46:08 roberto Exp roberto $ | 2 | ** $Id: llimits.h,v 1.47 2002/10/22 17:18:28 roberto Exp roberto $ |
3 | ** Limits, basic types, and some other `installation-dependent' definitions | 3 | ** Limits, basic types, and some other `installation-dependent' definitions |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -165,4 +165,10 @@ typedef unsigned long Instruction; | |||
165 | #endif | 165 | #endif |
166 | 166 | ||
167 | 167 | ||
168 | /* maximum number of syntactical nested non-terminals */ | ||
169 | #ifndef LUA_MAXPARSERLEVEL | ||
170 | #define LUA_MAXPARSERLEVEL 200 | ||
171 | #endif | ||
172 | |||
173 | |||
168 | #endif | 174 | #endif |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.196 2002/10/16 20:40:58 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.197 2002/11/22 13:59:04 roberto Exp roberto $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -26,6 +26,10 @@ | |||
26 | #define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) | 26 | #define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) |
27 | 27 | ||
28 | 28 | ||
29 | #define enterlevel(ls) if (++(ls)->nestlevel > LUA_MAXPARSERLEVEL) \ | ||
30 | luaX_syntaxerror(ls, "too many syntax levels"); | ||
31 | #define leavelevel(ls) ((ls)->nestlevel--) | ||
32 | |||
29 | 33 | ||
30 | /* | 34 | /* |
31 | ** nodes for block list (list of active blocks) | 35 | ** nodes for block list (list of active blocks) |
@@ -356,6 +360,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) { | |||
356 | struct LexState lexstate; | 360 | struct LexState lexstate; |
357 | struct FuncState funcstate; | 361 | struct FuncState funcstate; |
358 | lexstate.buff = buff; | 362 | lexstate.buff = buff; |
363 | lexstate.nestlevel = 0; | ||
359 | luaX_setinput(L, &lexstate, z, luaS_new(L, zname(z))); | 364 | luaX_setinput(L, &lexstate, z, luaS_new(L, zname(z))); |
360 | open_func(&lexstate, &funcstate); | 365 | open_func(&lexstate, &funcstate); |
361 | next(&lexstate); /* read first token */ | 366 | next(&lexstate); /* read first token */ |
@@ -364,6 +369,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) { | |||
364 | close_func(&lexstate); | 369 | close_func(&lexstate); |
365 | lua_assert(funcstate.prev == NULL); | 370 | lua_assert(funcstate.prev == NULL); |
366 | lua_assert(funcstate.f->nupvalues == 0); | 371 | lua_assert(funcstate.f->nupvalues == 0); |
372 | lua_assert(lexstate.nestlevel == 0); | ||
367 | return funcstate.f; | 373 | return funcstate.f; |
368 | } | 374 | } |
369 | 375 | ||
@@ -749,7 +755,9 @@ static const struct { | |||
749 | */ | 755 | */ |
750 | static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { | 756 | static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { |
751 | BinOpr op; | 757 | BinOpr op; |
752 | UnOpr uop = getunopr(ls->t.token); | 758 | UnOpr uop; |
759 | enterlevel(ls); | ||
760 | uop = getunopr(ls->t.token); | ||
753 | if (uop != OPR_NOUNOPR) { | 761 | if (uop != OPR_NOUNOPR) { |
754 | next(ls); | 762 | next(ls); |
755 | subexpr(ls, v, UNARY_PRIORITY); | 763 | subexpr(ls, v, UNARY_PRIORITY); |
@@ -768,6 +776,7 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { | |||
768 | luaK_posfix(ls->fs, op, v, &v2); | 776 | luaK_posfix(ls->fs, op, v, &v2); |
769 | op = nextop; | 777 | op = nextop; |
770 | } | 778 | } |
779 | leavelevel(ls); | ||
771 | return op; /* return first untreated operator */ | 780 | return op; /* return first untreated operator */ |
772 | } | 781 | } |
773 | 782 | ||
@@ -1299,11 +1308,13 @@ static void body (LexState *ls, expdesc *e, int needself, int line) { | |||
1299 | static void chunk (LexState *ls) { | 1308 | static void chunk (LexState *ls) { |
1300 | /* chunk -> { stat [`;'] } */ | 1309 | /* chunk -> { stat [`;'] } */ |
1301 | int islast = 0; | 1310 | int islast = 0; |
1311 | enterlevel(ls); | ||
1302 | while (!islast && !block_follow(ls->t.token)) { | 1312 | while (!islast && !block_follow(ls->t.token)) { |
1303 | islast = statement(ls); | 1313 | islast = statement(ls); |
1304 | testnext(ls, ';'); | 1314 | testnext(ls, ';'); |
1305 | lua_assert(ls->fs->freereg >= ls->fs->nactvar); | 1315 | lua_assert(ls->fs->freereg >= ls->fs->nactvar); |
1306 | ls->fs->freereg = ls->fs->nactvar; /* free registers */ | 1316 | ls->fs->freereg = ls->fs->nactvar; /* free registers */ |
1307 | } | 1317 | } |
1318 | leavelevel(ls); | ||
1308 | } | 1319 | } |
1309 | 1320 | ||