diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-12-17 15:36:51 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-12-17 15:36:51 -0200 |
| commit | 1221e987fe5ffbf2464b6e56301fb09cf6f3bb32 (patch) | |
| tree | 057c11d1f99e4934ec10584553e70bee5a6778f3 | |
| parent | 063d4e4543088e7a21965bda8ee5a0f952a9029e (diff) | |
| download | lua-1221e987fe5ffbf2464b6e56301fb09cf6f3bb32.tar.gz lua-1221e987fe5ffbf2464b6e56301fb09cf6f3bb32.tar.bz2 lua-1221e987fe5ffbf2464b6e56301fb09cf6f3bb32.zip | |
Bug: Long brackets with a huge number of '=' causes overflow
A long bracket with too many equal signs can overflow the 'int' used for
the counting and some arithmetic done on the value. Changing the counter
to 'size_t' avoids that. (Because what is counted goes to a buffer, an
overflow in the counter will first raise a buffer-overflow error.)
| -rw-r--r-- | llex.c | 31 |
1 files changed, 17 insertions, 14 deletions
| @@ -244,12 +244,12 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) { | |||
| 244 | 244 | ||
| 245 | 245 | ||
| 246 | /* | 246 | /* |
| 247 | ** skip a sequence '[=*[' or ']=*]'; if sequence is well formed, return | 247 | ** reads a sequence '[=*[' or ']=*]', leaving the last bracket. |
| 248 | ** its number of '='s; otherwise, return a negative number (-1 iff there | 248 | ** If sequence is well formed, return its number of '='s + 2; otherwise, |
| 249 | ** are no '='s after initial bracket) | 249 | ** return 1 if there is no '='s or 0 otherwise (an unfinished '[==...'). |
| 250 | */ | 250 | */ |
| 251 | static int skip_sep (LexState *ls) { | 251 | static size_t skip_sep (LexState *ls) { |
| 252 | int count = 0; | 252 | size_t count = 0; |
| 253 | int s = ls->current; | 253 | int s = ls->current; |
| 254 | lua_assert(s == '[' || s == ']'); | 254 | lua_assert(s == '[' || s == ']'); |
| 255 | save_and_next(ls); | 255 | save_and_next(ls); |
| @@ -257,11 +257,14 @@ static int skip_sep (LexState *ls) { | |||
| 257 | save_and_next(ls); | 257 | save_and_next(ls); |
| 258 | count++; | 258 | count++; |
| 259 | } | 259 | } |
| 260 | return (ls->current == s) ? count : (-count) - 1; | 260 | return (ls->current == s) ? count + 2 |
| 261 | : (count == 0) ? 1 | ||
| 262 | : 0; | ||
| 263 | |||
| 261 | } | 264 | } |
| 262 | 265 | ||
| 263 | 266 | ||
| 264 | static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { | 267 | static void read_long_string (LexState *ls, SemInfo *seminfo, size_t sep) { |
| 265 | int line = ls->linenumber; /* initial line (for error message) */ | 268 | int line = ls->linenumber; /* initial line (for error message) */ |
| 266 | save_and_next(ls); /* skip 2nd '[' */ | 269 | save_and_next(ls); /* skip 2nd '[' */ |
| 267 | if (currIsNewline(ls)) /* string starts with a newline? */ | 270 | if (currIsNewline(ls)) /* string starts with a newline? */ |
| @@ -295,8 +298,8 @@ static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { | |||
| 295 | } | 298 | } |
| 296 | } endloop: | 299 | } endloop: |
| 297 | if (seminfo) | 300 | if (seminfo) |
| 298 | seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), | 301 | seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + sep, |
| 299 | luaZ_bufflen(ls->buff) - 2*(2 + sep)); | 302 | luaZ_bufflen(ls->buff) - 2 * sep); |
| 300 | } | 303 | } |
| 301 | 304 | ||
| 302 | 305 | ||
| @@ -444,9 +447,9 @@ static int llex (LexState *ls, SemInfo *seminfo) { | |||
| 444 | /* else is a comment */ | 447 | /* else is a comment */ |
| 445 | next(ls); | 448 | next(ls); |
| 446 | if (ls->current == '[') { /* long comment? */ | 449 | if (ls->current == '[') { /* long comment? */ |
| 447 | int sep = skip_sep(ls); | 450 | size_t sep = skip_sep(ls); |
| 448 | luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */ | 451 | luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */ |
| 449 | if (sep >= 0) { | 452 | if (sep >= 2) { |
| 450 | read_long_string(ls, NULL, sep); /* skip long comment */ | 453 | read_long_string(ls, NULL, sep); /* skip long comment */ |
| 451 | luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ | 454 | luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ |
| 452 | break; | 455 | break; |
| @@ -458,12 +461,12 @@ static int llex (LexState *ls, SemInfo *seminfo) { | |||
| 458 | break; | 461 | break; |
| 459 | } | 462 | } |
| 460 | case '[': { /* long string or simply '[' */ | 463 | case '[': { /* long string or simply '[' */ |
| 461 | int sep = skip_sep(ls); | 464 | size_t sep = skip_sep(ls); |
| 462 | if (sep >= 0) { | 465 | if (sep >= 2) { |
| 463 | read_long_string(ls, seminfo, sep); | 466 | read_long_string(ls, seminfo, sep); |
| 464 | return TK_STRING; | 467 | return TK_STRING; |
| 465 | } | 468 | } |
| 466 | else if (sep != -1) /* '[=...' missing second bracket */ | 469 | else if (sep == 0) /* '[=...' missing second bracket */ |
| 467 | lexerror(ls, "invalid long string delimiter", TK_STRING); | 470 | lexerror(ls, "invalid long string delimiter", TK_STRING); |
| 468 | return '['; | 471 | return '['; |
| 469 | } | 472 | } |
