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-github-04b143ddf931f5312209ddfc1d8d14ede6997afd.tar.gz |
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 @@ /* -** $Id: llex.h,v 1.44 2002/09/03 11:57:38 roberto Exp roberto $ +** $Id: llex.h,v 1.45 2002/10/08 18:46:08 roberto Exp roberto $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -59,6 +59,7 @@ typedef struct LexState { ZIO *z; /* input stream */ Mbuffer *buff; /* buffer for tokens */ TString *source; /* current source name */ + int nestlevel; /* level of nested non-terminals */ } LexState; @@ -1,5 +1,5 @@ /* -** $Id: llimits.h,v 1.46 2002/10/08 18:46:08 roberto Exp roberto $ +** $Id: llimits.h,v 1.47 2002/10/22 17:18:28 roberto Exp roberto $ ** Limits, basic types, and some other `installation-dependent' definitions ** See Copyright Notice in lua.h */ @@ -165,4 +165,10 @@ typedef unsigned long Instruction; #endif +/* maximum number of syntactical nested non-terminals */ +#ifndef LUA_MAXPARSERLEVEL +#define LUA_MAXPARSERLEVEL 200 +#endif + + #endif @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 1.196 2002/10/16 20:40:58 roberto Exp roberto $ +** $Id: lparser.c,v 1.197 2002/11/22 13:59:04 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -26,6 +26,10 @@ #define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) +#define enterlevel(ls) if (++(ls)->nestlevel > LUA_MAXPARSERLEVEL) \ + luaX_syntaxerror(ls, "too many syntax levels"); +#define leavelevel(ls) ((ls)->nestlevel--) + /* ** nodes for block list (list of active blocks) @@ -356,6 +360,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) { struct LexState lexstate; struct FuncState funcstate; lexstate.buff = buff; + lexstate.nestlevel = 0; luaX_setinput(L, &lexstate, z, luaS_new(L, zname(z))); open_func(&lexstate, &funcstate); next(&lexstate); /* read first token */ @@ -364,6 +369,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) { close_func(&lexstate); lua_assert(funcstate.prev == NULL); lua_assert(funcstate.f->nupvalues == 0); + lua_assert(lexstate.nestlevel == 0); return funcstate.f; } @@ -749,7 +755,9 @@ static const struct { */ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { BinOpr op; - UnOpr uop = getunopr(ls->t.token); + UnOpr uop; + enterlevel(ls); + uop = getunopr(ls->t.token); if (uop != OPR_NOUNOPR) { next(ls); subexpr(ls, v, UNARY_PRIORITY); @@ -768,6 +776,7 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { luaK_posfix(ls->fs, op, v, &v2); op = nextop; } + leavelevel(ls); return op; /* return first untreated operator */ } @@ -1299,11 +1308,13 @@ static void body (LexState *ls, expdesc *e, int needself, int line) { static void chunk (LexState *ls) { /* chunk -> { stat [`;'] } */ int islast = 0; + enterlevel(ls); while (!islast && !block_follow(ls->t.token)) { islast = statement(ls); testnext(ls, ';'); lua_assert(ls->fs->freereg >= ls->fs->nactvar); ls->fs->freereg = ls->fs->nactvar; /* free registers */ } + leavelevel(ls); } |