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
