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 | } |