summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-12-17 15:36:51 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-12-17 15:36:51 -0200
commit1221e987fe5ffbf2464b6e56301fb09cf6f3bb32 (patch)
tree057c11d1f99e4934ec10584553e70bee5a6778f3
parent063d4e4543088e7a21965bda8ee5a0f952a9029e (diff)
downloadlua-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.c31
1 files changed, 17 insertions, 14 deletions
diff --git a/llex.c b/llex.c
index 66fd411b..b6d9a465 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,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
264static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { 267static 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 }