diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-12-14 13:12:01 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-12-14 13:12:01 -0200 |
commit | 57f5b81da9f1f23380d20f164012e10c5f4fef94 (patch) | |
tree | f626d12697bfec8bba9290a0f11b29f71705eaab /llex.c | |
parent | fdc25a1ebfe9968dcec390dd556375105aa0be40 (diff) | |
download | lua-57f5b81da9f1f23380d20f164012e10c5f4fef94.tar.gz lua-57f5b81da9f1f23380d20f164012e10c5f4fef94.tar.bz2 lua-57f5b81da9f1f23380d20f164012e10c5f4fef94.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.)
Diffstat (limited to 'llex.c')
-rw-r--r-- | llex.c | 30 |
1 files changed, 16 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,13 @@ 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; | ||
261 | } | 263 | } |
262 | 264 | ||
263 | 265 | ||
264 | static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { | 266 | static void read_long_string (LexState *ls, SemInfo *seminfo, size_t sep) { |
265 | int line = ls->linenumber; /* initial line (for error message) */ | 267 | int line = ls->linenumber; /* initial line (for error message) */ |
266 | save_and_next(ls); /* skip 2nd '[' */ | 268 | save_and_next(ls); /* skip 2nd '[' */ |
267 | if (currIsNewline(ls)) /* string starts with a newline? */ | 269 | if (currIsNewline(ls)) /* string starts with a newline? */ |
@@ -295,8 +297,8 @@ static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { | |||
295 | } | 297 | } |
296 | } endloop: | 298 | } endloop: |
297 | if (seminfo) | 299 | if (seminfo) |
298 | seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), | 300 | seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + sep, |
299 | luaZ_bufflen(ls->buff) - 2*(2 + sep)); | 301 | luaZ_bufflen(ls->buff) - 2 * sep); |
300 | } | 302 | } |
301 | 303 | ||
302 | 304 | ||
@@ -444,9 +446,9 @@ static int llex (LexState *ls, SemInfo *seminfo) { | |||
444 | /* else is a comment */ | 446 | /* else is a comment */ |
445 | next(ls); | 447 | next(ls); |
446 | if (ls->current == '[') { /* long comment? */ | 448 | if (ls->current == '[') { /* long comment? */ |
447 | int sep = skip_sep(ls); | 449 | size_t sep = skip_sep(ls); |
448 | luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */ | 450 | luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */ |
449 | if (sep >= 0) { | 451 | if (sep >= 2) { |
450 | read_long_string(ls, NULL, sep); /* skip long comment */ | 452 | read_long_string(ls, NULL, sep); /* skip long comment */ |
451 | luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ | 453 | luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ |
452 | break; | 454 | break; |
@@ -458,12 +460,12 @@ static int llex (LexState *ls, SemInfo *seminfo) { | |||
458 | break; | 460 | break; |
459 | } | 461 | } |
460 | case '[': { /* long string or simply '[' */ | 462 | case '[': { /* long string or simply '[' */ |
461 | int sep = skip_sep(ls); | 463 | size_t sep = skip_sep(ls); |
462 | if (sep >= 0) { | 464 | if (sep >= 2) { |
463 | read_long_string(ls, seminfo, sep); | 465 | read_long_string(ls, seminfo, sep); |
464 | return TK_STRING; | 466 | return TK_STRING; |
465 | } | 467 | } |
466 | else if (sep != -1) /* '[=...' missing second bracket */ | 468 | else if (sep == 0) /* '[=...' missing second bracket? */ |
467 | lexerror(ls, "invalid long string delimiter", TK_STRING); | 469 | lexerror(ls, "invalid long string delimiter", TK_STRING); |
468 | return '['; | 470 | return '['; |
469 | } | 471 | } |