new file mode 100644
@@ -0,0 +1,161 @@
+From 2802b52b554cb9f0f249a24474c9fba94e933dbb Mon Sep 17 00:00:00 2001
+From: Ozan Tezcan <ozantezcan@gmail.com>
+Date: Mon, 23 Jun 2025 12:11:31 +0300
+Subject: [PATCH] LUA out-of-bound read (CVE-2025-46819)
+
+Upstream-Status: Backport [https://github.com/redis/redis/commit/2802b52b554cb9f0f249a24474c9fba94e933dbb]
+CVE: CVE-2025-46819
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ deps/lua/src/llex.c | 34 ++++++++++++++++++-----------
+ tests/unit/scripting.tcl | 47 ++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 68 insertions(+), 13 deletions(-)
+
+diff --git a/deps/lua/src/llex.c b/deps/lua/src/llex.c
+index 88c6790..efad709 100644
+--- a/deps/lua/src/llex.c
++++ b/deps/lua/src/llex.c
+@@ -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);
+diff --git a/tests/unit/scripting.tcl b/tests/unit/scripting.tcl
+index 58f2028..2ff0d44 100644
+--- a/tests/unit/scripting.tcl
++++ b/tests/unit/scripting.tcl
+@@ -1070,6 +1070,53 @@ 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}}] {
+--
+2.25.1
+
@@ -29,6 +29,7 @@ SRC_URI = "http://download.redis.io/releases/${BP}.tar.gz \
file://CVE-2025-48367.patch \
file://CVE-2025-46817.patch \
file://CVE-2025-46818.patch \
+ file://CVE-2025-46819.patch \
"
SRC_URI[sha256sum] = "97065774d5fb8388eb0d8913458decfcb167d356e40d31dd01cd30c1cc391673"