mirror of
https://github.com/lua/lua
synced 2024-11-25 22:29:39 +03:00
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.)
This commit is contained in:
parent
fdc25a1ebf
commit
57f5b81da9
19
bugs
19
bugs
@ -4017,6 +4017,25 @@ patch = [[
|
||||
|
||||
|
||||
|
||||
--[=[
|
||||
Bug{
|
||||
what = [[Long brackets with a huge number of '=' overflow some
|
||||
internal buffer arithmetic]],
|
||||
report = [[Marco, 2018/12/12]],
|
||||
since = [[5.1]],
|
||||
fix = nil,
|
||||
example = [[
|
||||
local eqs = string.rep("=", 0x3ffffffe)
|
||||
local code = "return [" .. eqs .. "[a]" .. eqs .. "]"
|
||||
print(#assert(load(code))())
|
||||
]],
|
||||
patch = [[
|
||||
]]
|
||||
}
|
||||
]=]
|
||||
|
||||
|
||||
|
||||
|
||||
--[=[
|
||||
Bug{
|
||||
|
30
llex.c
30
llex.c
@ -244,12 +244,12 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) {
|
||||
|
||||
|
||||
/*
|
||||
** skip a sequence '[=*[' or ']=*]'; if sequence is well formed, return
|
||||
** its number of '='s; otherwise, return a negative number (-1 iff there
|
||||
** are no '='s after initial bracket)
|
||||
** reads a sequence '[=*[' or ']=*]', leaving the last bracket.
|
||||
** If sequence is well formed, return its number of '='s + 2; otherwise,
|
||||
** return 1 if there is no '='s or 0 otherwise (an unfinished '[==...').
|
||||
*/
|
||||
static int skip_sep (LexState *ls) {
|
||||
int count = 0;
|
||||
static size_t skip_sep (LexState *ls) {
|
||||
size_t count = 0;
|
||||
int s = ls->current;
|
||||
lua_assert(s == '[' || s == ']');
|
||||
save_and_next(ls);
|
||||
@ -257,11 +257,13 @@ static int skip_sep (LexState *ls) {
|
||||
save_and_next(ls);
|
||||
count++;
|
||||
}
|
||||
return (ls->current == s) ? count : (-count) - 1;
|
||||
return (ls->current == s) ? count + 2
|
||||
: (count == 0) ? 1
|
||||
: 0;
|
||||
}
|
||||
|
||||
|
||||
static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
|
||||
static void read_long_string (LexState *ls, SemInfo *seminfo, size_t sep) {
|
||||
int line = ls->linenumber; /* initial line (for error message) */
|
||||
save_and_next(ls); /* skip 2nd '[' */
|
||||
if (currIsNewline(ls)) /* string starts with a newline? */
|
||||
@ -295,8 +297,8 @@ static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
|
||||
}
|
||||
} endloop:
|
||||
if (seminfo)
|
||||
seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep),
|
||||
luaZ_bufflen(ls->buff) - 2*(2 + sep));
|
||||
seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + sep,
|
||||
luaZ_bufflen(ls->buff) - 2 * sep);
|
||||
}
|
||||
|
||||
|
||||
@ -444,9 +446,9 @@ static int llex (LexState *ls, SemInfo *seminfo) {
|
||||
/* else is a comment */
|
||||
next(ls);
|
||||
if (ls->current == '[') { /* long comment? */
|
||||
int sep = skip_sep(ls);
|
||||
size_t sep = skip_sep(ls);
|
||||
luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */
|
||||
if (sep >= 0) {
|
||||
if (sep >= 2) {
|
||||
read_long_string(ls, NULL, sep); /* skip long comment */
|
||||
luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */
|
||||
break;
|
||||
@ -458,12 +460,12 @@ static int llex (LexState *ls, SemInfo *seminfo) {
|
||||
break;
|
||||
}
|
||||
case '[': { /* long string or simply '[' */
|
||||
int sep = skip_sep(ls);
|
||||
if (sep >= 0) {
|
||||
size_t sep = skip_sep(ls);
|
||||
if (sep >= 2) {
|
||||
read_long_string(ls, seminfo, sep);
|
||||
return TK_STRING;
|
||||
}
|
||||
else if (sep != -1) /* '[=...' missing second bracket */
|
||||
else if (sep == 0) /* '[=...' missing second bracket? */
|
||||
lexerror(ls, "invalid long string delimiter", TK_STRING);
|
||||
return '[';
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user