Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package redis for openSUSE:Factory checked 
in at 2026-02-24 15:37:58
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/redis (Old)
 and      /work/SRC/openSUSE:Factory/.redis.new.1977 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "redis"

Tue Feb 24 15:37:58 2026 rev:12 rq:1334485 version:8.6.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/redis/redis.changes      2026-02-11 
18:53:36.849404864 +0100
+++ /work/SRC/openSUSE:Factory/.redis.new.1977/redis.changes    2026-02-24 
15:38:18.725700489 +0100
@@ -1,0 +2,11 @@
+Mon Feb 23 10:07:40 UTC 2026 - Илья Индиго <[email protected]>
+
+- Updated to 8.6.1 (boo#1258706)
+  * https://github.com/redis/redis/releases/tag/8.6.1
+  * Fixed user can manipulate data read by a connection by
+    injecting \r\n sequences into a Redis error reply.
+  * Fixed INFO command may display module information,
+    and the missing HOTKEYS HELP subcommand has been added.
+  * Fixed RDB loading prevented hash table expansion.
+
+-------------------------------------------------------------------
@@ -4 +15,2 @@
-- Updated to 8.6.0 Major changes compared to 8.4
+- Updated to 8.6.0
+  Major changes compared to 8.4

Old:
----
  redis-8.6.0.tar.gz

New:
----
  redis-8.6.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ redis.spec ++++++
--- /var/tmp/diff_new_pack.05oNnD/_old  2026-02-24 15:38:19.533734031 +0100
+++ /var/tmp/diff_new_pack.05oNnD/_new  2026-02-24 15:38:19.537734198 +0100
@@ -20,7 +20,7 @@
 %define _log_dir        %{_localstatedir}/log/%{name}
 %define _conf_dir       %{_sysconfdir}/%{name}
 Name:           redis
-Version:        8.6.0
+Version:        8.6.1
 Release:        0
 Summary:        Persistent key-value database
 License:        AGPL-3.0-only

++++++ redis-8.6.0.tar.gz -> redis-8.6.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/00-RELEASENOTES 
new/redis-8.6.1/00-RELEASENOTES
--- old/redis-8.6.0/00-RELEASENOTES     2026-02-10 15:08:46.000000000 +0100
+++ new/redis-8.6.1/00-RELEASENOTES     2026-02-23 10:06:21.000000000 +0100
@@ -20,6 +20,22 @@
 #Pn = Probabilistic (https://github.com/RedisBloom/RedisBloom)
 
 
+================================================================================
+Redis 8.6.1    Released Mon 23 Feb 2026 10:00:00 IST
+================================================================================
+
+SECURITY: There is a security fix in the release
+
+### Security fixes
+
+- A user can manipulate data read by a connection by injecting \r\n sequences 
into a Redis error reply
+
+### Bug fixes
+
+- #14785 `HOTKEYS`: The `INFO` command may display module information, and the 
missing `HOTKEYS HELP` subcommand has been added
+- #14789 Bug in RDB loading prevented hash table expansion, increasing load 
time
+
+
 ================================================================
 Redis 8.6 GA (8.6.0)    Released Tue 10 Feb 2026 16:00:00 IST
 ================================================================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/src/commands/hotkeys-help.json 
new/redis-8.6.1/src/commands/hotkeys-help.json
--- old/redis-8.6.0/src/commands/hotkeys-help.json      1970-01-01 
01:00:00.000000000 +0100
+++ new/redis-8.6.1/src/commands/hotkeys-help.json      2026-02-23 
10:06:21.000000000 +0100
@@ -0,0 +1,22 @@
+{
+    "HELP": {
+        "summary": "Return helpful text about HOTKEYS command parameters.",
+        "complexity": "O(1)",
+        "group": "server",
+        "since": "8.6.1",
+        "arity": 2,
+        "container": "HOTKEYS",
+        "function": "hotkeysCommand",
+        "command_flags": [
+            "LOADING",
+            "STALE"
+        ],
+        "reply_schema": {
+            "type": "array",
+            "description": "Helpful text about subcommands.",
+            "items": {
+                "type": "string"
+            }
+        }
+    }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/src/commands.def 
new/redis-8.6.1/src/commands.def
--- old/redis-8.6.0/src/commands.def    2026-02-10 15:08:46.000000000 +0100
+++ new/redis-8.6.1/src/commands.def    2026-02-23 10:06:21.000000000 +0100
@@ -7332,6 +7332,23 @@
 #define HOTKEYS_GET_Keyspecs NULL
 #endif
 
+/********** HOTKEYS HELP ********************/
+
+#ifndef SKIP_CMD_HISTORY_TABLE
+/* HOTKEYS HELP history */
+#define HOTKEYS_HELP_History NULL
+#endif
+
+#ifndef SKIP_CMD_TIPS_TABLE
+/* HOTKEYS HELP tips */
+#define HOTKEYS_HELP_Tips NULL
+#endif
+
+#ifndef SKIP_CMD_KEY_SPECS_TABLE
+/* HOTKEYS HELP key specs */
+#define HOTKEYS_HELP_Keyspecs NULL
+#endif
+
 /********** HOTKEYS RESET ********************/
 
 #ifndef SKIP_CMD_HISTORY_TABLE
@@ -7414,6 +7431,7 @@
 /* HOTKEYS command table */
 struct COMMAND_STRUCT HOTKEYS_Subcommands[] = {
 {MAKE_CMD("get","Returns lists of top K hotkeys depending on metrics chosen in 
HOTKEYS START command.","O(K) where K is the number of hotkeys 
returned.","8.6.0",CMD_DOC_NONE,NULL,NULL,"server",COMMAND_GROUP_SERVER,HOTKEYS_GET_History,0,HOTKEYS_GET_Tips,3,hotkeysCommand,2,CMD_ADMIN|CMD_NOSCRIPT,0,HOTKEYS_GET_Keyspecs,0,NULL,0)},
+{MAKE_CMD("help","Return helpful text about HOTKEYS command 
parameters.","O(1)","8.6.1",CMD_DOC_NONE,NULL,NULL,"server",COMMAND_GROUP_SERVER,HOTKEYS_HELP_History,0,HOTKEYS_HELP_Tips,0,hotkeysCommand,2,CMD_LOADING|CMD_STALE,0,HOTKEYS_HELP_Keyspecs,0,NULL,0)},
 {MAKE_CMD("reset","Release the resources used for hotkey 
tracking.","O(1)","8.6.0",CMD_DOC_NONE,NULL,NULL,"server",COMMAND_GROUP_SERVER,HOTKEYS_RESET_History,0,HOTKEYS_RESET_Tips,1,hotkeysCommand,2,CMD_ADMIN|CMD_NOSCRIPT,0,HOTKEYS_RESET_Keyspecs,0,NULL,0)},
 {MAKE_CMD("start","Starts hotkeys 
tracking.","O(1)","8.6.0",CMD_DOC_NONE,NULL,NULL,"server",COMMAND_GROUP_SERVER,HOTKEYS_START_History,0,HOTKEYS_START_Tips,1,hotkeysCommand,-2,CMD_ADMIN|CMD_NOSCRIPT,0,HOTKEYS_START_Keyspecs,0,NULL,5),.args=HOTKEYS_START_Args},
 {MAKE_CMD("stop","Stops hotkeys 
tracking.","O(1)","8.6.0",CMD_DOC_NONE,NULL,NULL,"server",COMMAND_GROUP_SERVER,HOTKEYS_STOP_History,0,HOTKEYS_STOP_Tips,1,hotkeysCommand,2,CMD_ADMIN|CMD_NOSCRIPT,0,HOTKEYS_STOP_Keyspecs,0,NULL,0)},
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/src/functions.c 
new/redis-8.6.1/src/functions.c
--- old/redis-8.6.0/src/functions.c     2026-02-10 15:08:46.000000000 +0100
+++ new/redis-8.6.1/src/functions.c     2026-02-23 10:06:21.000000000 +0100
@@ -520,7 +520,7 @@
             library_name = c->argv[++i]->ptr;
             continue;
         }
-        addReplyErrorSds(c, sdscatfmt(sdsempty(), "Unknown argument %s", 
next_arg->ptr));
+        addReplyErrorSdsSafe(c, sdscatfmt(sdsempty(), "Unknown argument %s", 
next_arg->ptr));
         return;
     }
     size_t reply_len = 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/src/hotkeys.c 
new/redis-8.6.1/src/hotkeys.c
--- old/redis-8.6.0/src/hotkeys.c       2026-02-10 15:08:46.000000000 +0100
+++ new/redis-8.6.1/src/hotkeys.c       2026-02-23 10:06:21.000000000 +0100
@@ -266,7 +266,33 @@
 
     char *sub = c->argv[1]->ptr;
 
-    if (!strcasecmp(sub, "START")) {
+    if (!strcasecmp(sub, "HELP")) {
+        const char *help[] = {
+            "START <METRICS count [CPU] [NET]> [COUNT k] [DURATION duration] 
[SAMPLE ratio] [SLOTS count slot...]",
+            "    Starts hotkeys tracking with specified metrics.",
+            "    * METRICS count [CPU] [NET]",
+            "        Specify count of metrics and choose amongst:",
+            "        - CPU: Track hotkeys by CPU time percentage",
+            "        - NET: Track hotkeys by network bytes percentage",
+            "    * COUNT k",
+            "        Specifies the value of K for the top-K hotkeys tracking. 
Default: 10",
+            "    * DURATION duration",
+            "        Specifies tracking duration in seconds. 0 means tracking 
will continue until manually stopped. Default: 0",
+            "    * SAMPLE ratio",
+            "        Keys are tracked with probability 1/ratio. Default: 1 
(tracks every key)",
+            "    * SLOTS count slot...",
+            "        Specify which slots to track keys from. Only available in 
cluster mode. Default: empty (track all slots)",
+            "STOP",
+            "    Stop hotkeys tracking. Results are still available via GET",
+            "GET",
+            "    Get results from hotkeys tracking.",
+            "RESET",
+            "    Reset memory used for hotkeys tracking. Tracking must have 
been stopped.",
+            "    Results will no longer be available after this command.",
+            NULL
+        };
+        addReplyHelp(c, help);
+    } else if (!strcasecmp(sub, "START")) {
         /* HOTKEYS START
          *         <METRICS count [CPU] [NET]>
          *         [COUNT k]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/src/kvstore.c 
new/redis-8.6.1/src/kvstore.c
--- old/redis-8.6.0/src/kvstore.c       2026-02-10 15:08:46.000000000 +0100
+++ new/redis-8.6.1/src/kvstore.c       2026-02-23 10:06:21.000000000 +0100
@@ -385,9 +385,10 @@
  */
 int kvstoreExpand(kvstore *kvs, uint64_t newsize, int try_expand, 
kvstoreExpandShouldSkipDictIndex *skip_cb) {
     for (int i = 0; i < kvs->num_dicts; i++) {
-        dict *d = kvstoreGetDict(kvs, i);
-        if (!d || (skip_cb && skip_cb(i)))
-            continue;
+        if (skip_cb && skip_cb(i)) continue;
+        dict *d = createDictIfNeeded(kvs, i);
+        if (!d) continue;
+
         int result = try_expand ? dictTryExpand(d, newsize) : dictExpand(d, 
newsize);
         if (try_expand && result == DICT_ERR)
             return 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/src/module.c new/redis-8.6.1/src/module.c
--- old/redis-8.6.0/src/module.c        2026-02-10 15:08:46.000000000 +0100
+++ new/redis-8.6.1/src/module.c        2026-02-23 10:06:21.000000000 +0100
@@ -3162,9 +3162,7 @@
 int RM_ReplyWithSimpleString(RedisModuleCtx *ctx, const char *msg) {
     client *c = moduleGetReplyClient(ctx);
     if (c == NULL) return REDISMODULE_OK;
-    addReplyProto(c,"+",1);
-    addReplyProto(c,msg,strlen(msg));
-    addReplyProto(c,"\r\n",2);
+    addReplyStatusSafe(c, msg);
     return REDISMODULE_OK;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/src/networking.c 
new/redis-8.6.1/src/networking.c
--- old/redis-8.6.0/src/networking.c    2026-02-10 15:08:46.000000000 +0100
+++ new/redis-8.6.1/src/networking.c    2026-02-23 10:06:21.000000000 +0100
@@ -766,6 +766,13 @@
     sdsfree(err);
 }
 
+/* See addReplyErrorLength for expectations from the input string.
+ * The string is safe to contain \r and \n anywhere. */
+void addReplyErrorSdsExSafe(client *c, sds err, int flags) {
+    err = sdsmapchars(err, "\r\n", "  ",  2);
+    addReplyErrorSdsEx(c, err, flags);
+}
+
 /* See addReplyErrorLength for expectations from the input string. */
 /* As a side effect the SDS string is freed. */
 void addReplyErrorSds(client *c, sds err) {
@@ -832,11 +839,23 @@
     addReplyStatusLength(c,status,strlen(status));
 }
 
+/* Like addReplyStatus() but the string is safe to contain \r and \n anywhere. 
*/
+void addReplyStatusSafe(client *c, const char *status) {
+    sds s = sdsmapchars(sdsnew(status), "\r\n", "  ",  2);
+    addReplyStatusLength(c,s,sdslen(s));
+    sdsfree(s);
+}
+
 void addReplyStatusFormat(client *c, const char *fmt, ...) {
     va_list ap;
     va_start(ap,fmt);
     sds s = sdscatvprintf(sdsempty(),fmt,ap);
     va_end(ap);
+    /* Trim any newlines at the end (ones will be added by 
addReplyStatusLength) */
+    s = sdstrim(s, "\r\n");
+    /* Make sure there are no newlines in the middle of the string, otherwise
+     * invalid protocol is emitted. */
+    s = sdsmapchars(s, "\r\n", "  ",  2);
     addReplyStatusLength(c,s,sdslen(s));
     sdsfree(s);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/src/rdb.c new/redis-8.6.1/src/rdb.c
--- old/redis-8.6.0/src/rdb.c   2026-02-10 15:08:46.000000000 +0100
+++ new/redis-8.6.1/src/rdb.c   2026-02-23 10:06:21.000000000 +0100
@@ -3902,6 +3902,8 @@
             dbExpand(db, db_size, 0);
             dbExpandExpires(db, expires_size, 0);
             should_expand_db = 0;
+            serverLog(LL_VERBOSE, "DB %d resized: %lu key buckets, %lu expire 
buckets",
+                        db->id, kvstoreBuckets(db->keys), 
kvstoreBuckets(db->expires));
         }
 
         /* With metadata, type = RDB_OPCODE_KEY_META. Layout: 
[<META>,]<TYPE>,<KEY>,<VALUE> */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/src/script_lua.c 
new/redis-8.6.1/src/script_lua.c
--- old/redis-8.6.0/src/script_lua.c    2026-02-10 15:08:46.000000000 +0100
+++ new/redis-8.6.1/src/script_lua.c    2026-02-23 10:06:21.000000000 +0100
@@ -636,10 +636,7 @@
         lua_rawget(lua,-2);
         t = lua_type(lua,-1);
         if (t == LUA_TSTRING) {
-            sds ok = sdsnew(lua_tostring(lua,-1));
-            sdsmapchars(ok,"\r\n","  ",2);
-            addReplyStatusLength(c, ok, sdslen(ok));
-            sdsfree(ok);
+            addReplyStatusSafe(c, lua_tostring(lua,-1));
             lua_pop(lua,2);
             return;
         }
@@ -1727,7 +1724,7 @@
                                       err_info.source,
                                       err_info.line);
             }
-            addReplyErrorSdsEx(c, final_msg, err_info.ignore_err_stats_update? 
ERR_REPLY_FLAG_NO_STATS_UPDATE : 0);
+            addReplyErrorSdsExSafe(c, final_msg, 
err_info.ignore_err_stats_update? ERR_REPLY_FLAG_NO_STATS_UPDATE : 0);
             luaErrorInformationDiscard(&err_info);
         }
         lua_pop(lua,1); /* Consume the Lua error */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/src/server.c new/redis-8.6.1/src/server.c
--- old/redis-8.6.0/src/server.c        2026-02-10 15:08:46.000000000 +0100
+++ new/redis-8.6.1/src/server.c        2026-02-23 10:06:21.000000000 +0100
@@ -6721,16 +6721,18 @@
     }
 
     /* Hotkeys */
-    if (server.hotkeys &&
-        (all_sections || (dictFind(section_dict,"hotkeys") != NULL)))
+    if (all_sections || (dictFind(section_dict,"hotkeys") != NULL))
     {
         if (sections++) info = sdscat(info,"\r\n"); 
 
-        info = sdscatprintf(info, "# Hotkeys\r\n"
-            "hotkeys-tracking-active:%d\r\n"
-            "hotkeys-cmd-cpu-time:%lld\r\n",
-            server.hotkeys->active ? 1 : 0,
-            server.hotkeys->cpu_time);
+        info = sdscatprintf(info, "# Hotkeys\r\n");
+        if (server.hotkeys) {
+            info = sdscatprintf(info,
+                "hotkeys-tracking-active:%d\r\n"
+                "hotkeys-cmd-cpu-time:%lld\r\n",
+                server.hotkeys->active ? 1 : 0,
+                server.hotkeys->cpu_time);
+        }
     }
 
     /* Modules */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/src/server.h new/redis-8.6.1/src/server.h
--- old/redis-8.6.0/src/server.h        2026-02-10 15:08:46.000000000 +0100
+++ new/redis-8.6.1/src/server.h        2026-02-23 10:06:21.000000000 +0100
@@ -3134,12 +3134,14 @@
 void afterErrorReply(client *c, const char *s, size_t len, int flags);
 void addReplyErrorFormatInternal(client *c, int flags, const char *fmt, 
va_list ap);
 void addReplyErrorSdsEx(client *c, sds err, int flags);
+void addReplyErrorSdsExSafe(client *c, sds err, int flags);
 void addReplyErrorSds(client *c, sds err);
 void addReplyErrorSdsSafe(client *c, sds err);
 void addReplyError(client *c, const char *err);
 void addReplyErrorArity(client *c);
 void addReplyErrorExpireTime(client *c);
 void addReplyStatus(client *c, const char *status);
+void addReplyStatusSafe(client *c, const char *s);
 void addReplyDouble(client *c, double d);
 void addReplyBigNum(client *c, const char *num, size_t len);
 void addReplyHumanLongDouble(client *c, long double d);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/src/version.h 
new/redis-8.6.1/src/version.h
--- old/redis-8.6.0/src/version.h       2026-02-10 15:08:46.000000000 +0100
+++ new/redis-8.6.1/src/version.h       2026-02-23 10:06:21.000000000 +0100
@@ -1,2 +1,2 @@
-#define REDIS_VERSION "8.6.0"
-#define REDIS_VERSION_NUM 0x00080600
+#define REDIS_VERSION "8.6.1"
+#define REDIS_VERSION_NUM 0x00080601
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/tests/integration/rdb.tcl 
new/redis-8.6.1/tests/integration/rdb.tcl
--- old/redis-8.6.0/tests/integration/rdb.tcl   2026-02-10 15:08:46.000000000 
+0100
+++ new/redis-8.6.1/tests/integration/rdb.tcl   2026-02-23 10:06:21.000000000 
+0100
@@ -80,6 +80,23 @@
     r del stream
 }
 
+start_server {overrides {loglevel verbose}} {
+    test {RDB load applies RESIZEDB hint to expand hash tables} {
+        # Populate keys and save RDB
+        r flushall sync
+        regexp {db=(\d+)} [r client info] -> dbid
+        # 500 keys with 3600 second expiration, 500 without
+        populate 500 "key1:" 3 0 false 3600
+        populate 500 "key2:" 3 0 false 0
+        r save
+
+        restart_server 0 true false
+
+        # Verify DB resize log message
+        verify_log_message 0 "*DB $dbid resized*1024 key*512 expire*" 0
+    }
+}
+
 # Helper function to start a server and kill it, just to check the error
 # logged.
 set defaults {}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/tests/modules/infotest.c 
new/redis-8.6.1/tests/modules/infotest.c
--- old/redis-8.6.0/tests/modules/infotest.c    2026-02-10 15:08:46.000000000 
+0100
+++ new/redis-8.6.1/tests/modules/infotest.c    2026-02-23 10:06:21.000000000 
+0100
@@ -3,9 +3,11 @@
 #include <string.h>
 
 void InfoFunc(RedisModuleInfoCtx *ctx, int for_crash_report) {
+    static int info_func_calls = 0;
     RedisModule_InfoAddSection(ctx, "");
     RedisModule_InfoAddFieldLongLong(ctx, "global", -2);
     RedisModule_InfoAddFieldULongLong(ctx, "uglobal", (unsigned long long)-2);
+    RedisModule_InfoAddFieldLongLong(ctx, "info_calls", ++info_func_calls);
 
     RedisModule_InfoAddSection(ctx, "Spanish");
     RedisModule_InfoAddFieldCString(ctx, "uno", "one");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/tests/modules/reply.c 
new/redis-8.6.1/tests/modules/reply.c
--- old/redis-8.6.0/tests/modules/reply.c       2026-02-10 15:08:46.000000000 
+0100
+++ new/redis-8.6.1/tests/modules/reply.c       2026-02-23 10:06:21.000000000 
+0100
@@ -82,6 +82,19 @@
     return REDISMODULE_OK;
 }
 
+int rw_simplestring_array(RedisModuleCtx *ctx, RedisModuleString **argv, int 
argc) {
+    if (argc < 2) return RedisModule_WrongArity(ctx);
+
+    RedisModule_ReplyWithArray(ctx, argc - 1);
+    for (int i = 1; i < argc; ++i) {
+        size_t len;
+        const char *str = RedisModule_StringPtrLen(argv[i], &len);
+        RedisModule_ReplyWithSimpleString(ctx, str);
+    }
+
+    return REDISMODULE_OK;
+}
+
 int rw_map(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
     if (argc != 2) return RedisModule_WrongArity(ctx);
 
@@ -193,6 +206,8 @@
         return REDISMODULE_ERR;
     if (RedisModule_CreateCommand(ctx,"rw.array",rw_array,"",0,0,0) != 
REDISMODULE_OK)
         return REDISMODULE_ERR;
+    if 
(RedisModule_CreateCommand(ctx,"rw.simplestring_array",rw_simplestring_array,"",0,0,0)
 != REDISMODULE_OK)
+        return REDISMODULE_ERR;
     if (RedisModule_CreateCommand(ctx,"rw.map",rw_map,"",0,0,0) != 
REDISMODULE_OK)
         return REDISMODULE_ERR;
     if (RedisModule_CreateCommand(ctx,"rw.attribute",rw_attribute,"",0,0,0) != 
REDISMODULE_OK)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/tests/unit/functions.tcl 
new/redis-8.6.1/tests/unit/functions.tcl
--- old/redis-8.6.0/tests/unit/functions.tcl    2026-02-10 15:08:46.000000000 
+0100
+++ new/redis-8.6.1/tests/unit/functions.tcl    2026-02-23 10:06:21.000000000 
+0100
@@ -1020,6 +1020,15 @@
 
         r config set maxmemory 0
     } {OK} {needs:config-maxmemory}
+
+    test {FUNCTION - test function list with CRLF injection attempt} {
+        r function flush
+
+        # This test verifies that CRLF characters are properly handled
+        # to prevent protocol injection attacks when using FUNCTION LIST.
+        # The error message should have CRLF replaced with spaces.
+        assert_error {*Unknown argument X  +INJECTED*} {r function list 
"X\r\n+INJECTED"}
+    }
 }
 
 start_server {tags {"scripting"}} {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/tests/unit/moduleapi/infotest.tcl 
new/redis-8.6.1/tests/unit/moduleapi/infotest.tcl
--- old/redis-8.6.0/tests/unit/moduleapi/infotest.tcl   2026-02-10 
15:08:46.000000000 +0100
+++ new/redis-8.6.1/tests/unit/moduleapi/infotest.tcl   2026-02-23 
10:06:21.000000000 +0100
@@ -10,6 +10,16 @@
 start_server {tags {"modules external:skip"}} {
     r module load $testmodule log-key 0
 
+    test {module info not attempted in INFO ALL} {
+        # call INFO in a few different ways, check that regardless of the 
section filtering,
+        # the module isn't at all being called when unneeded.
+        r INFO
+        r INFO all
+        r INFO memory
+        set info [r info everything]
+        set calls [field $info infotest_info_calls]
+    } {1}
+
     test {module reading info} {
         # check string, integer and float fields
         assert_equal [r info.gets replication role] "master"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/tests/unit/moduleapi/reply.tcl 
new/redis-8.6.1/tests/unit/moduleapi/reply.tcl
--- old/redis-8.6.0/tests/unit/moduleapi/reply.tcl      2026-02-10 
15:08:46.000000000 +0100
+++ new/redis-8.6.1/tests/unit/moduleapi/reply.tcl      2026-02-23 
10:06:21.000000000 +0100
@@ -143,6 +143,22 @@
             assert_match "WRONGTYPE A type error: foo5" $e
         }
 
+        test "RESP$proto: redis.call reply parsing with invalid CRLF 
character" {
+            # When Lua parses redis.call replies, the current implementation 
only
+            # searches for '\r' characters without verifying that '\n' 
follows. If a '\r'
+            # appears in the protocol data (not as part of the CRLF 
delimiter), the parser
+            # incorrectly treats it as a valid '\r\n' terminator.
+            #
+            # Example: Protocol data containing "\rx=100000000000" would be 
parsed as:
+            #   - '\rx' is treated as line terminator (should require '\r\n')
+            #   - '=100000000000' is interpreted as length specifier
+            #   - Lua attempts to create a massive string → Out of Memory
+            r deferred 1
+            r eval {return redis.call('rw.simplestring_array', 
'\rx=100000000000', 'hello')} 0
+            assert_equal [r rawread 30] "*2\r\n+ x=100000000000\r\n+hello\r\n"
+            r deferred 0
+        }
+
         r hello 2
     }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.0/tests/unit/scripting.tcl 
new/redis-8.6.1/tests/unit/scripting.tcl
--- old/redis-8.6.0/tests/unit/scripting.tcl    2026-02-10 15:08:46.000000000 
+0100
+++ new/redis-8.6.1/tests/unit/scripting.tcl    2026-02-23 10:06:21.000000000 
+0100
@@ -2606,6 +2606,14 @@
         assert_equal [errorrstat ERR r] {count=1}
     }
 
+    test "LUA redis.error_reply API with CRLF injection attempt" {
+        catch {
+            r eval {error(redis.error_reply("X\r\n+INJECTED"))} 0
+        } err
+        # The error message should have CRLF replaced with spaces
+        assert_match {ERR X  +INJECTED*} $err
+    }
+
     test "LUA redis.status_reply API" {
         r config resetstat
         r readraw 1

++++++ redis.hashes ++++++
--- /var/tmp/diff_new_pack.05oNnD/_old  2026-02-24 15:38:20.921791651 +0100
+++ /var/tmp/diff_new_pack.05oNnD/_new  2026-02-24 15:38:20.929791984 +0100
@@ -214,4 +214,10 @@
 hash redis-8.2.4.tar.gz sha256 
954943d4873f3add5e3b694832b52753e9f55b810a917d0148675f27480ac8c2 
http://download.redis.io/releases/redis-8.2.4.tar.gz
 hash redis-8.4.1.tar.gz sha256 
859fe81b881f741843006eacf3e43d36b01af7ce3eabd5d7d2cb568533502162 
http://download.redis.io/releases/redis-8.4.1.tar.gz
 hash redis-8.6.0.tar.gz sha256 
d7e5f65f0bb0b4753d0cf98a60f5409a7c9b430ff8ac3397d336260cf64e5a6e 
http://download.redis.io/releases/redis-8.6.0.tar.gz
+hash redis-8.6.1.tar.gz sha256 
6873fc933eeb7018aa329e868beac7228695f50c0d46f236a4ff1a6d7f7bb5b6 
http://download.redis.io/releases/redis-8.6.1.tar.gz
+hash redis-8.4.2.tar.gz sha256 
0e7c150919e10c630d6e806fa7e65ce12aa90ddd0805e459b7da64ee65892805 
http://download.redis.io/releases/redis-8.4.2.tar.gz
+hash redis-8.2.5.tar.gz sha256 
68de6b8c7665ac7f5ddea026745515ea027a1e233d3ed413f67134333c0e611b 
http://download.redis.io/releases/redis-8.2.5.tar.gz
+hash redis-8.0.6.tar.gz sha256 
6d0a9913887a4972536f9da226f1575859c34d86354129163260a5f9c6bd4229 
http://download.redis.io/releases/redis-8.0.6.tar.gz
+hash redis-7.4.8.tar.gz sha256 
f6773cb7d63be236c59c2917a82f1f08e47b77d89b2f0c9f53becb22b8ea4172 
http://download.redis.io/releases/redis-7.4.8.tar.gz
+hash redis-7.2.13.tar.gz sha256 
b3eeef15ea90a41c568f1f97a78d3370400baad55566869bbbf1af9f9106d85c 
http://download.redis.io/releases/redis-7.2.13.tar.gz
 

Reply via email to