aboutsummaryrefslogtreecommitdiff
path: root/llex.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-12-14 13:12:01 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-12-14 13:12:01 -0200
commit57f5b81da9f1f23380d20f164012e10c5f4fef94 (patch)
treef626d12697bfec8bba9290a0f11b29f71705eaab /llex.c
parentfdc25a1ebfe9968dcec390dd556375105aa0be40 (diff)
downloadlua-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.c30
1 files changed, 16 insertions, 14 deletions
diff --git a/llex.c b/llex.c
index 4a25607c..38c6d92d 100644
--- a/llex.c
+++ b/llex.c
@@ -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*/
251static int skip_sep (LexState *ls) { 251static 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
264static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { 266static 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 }