mirror of
https://github.com/redis/redis.git
synced 2026-02-03 20:39:54 -05:00
LUA out-of-bound read (CVE-2025-46819)
This commit is contained in:
parent
a3ae6cb0d6
commit
671953d021
2 changed files with 67 additions and 20 deletions
34
deps/lua/src/llex.c
vendored
34
deps/lua/src/llex.c
vendored
|
|
@ -138,6 +138,7 @@ static void inclinenumber (LexState *ls) {
|
|||
|
||||
|
||||
void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) {
|
||||
ls->t.token = 0;
|
||||
ls->decpoint = '.';
|
||||
ls->L = L;
|
||||
ls->lookahead.token = TK_EOS; /* no look-ahead token */
|
||||
|
|
@ -206,9 +207,13 @@ static void read_numeral (LexState *ls, SemInfo *seminfo) {
|
|||
trydecpoint(ls, seminfo); /* try to update decimal point separator */
|
||||
}
|
||||
|
||||
|
||||
static int skip_sep (LexState *ls) {
|
||||
int count = 0;
|
||||
/*
|
||||
** reads a sequence '[=*[' or ']=*]', leaving the last bracket.
|
||||
** If a sequence is well-formed, return its number of '='s + 2; otherwise,
|
||||
** return 1 if there is no '='s or 0 otherwise (an unfinished '[==...').
|
||||
*/
|
||||
static size_t skip_sep (LexState *ls) {
|
||||
size_t count = 0;
|
||||
int s = ls->current;
|
||||
lua_assert(s == '[' || s == ']');
|
||||
save_and_next(ls);
|
||||
|
|
@ -216,11 +221,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 cont = 0;
|
||||
(void)(cont); /* avoid warnings when `cont' is not used */
|
||||
save_and_next(ls); /* skip 2nd `[' */
|
||||
|
|
@ -270,8 +277,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);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -346,9 +353,9 @@ static int llex (LexState *ls, SemInfo *seminfo) {
|
|||
/* else is a comment */
|
||||
next(ls);
|
||||
if (ls->current == '[') {
|
||||
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); /* long comment */
|
||||
luaZ_resetbuffer(ls->buff);
|
||||
continue;
|
||||
|
|
@ -360,13 +367,14 @@ static int llex (LexState *ls, SemInfo *seminfo) {
|
|||
continue;
|
||||
}
|
||||
case '[': {
|
||||
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) return '[';
|
||||
else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING);
|
||||
else if (sep == 0) /* '[=...' missing second bracket */
|
||||
luaX_lexerror(ls, "invalid long string delimiter", TK_STRING);
|
||||
return '[';
|
||||
}
|
||||
case '=': {
|
||||
next(ls);
|
||||
|
|
|
|||
|
|
@ -355,13 +355,6 @@ start_server {tags {"scripting"}} {
|
|||
set e
|
||||
} {*against a key*}
|
||||
|
||||
test {EVAL - JSON string encoding a string larger than 2GB} {
|
||||
run_script {
|
||||
local s = string.rep("a", 1024 * 1024 * 1024)
|
||||
return #cjson.encode(s..s..s)
|
||||
} 0
|
||||
} {3221225474} {large-memory} ;# length includes two double quotes at both ends
|
||||
|
||||
test {EVAL - JSON numeric decoding} {
|
||||
# We must return the table as a string because otherwise
|
||||
# Redis converts floats to ints and we get 0 and 1023 instead
|
||||
|
|
@ -1207,6 +1200,52 @@ start_server {tags {"scripting"}} {
|
|||
} {*Script attempted to access nonexistent global variable 'print'*}
|
||||
}
|
||||
|
||||
# start a new server to test the large-memory tests
|
||||
start_server {tags {"scripting external:skip large-memory"}} {
|
||||
test {EVAL - JSON string encoding a string larger than 2GB} {
|
||||
run_script {
|
||||
local s = string.rep("a", 1024 * 1024 * 1024)
|
||||
return #cjson.encode(s..s..s)
|
||||
} 0
|
||||
} {3221225474} ;# length includes two double quotes at both ends
|
||||
|
||||
test {EVAL - Test long escape sequences for strings} {
|
||||
run_script {
|
||||
-- Generate 1gb '==...==' separator
|
||||
local s = string.rep('=', 1024 * 1024)
|
||||
local t = {} for i=1,1024 do t[i] = s end
|
||||
local sep = table.concat(t)
|
||||
collectgarbage('collect')
|
||||
|
||||
local code = table.concat({'return [',sep,'[x]',sep,']'})
|
||||
collectgarbage('collect')
|
||||
|
||||
-- Load the code and run it. Script will return the string length.
|
||||
-- Escape sequence: [=....=[ to ]=...=] will be ignored
|
||||
-- Actual string is a single character: 'x'. Script will return 1
|
||||
local func = loadstring(code)
|
||||
return #func()
|
||||
} 0
|
||||
} {1}
|
||||
|
||||
test {EVAL - Lua can parse string with too many new lines} {
|
||||
# Create a long string consisting only of newline characters. When Lua
|
||||
# fails to parse a string, it typically includes a snippet like
|
||||
# "... near ..." in the error message to indicate the last recognizable
|
||||
# token. In this test, since the input contains only newlines, there
|
||||
# should be no identifiable token, so the error message should contain
|
||||
# only the actual error, without a near clause.
|
||||
|
||||
run_script {
|
||||
local s = string.rep('\n', 1024 * 1024)
|
||||
local t = {} for i=1,2048 do t[#t+1] = s end
|
||||
local lines = table.concat(t)
|
||||
local fn, err = loadstring(lines)
|
||||
return err
|
||||
} 0
|
||||
} {*chunk has too many lines}
|
||||
}
|
||||
|
||||
# Start a new server to test lua-enable-deprecated-api config
|
||||
foreach enabled {no yes} {
|
||||
start_server [subst {tags {"scripting external:skip"} overrides {lua-enable-deprecated-api $enabled}}] {
|
||||
|
|
|
|||
Loading…
Reference in a new issue