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-05-06 19:17:49
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/redis (Old)
 and      /work/SRC/openSUSE:Factory/.redis.new.30200 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "redis"

Wed May  6 19:17:49 2026 rev:14 rq:1350996 version:8.6.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/redis/redis.changes      2026-03-27 
06:49:42.974487766 +0100
+++ /work/SRC/openSUSE:Factory/.redis.new.30200/redis.changes   2026-05-06 
19:18:34.686768610 +0200
@@ -1,0 +2,88 @@
+Tue May  5 14:08:33 UTC 2026 - Marcus Rueckert <[email protected]>
+
+- Updated to 8.6.3
+  - Security fixes
+    - (CVE-2026-23479) Use-After-Free in unblock client flow may
+      lead to Remote Code Execution.
+    - (CVE-2026-25243) Invalid memory access in RESTORE may lead to
+      Remote Code Execution
+    - (CVE-2026-23631) Lua Use-After-Free may lead to remote code
+      execution
+    - (CVE-2026-25588) Invalid memory access in RESTORE may lead to
+      Remote Code Execution (Time Series)
+    - (CVE-2026-25589) Invalid memory access in RESTORE may lead to
+      Remote Code Execution (Probabilistic)
+  - Bug fixes
+    - SUBSCRIBE, PSUBSCRIBE, SSUBSCRIBE: crash on OOM (RED-167788)
+    - CONFIG SET: some settings allow invalid characters
+      (RED-167787)
+    - SCRIPT DEBUG: potential crash on scripts (RED-175507)
+    - VADD: crash or buffer overflow on large REDUCE value
+      (RED-170921)
+    - VSET: crash on huge allocations (MOD-12678)
+    - Potential crash on disconnections and TLS failures (Time
+      Series) (MOD-14850)
+    - RediSearch/RediSearch#8745 Crash when many keys receive
+      expirations under heavy TTL activity (MOD-14500)
+    - RediSearch/RediSearch#8848 HNSW vector index memory growth
+      under high-churn workloads until shard restart (MOD-13761)
+    - RediSearch/RediSearch#8205, RediSearch/RediSearch#8259
+      FT.HYBRID VSIM RANGE + FILTER incorrectly returns zero
+      results (MOD-12370, MOD-13884)
+    - RediSearch/RediSearch#9182 FT.PROFILE HYBRID returns an empty
+      reply (MOD-14778)
+    - RediSearch/RediSearch#8129, RediSearch/RediSearch#8140
+      FT.PROFILE reports an incorrect shard total profile time
+      (MOD-13735, MOD-13181)
+    - RediSearch/RediSearch#9047 FT.PROFILE output is inconsistent
+      when a profiled value is missing (MOD-10560)
+    - RediSearch/RediSearch#8791 FT.EXPLAIN does not lock, causing
+      a race with concurrent index changes (MOD-14461)
+    - RediSearch/RediSearch#8382 Crash when indexing negative zero
+      (-0.0) (MOD-13904)
+    - RediSearch/RediSearch#8590 FILTER returns inconsistent
+      results with multiple indexes sharing field aliases
+      (MOD-14063)
+    - RediSearch/RediSearch#8660 FILTER behavior depends on
+      property order in the expression (MOD-14065)
+    - RediSearch/RediSearch#8593 Filter expressions are evaluated
+      for indexes that do not match the document type (MOD-14064)
+    - RediSearch/RediSearch#8591 Documents are inconsistently
+      included or excluded depending on the indexing path taken
+      (MOD-13948)
+    - RediSearch/RediSearch#8589 RENAME notification handler loads
+      the wrong key, causing stale index entries after a rename
+      (MOD-14328)
+    - RediSearch/RediSearch#9012 PERSIST and HPERSIST notifications
+      are not reflected in index expiration tracking (MOD-14800)
+    - RediSearch/RediSearch#9079 FT.SPELLCHECK treats PARAMS
+      placeholders as literal terms instead of resolving them
+      (MOD-10596)
+    - RediSearch/RediSearch#8462 GC out-of-memory on replica shards
+      leaves the replica in an inconsistent state (MOD-14066)
+    - RediSearch/RediSearch#9066 Race condition in FT.HYBRID causes
+      intermittent failures under concurrent hybrid query load
+      (MOD-14732)
+    - RediSearch/RediSearch#8109, RediSearch/RediSearch#8149
+      Configuration registration omits module parameters, causing
+      them to be unexposed or misapplied (RED-171841)
+    - RediSearch/RediSearch#9163 Crash on FT.SEARCH when topology
+      validation fails (for example, some nodes unreachable)
+      (MOD-14475)
+    - RediSearch/RediSearch#8395 FT.SEARCH fails with "Query
+      requires unavailable slots" after shard restart or failover
+      (MOD-13828)
+    - RediSearch/RediSearch#8451 FT.INFO-style output no longer
+      reports zero-index summary data when no indices exist
+      (MOD-14079)
+    - RediSearch/RediSearch#9078 FT.CREATE now rejects schema
+      definitions with invalid option combinations at creation time
+      (MOD-14655)
+    - RediSearch/RediSearch#8051, RediSearch/RediSearch#8114 Crash
+      diagnostics now include the IndexSpec of the index the
+      failing thread was working on (MOD-7574)
+  - Metrics
+    - RediSearch/RediSearch#8210, RediSearch/RediSearch#8231
+      FT.PROFILE: added queue time tracking (MOD-13602)
+
+-------------------------------------------------------------------

Old:
----
  redis-8.6.2.tar.gz

New:
----
  redis-8.6.3.tar.gz

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

Other differences:
------------------
++++++ redis.spec ++++++
--- /var/tmp/diff_new_pack.7Q0dHy/_old  2026-05-06 19:18:35.570805040 +0200
+++ /var/tmp/diff_new_pack.7Q0dHy/_new  2026-05-06 19:18:35.582805534 +0200
@@ -20,7 +20,7 @@
 %define _log_dir        %{_localstatedir}/log/%{name}
 %define _conf_dir       %{_sysconfdir}/%{name}
 Name:           redis
-Version:        8.6.2
+Version:        8.6.3
 Release:        0
 Summary:        Persistent key-value database
 License:        AGPL-3.0-only

++++++ redis-8.6.2.tar.gz -> redis-8.6.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/00-RELEASENOTES 
new/redis-8.6.3/00-RELEASENOTES
--- old/redis-8.6.2/00-RELEASENOTES     2026-03-24 13:22:41.000000000 +0100
+++ new/redis-8.6.3/00-RELEASENOTES     2026-05-05 15:23:21.000000000 +0200
@@ -21,6 +21,57 @@
 
 
 
================================================================================
+Redis 8.6.3    Released Tue 5 May 2026 16:00:00 IST
+================================================================================
+
+Update urgency: `SECURITY`: There are security fixes in the release.
+
+### Security fixes
+
+- (CVE-2026-23479) Use-After-Free in unblock client flow may lead to Remote 
Code Execution.
+- (CVE-2026-25243) Invalid memory access in `RESTORE` may lead to Remote Code 
Execution
+- (CVE-2026-23631) Lua Use-After-Free may lead to remote code execution
+- (CVE-2026-25588) Invalid memory access in `RESTORE` may lead to Remote Code 
Execution (Time Series)
+- (CVE-2026-25589) Invalid memory access in `RESTORE` may lead to Remote Code 
Execution (Probabilistic)
+
+### Bug fixes
+
+- `SUBSCRIBE`, `PSUBSCRIBE`, `SSUBSCRIBE`: crash on OOM (RED-167788)
+- `CONFIG SET`: some settings allow invalid characters (RED-167787)
+- `SCRIPT DEBUG`: potential crash on scripts (RED-175507)
+- `VADD`: crash or buffer overflow on large `REDUCE` value (RED-170921)
+- `VSET`: crash on huge allocations (MOD-12678)
+- Potential crash on disconnections and TLS failures (Time Series) (MOD-14850)
+- #Q8745 Crash when many keys receive expirations under heavy TTL activity 
(MOD-14500)
+- #Q8848 HNSW vector index memory growth under high-churn workloads until 
shard restart (MOD-13761)
+- #Q8205, #Q8259 `FT.HYBRID` `VSIM RANGE` + `FILTER` incorrectly returns zero 
results (MOD-12370, MOD-13884)
+- #Q9182 `FT.PROFILE HYBRID` returns an empty reply (MOD-14778)
+- #Q8129, #Q8140 `FT.PROFILE` reports an incorrect shard total profile time 
(MOD-13735, MOD-13181)
+- #Q9047 `FT.PROFILE` output is inconsistent when a profiled value is missing 
(MOD-10560)
+- #Q8791 `FT.EXPLAIN` does not lock, causing a race with concurrent index 
changes (MOD-14461)
+- #Q8382 Crash when indexing negative zero (-0.0) (MOD-13904)
+- #Q8590 `FILTER` returns inconsistent results with multiple indexes sharing 
field aliases (MOD-14063)
+- #Q8660 `FILTER` behavior depends on property order in the expression 
(MOD-14065)
+- #Q8593 Filter expressions are evaluated for indexes that do not match the 
document type (MOD-14064)
+- #Q8591 Documents are inconsistently included or excluded depending on the 
indexing path taken (MOD-13948)
+- #Q8589 `RENAME` notification handler loads the wrong key, causing stale 
index entries after a rename (MOD-14328)
+- #Q9012 `PERSIST` and `HPERSIST` notifications are not reflected in index 
expiration tracking (MOD-14800)
+- #Q9079 `FT.SPELLCHECK` treats `PARAMS` placeholders as literal terms instead 
of resolving them (MOD-10596)
+- #Q8462 GC out-of-memory on replica shards leaves the replica in an 
inconsistent state (MOD-14066)
+- #Q9066 Race condition in `FT.HYBRID` causes intermittent failures under 
concurrent hybrid query load (MOD-14732)
+- #Q8109, #Q8149 Configuration registration omits module parameters, causing 
them to be unexposed or misapplied (RED-171841)
+- #Q9163 Crash on `FT.SEARCH` when topology validation fails (for example, 
some nodes unreachable) (MOD-14475)
+- #Q8395 `FT.SEARCH` fails with "Query requires unavailable slots" after shard 
restart or failover (MOD-13828)
+- #Q8451 `FT.INFO`-style output no longer reports zero-index summary data when 
no indices exist (MOD-14079)
+- #Q9078 `FT.CREATE` now rejects schema definitions with invalid option 
combinations at creation time (MOD-14655)
+- #Q8051, #Q8114 Crash diagnostics now include the `IndexSpec` of the index 
the failing thread was working on (MOD-7574)
+
+### Metrics
+
+- #Q8210, #Q8231 `FT.PROFILE`: added queue time tracking (MOD-13602)
+
+
+================================================================================
 Redis 8.6.2    Released Tue 24 Mar 2026 12:00:00 IST
 
================================================================================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/modules/redisbloom/Makefile 
new/redis-8.6.3/modules/redisbloom/Makefile
--- old/redis-8.6.2/modules/redisbloom/Makefile 2026-03-24 13:22:41.000000000 
+0100
+++ new/redis-8.6.3/modules/redisbloom/Makefile 2026-05-05 15:23:21.000000000 
+0200
@@ -1,5 +1,5 @@
 SRC_DIR = src
-MODULE_VERSION = v8.6.0
+MODULE_VERSION = v8.6.2
 MODULE_REPO = https://github.com/redisbloom/redisbloom
 TARGET_MODULE = $(SRC_DIR)/bin/$(FULL_VARIANT)/redisbloom.so
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/modules/redisearch/Makefile 
new/redis-8.6.3/modules/redisearch/Makefile
--- old/redis-8.6.2/modules/redisearch/Makefile 2026-03-24 13:22:41.000000000 
+0100
+++ new/redis-8.6.3/modules/redisearch/Makefile 2026-05-05 15:23:21.000000000 
+0200
@@ -1,5 +1,5 @@
 SRC_DIR = src
-MODULE_VERSION = v8.6.0
+MODULE_VERSION = v8.6.7
 MODULE_REPO = https://github.com/redisearch/redisearch
 TARGET_MODULE = $(SRC_DIR)/bin/$(FULL_VARIANT)/search-community/redisearch.so
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/modules/redistimeseries/Makefile 
new/redis-8.6.3/modules/redistimeseries/Makefile
--- old/redis-8.6.2/modules/redistimeseries/Makefile    2026-03-24 
13:22:41.000000000 +0100
+++ new/redis-8.6.3/modules/redistimeseries/Makefile    2026-05-05 
15:23:21.000000000 +0200
@@ -1,5 +1,5 @@
 SRC_DIR = src
-MODULE_VERSION = v8.6.0
+MODULE_VERSION = v8.6.2
 MODULE_REPO = https://github.com/redistimeseries/redistimeseries
 TARGET_MODULE = $(SRC_DIR)/bin/$(FULL_VARIANT)/redistimeseries.so
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/redis-8.6.2/modules/vector-sets/tests/dimension_max_limit.py 
new/redis-8.6.3/modules/vector-sets/tests/dimension_max_limit.py
--- old/redis-8.6.2/modules/vector-sets/tests/dimension_max_limit.py    
1970-01-01 01:00:00.000000000 +0100
+++ new/redis-8.6.3/modules/vector-sets/tests/dimension_max_limit.py    
2026-05-05 15:23:21.000000000 +0200
@@ -0,0 +1,129 @@
+from test import TestCase, generate_random_vector
+import struct
+import redis.exceptions
+
+MAX_DIM = 65536
+
+
+class DimensionMaxLimitVaddAtLimit(TestCase):
+    def getname(self):
+        return "[regression] VADD VALUES dim == MAX_DIM accepted"
+
+    def estimated_runtime(self):
+        return 0.5
+
+    def test(self):
+        dim = MAX_DIM
+        vec = generate_random_vector(dim)
+
+        result = self.redis.execute_command(
+            'VADD', self.test_key,
+            'VALUES', dim,
+            *[str(x) for x in vec],
+            f"{self.test_key}:item:maxdim")
+        assert result == 1, "VADD with dimension at the limit should succeed"
+
+
+class DimensionMaxLimitVaddAboveLimit(TestCase):
+    def getname(self):
+        return "[regression] VADD VALUES dim > MAX_DIM rejected"
+
+    def estimated_runtime(self):
+        return 0.1
+
+    def test(self):
+        too_big_dim = MAX_DIM + 1
+        too_big_vec = generate_random_vector(16)
+        try:
+            self.redis.execute_command(
+                'VADD', self.test_key,
+                'VALUES', too_big_dim,
+                *[str(x) for x in too_big_vec],
+                f"{self.test_key}:item:toolarge")
+            assert False, "VADD with dimension above the limit should fail"
+        except redis.exceptions.ResponseError as e:
+            # parseVector returns NULL so caller uses the generic invalid spec 
error
+            assert "invalid vector specification" in str(e), (
+                f"Expected invalid vector specification error, got: {e}")
+
+
+class DimensionMaxLimitVsimAtLimit(TestCase):
+    def getname(self):
+        return "[regression] VSIM VALUES dim == MAX_DIM accepted"
+
+    def estimated_runtime(self):
+        return 0.5
+
+    def test(self):
+        # Insert a vector at the maximum allowed dimension, then query at the 
same dimension.
+        dim = MAX_DIM
+        base_vec = generate_random_vector(dim)
+
+        result = self.redis.execute_command(
+            'VADD', self.test_key,
+            'VALUES', dim,
+            *[str(x) for x in base_vec],
+            f"{self.test_key}:item:1")
+        assert result == 1, "VADD with dimension at the limit should succeed"
+
+        query = generate_random_vector(dim)
+        res = self.redis.execute_command(
+            'VSIM', self.test_key,
+            'VALUES', dim,
+            *[str(x) for x in query],
+            'COUNT', 1)
+        assert isinstance(res, list), "VSIM with dimension at the limit should 
return a list"
+
+
+class DimensionMaxLimitVsimAboveLimit(TestCase):
+    def getname(self):
+        return "[regression] VSIM VALUES dim > MAX_DIM rejected"
+
+    def estimated_runtime(self):
+        return 0.1
+
+    def test(self):
+        # Create a small index, then issue a VSIM with an over-limit dimension.
+        base_dim = 16
+        base_vec = generate_random_vector(base_dim)
+        result = self.redis.execute_command(
+            'VADD', self.test_key,
+            'VALUES', base_dim,
+            *[str(x) for x in base_vec],
+            f"{self.test_key}:item:1")
+        assert result == 1, "VADD with base_dim should succeed"
+
+        too_big_dim = MAX_DIM + 1
+        too_big_vec = generate_random_vector(16)
+        try:
+            self.redis.execute_command(
+                'VSIM', self.test_key,
+                'VALUES', too_big_dim,
+                *[str(x) for x in too_big_vec],
+                'COUNT', 1)
+            assert False, "VSIM with dimension above the limit should fail"
+        except redis.exceptions.ResponseError as e:
+            assert "invalid vector specification" in str(e), (
+                f"Expected invalid vector specification error in VSIM, got: 
{e}")
+
+
+class DimensionMaxLimitHugeDimension(TestCase):
+    def getname(self):
+        return "[regression] VADD VALUES absurdly large dim rejected"
+
+    def estimated_runtime(self):
+        return 0.1
+
+    def test(self):
+        # Extremely large dimension close to LLONG_MAX should also be rejected 
safely.
+        huge_dim = 9223372036854775807  # LLONG_MAX from the original report
+        try:
+            self.redis.execute_command(
+                'VADD', self.test_key,
+                'VALUES', huge_dim,
+                '0')  # Just a dummy value; parseVector should reject based on 
dimension alone
+            assert False, "VADD with absurdly large dimension should fail"
+        except redis.exceptions.ResponseError as e:
+            assert "invalid vector specification" in str(e), (
+                f"Expected invalid vector specification error for huge dim, 
got: {e}")
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/redis-8.6.2/modules/vector-sets/tests/dimension_validation.py 
new/redis-8.6.3/modules/vector-sets/tests/dimension_validation.py
--- old/redis-8.6.2/modules/vector-sets/tests/dimension_validation.py   
2026-03-24 13:22:41.000000000 +0100
+++ new/redis-8.6.3/modules/vector-sets/tests/dimension_validation.py   
2026-05-05 15:23:21.000000000 +0200
@@ -65,3 +65,33 @@
             assert False, "VSIM with wrong dimension should fail"
         except redis.exceptions.ResponseError as e:
             assert "Input dimension mismatch for projection" in str(e), 
f"Expected dimension mismatch error in VSIM, got: {e}"
+
+class ReduceDimConstraintValidation(TestCase):
+    def getname(self):
+        return "[regression] VADD enforces reduce_dim <= dim"
+
+    def estimated_runtime(self):
+        return 0.1
+
+    def test(self):
+        import struct
+
+        dim = 16
+        reduce_dim = dim + 1  # Intentionally larger than dim
+
+        # Build a simple FP32 vector of the given dimension.
+        vec = [0.0] * dim
+        vec_bytes = struct.pack(f'{dim}f', *vec)
+
+        try:
+            self.redis.execute_command(
+                'VADD', self.test_key,
+                'REDUCE', reduce_dim,
+                'FP32', vec_bytes,
+                f'{self.test_key}:item:reducemismatch')
+            assert False, "VADD with reduce_dim > dim should fail"
+        except redis.exceptions.ResponseError as e:
+            # Same generic validation error path as other vector spec problems.
+            assert "invalid vector specification" in str(e), (
+                f"Expected invalid vector error, got: {e}")
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/modules/vector-sets/vset.c 
new/redis-8.6.3/modules/vector-sets/vset.c
--- old/redis-8.6.2/modules/vector-sets/vset.c  2026-03-24 13:22:41.000000000 
+0100
+++ new/redis-8.6.3/modules/vector-sets/vset.c  2026-05-05 15:23:21.000000000 
+0200
@@ -134,6 +134,9 @@
 // Default num elements returned by VSIM.
 #define VSET_DEFAULT_COUNT 10
 
+// Maximum allowed vector dimension for input vectors and sets.
+#define VSET_MAX_VECTOR_DIM (1<<16)
+
 /* ========================== Internal data structure  ====================== 
*/
 
 /* Our abstract data type needs a dual representation similar to Redis
@@ -408,6 +411,7 @@
         // Must be 4 bytes per component.
         if (vec_raw_len % 4 || vec_raw_len < 4) return NULL;
         *dim = vec_raw_len/4;
+        if (*dim > VSET_MAX_VECTOR_DIM) return NULL;
 
         vec = RedisModule_Alloc(vec_raw_len);
         if (!vec) return NULL;
@@ -417,7 +421,7 @@
         if (argc < start_idx + 2) return NULL;  // Need at least the dimension.
         long long vdim; // Vector dimension passed by the user.
         if (RedisModule_StringToLongLong(argv[start_idx+1],&vdim)
-            != REDISMODULE_OK || vdim < 1) return NULL;
+            != REDISMODULE_OK || vdim < 1 || vdim > VSET_MAX_VECTOR_DIM) 
return NULL;
 
         // Check that all the arguments are available.
         if (argc < start_idx + 2 + vdim) return NULL;
@@ -441,6 +445,12 @@
         return NULL;  // Unknown format.
     }
 
+    // reduce_dim must be <= dim
+    if (reduce_dim && *reduce_dim && *reduce_dim > *dim) {
+        if (vec) RedisModule_Free(vec);
+        return NULL;
+    }
+
     if (consumed_args) *consumed_args = consumed;
     return vec;
 }
@@ -1960,6 +1970,15 @@
     uint32_t quant_type = hnsw_config & 0xff;
     uint32_t hnsw_m = (hnsw_config >> 8) & 0xffff;
 
+    /* Validate dimension loaded from RDB to enforce invariants and
+     * avoid absurd allocations or inconsistent state. */
+    if (dim == 0 || dim > VSET_MAX_VECTOR_DIM) {
+        RedisModule_LogIOError(rdb, "warning",
+            "Invalid vector dimension in RDB: dim=%u (max allowed %u)",
+            (unsigned)dim, (unsigned)VSET_MAX_VECTOR_DIM);
+        return NULL;
+    }
+
     /* Check that the quantization type is correct. Otherwise
      * return ASAP signaling the error. */
     if (quant_type != HNSW_QUANT_NONE &&
@@ -1981,14 +2000,44 @@
         uint32_t input_dim = RedisModule_LoadUnsigned(rdb);
         if (RedisModule_IsIOError(rdb)) goto ioerr;
         uint32_t output_dim = dim;
-        size_t matrix_size = sizeof(float) * input_dim * output_dim;
 
-        vset->proj_matrix = RedisModule_Alloc(matrix_size);
-        vset->proj_input_size = input_dim;
+        /* Sanity check projection dimensions. */
+        if (input_dim == 0 || output_dim == 0 || input_dim > 
VSET_MAX_VECTOR_DIM || output_dim > input_dim) {
+            RedisModule_LogIOError(rdb, "warning",
+                "Invalid projection matrix dimensions: input_dim=%u, 
output_dim=%u (max allowed %u)",
+                (unsigned)input_dim, (unsigned)output_dim,
+                (unsigned)VSET_MAX_VECTOR_DIM);
+            goto ioerr;
+        }
+
+        /* Check for overflow in matrix_size = sizeof(float) * input_dim * 
output_dim. */
+        #if SIZE_MAX == UINT32_MAX
+            uint64_t product = (uint64_t) output_dim * (uint64_t) input_dim * 
sizeof(float);
+            if (product > SIZE_MAX) {
+                RedisModule_LogIOError(rdb, "warning",
+                    "Projection matrix size overflow (output_dim too large): 
input_dim=%u, output_dim=%u",
+                    (unsigned)input_dim, (unsigned)output_dim);
+                goto ioerr;
+            }
+        #endif
 
-        // Load projection matrix as a binary blob
-        char *matrix_blob = RedisModule_LoadStringBuffer(rdb, NULL);
+        size_t matrix_size = sizeof(float) * (size_t)input_dim * 
(size_t)output_dim;
+
+        /* Load projection matrix as a binary blob and validate length. */
+        size_t blob_len = 0;
+        char *matrix_blob = RedisModule_LoadStringBuffer(rdb, &blob_len);
         if (matrix_blob == NULL) goto ioerr;
+
+        if (blob_len != matrix_size) {
+            RedisModule_LogIOError(rdb, "warning",
+                "Mismatching projection matrix length: expected=%zu, got=%zu",
+                matrix_size, blob_len);
+            RedisModule_Free(matrix_blob);
+            goto ioerr;
+        }
+
+        vset->proj_matrix = RedisModule_Alloc(matrix_size);
+        vset->proj_input_size = input_dim;
         memcpy(vset->proj_matrix, matrix_blob, matrix_size);
         RedisModule_Free(matrix_blob);
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/src/blocked.c 
new/redis-8.6.3/src/blocked.c
--- old/redis-8.6.2/src/blocked.c       2026-03-24 13:22:41.000000000 +0100
+++ new/redis-8.6.3/src/blocked.c       2026-05-05 15:23:21.000000000 +0200
@@ -691,7 +691,13 @@
         client *old_client = server.current_client;
         server.current_client = c;
         enterExecutionUnit(1, 0);
-        processCommandAndResetClient(c);
+        if (processCommandAndResetClient(c) == C_ERR) {
+            /* Client was freed during command processing, exit immediately */
+            exitExecutionUnit();
+            server.current_client = old_client;
+            return;
+        }
+
         if (!(c->flags & CLIENT_BLOCKED)) {
             if (c->flags & CLIENT_MODULE) {
                 moduleCallCommandUnblockedHandler(c);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/src/cluster.c 
new/redis-8.6.3/src/cluster.c
--- old/redis-8.6.2/src/cluster.c       2026-03-24 13:22:41.000000000 +0100
+++ new/redis-8.6.3/src/cluster.c       2026-05-05 15:23:21.000000000 +0200
@@ -805,7 +805,12 @@
 }
 
 int isValidAuxChar(int c) {
-    return isalnum(c) || (strchr("!#$%&()*+:;<>?@[]^{|}~", c) == NULL);
+    /* Reject control characters (0x00-0x1F and 0x7F). */
+    if (iscntrl(c)) {
+        return 0;
+    }
+    /* Reject forbidden characters including nodes.conf delimiters and special 
parsing characters */
+    return isalnum(c) || (strchr("!#$%&()*+:;<>?@[]^{|}~,= \"'\\", c) == NULL);
 }
 
 int isValidAuxString(char *s, unsigned int length) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/src/commands/psubscribe.json 
new/redis-8.6.3/src/commands/psubscribe.json
--- old/redis-8.6.2/src/commands/psubscribe.json        2026-03-24 
13:22:41.000000000 +0100
+++ new/redis-8.6.3/src/commands/psubscribe.json        2026-05-05 
15:23:21.000000000 +0200
@@ -11,7 +11,8 @@
             "NOSCRIPT",
             "LOADING",
             "STALE",
-            "SENTINEL"
+            "SENTINEL",
+            "DENYOOM"
         ],
         "arguments": [
             {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/src/commands/ssubscribe.json 
new/redis-8.6.3/src/commands/ssubscribe.json
--- old/redis-8.6.2/src/commands/ssubscribe.json        2026-03-24 
13:22:41.000000000 +0100
+++ new/redis-8.6.3/src/commands/ssubscribe.json        2026-05-05 
15:23:21.000000000 +0200
@@ -10,7 +10,8 @@
             "PUBSUB",
             "NOSCRIPT",
             "LOADING",
-            "STALE"
+            "STALE",
+            "DENYOOM"
         ],
         "arguments": [
             {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/src/commands/subscribe.json 
new/redis-8.6.3/src/commands/subscribe.json
--- old/redis-8.6.2/src/commands/subscribe.json 2026-03-24 13:22:41.000000000 
+0100
+++ new/redis-8.6.3/src/commands/subscribe.json 2026-05-05 15:23:21.000000000 
+0200
@@ -12,7 +12,8 @@
             "NOSCRIPT",
             "LOADING",
             "STALE",
-            "SENTINEL"
+            "SENTINEL",
+            "DENYOOM"
         ],
         "arguments": [
             {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/src/commands.def 
new/redis-8.6.3/src/commands.def
--- old/redis-8.6.2/src/commands.def    2026-03-24 13:22:41.000000000 +0100
+++ new/redis-8.6.3/src/commands.def    2026-05-05 15:23:21.000000000 +0200
@@ -11856,13 +11856,13 @@
 {MAKE_CMD("rpush","Appends one or more elements to a list. Creates the key if 
it doesn't exist.","O(1) for each element added, so O(N) to add N elements when 
the command is called with multiple 
arguments.","1.0.0",CMD_DOC_NONE,NULL,NULL,"list",COMMAND_GROUP_LIST,RPUSH_History,1,RPUSH_Tips,0,rpushCommand,-3,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_LIST,RPUSH_Keyspecs,1,NULL,2),.args=RPUSH_Args},
 {MAKE_CMD("rpushx","Appends an element to a list only when the list 
exists.","O(1) for each element added, so O(N) to add N elements when the 
command is called with multiple 
arguments.","2.2.0",CMD_DOC_NONE,NULL,NULL,"list",COMMAND_GROUP_LIST,RPUSHX_History,1,RPUSHX_Tips,0,rpushxCommand,-3,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_LIST,RPUSHX_Keyspecs,1,NULL,2),.args=RPUSHX_Args},
 /* pubsub */
-{MAKE_CMD("psubscribe","Listens for messages published to channels that match 
one or more patterns.","O(N) where N is the number of patterns to subscribe 
to.","2.0.0",CMD_DOC_NONE,NULL,NULL,"pubsub",COMMAND_GROUP_PUBSUB,PSUBSCRIBE_History,0,PSUBSCRIBE_Tips,0,psubscribeCommand,-2,CMD_PUBSUB|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,0,PSUBSCRIBE_Keyspecs,0,NULL,1),.args=PSUBSCRIBE_Args},
+{MAKE_CMD("psubscribe","Listens for messages published to channels that match 
one or more patterns.","O(N) where N is the number of patterns to subscribe 
to.","2.0.0",CMD_DOC_NONE,NULL,NULL,"pubsub",COMMAND_GROUP_PUBSUB,PSUBSCRIBE_History,0,PSUBSCRIBE_Tips,0,psubscribeCommand,-2,CMD_PUBSUB|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL|CMD_DENYOOM,0,PSUBSCRIBE_Keyspecs,0,NULL,1),.args=PSUBSCRIBE_Args},
 {MAKE_CMD("publish","Posts a message to a channel.","O(N+M) where N is the 
number of clients subscribed to the receiving channel and M is the total number 
of subscribed patterns (by any 
client).","2.0.0",CMD_DOC_NONE,NULL,NULL,"pubsub",COMMAND_GROUP_PUBSUB,PUBLISH_History,0,PUBLISH_Tips,0,publishCommand,3,CMD_PUBSUB|CMD_LOADING|CMD_STALE|CMD_FAST|CMD_MAY_REPLICATE|CMD_SENTINEL,0,PUBLISH_Keyspecs,0,NULL,2),.args=PUBLISH_Args},
 {MAKE_CMD("pubsub","A container for Pub/Sub commands.","Depends on 
subcommand.","2.8.0",CMD_DOC_NONE,NULL,NULL,"pubsub",COMMAND_GROUP_PUBSUB,PUBSUB_History,0,PUBSUB_Tips,0,NULL,-2,0,0,PUBSUB_Keyspecs,0,NULL,0),.subcommands=PUBSUB_Subcommands},
 {MAKE_CMD("punsubscribe","Stops listening to messages published to channels 
that match one or more patterns.","O(N) where N is the number of patterns to 
unsubscribe.","2.0.0",CMD_DOC_NONE,NULL,NULL,"pubsub",COMMAND_GROUP_PUBSUB,PUNSUBSCRIBE_History,0,PUNSUBSCRIBE_Tips,0,punsubscribeCommand,-1,CMD_PUBSUB|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,0,PUNSUBSCRIBE_Keyspecs,0,NULL,1),.args=PUNSUBSCRIBE_Args},
 {MAKE_CMD("spublish","Post a message to a shard channel","O(N) where N is the 
number of clients subscribed to the receiving shard 
channel.","7.0.0",CMD_DOC_NONE,NULL,NULL,"pubsub",COMMAND_GROUP_PUBSUB,SPUBLISH_History,0,SPUBLISH_Tips,0,spublishCommand,3,CMD_PUBSUB|CMD_LOADING|CMD_STALE|CMD_FAST|CMD_MAY_REPLICATE,0,SPUBLISH_Keyspecs,1,NULL,2),.args=SPUBLISH_Args},
-{MAKE_CMD("ssubscribe","Listens for messages published to shard 
channels.","O(N) where N is the number of shard channels to subscribe 
to.","7.0.0",CMD_DOC_NONE,NULL,NULL,"pubsub",COMMAND_GROUP_PUBSUB,SSUBSCRIBE_History,0,SSUBSCRIBE_Tips,0,ssubscribeCommand,-2,CMD_PUBSUB|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,0,SSUBSCRIBE_Keyspecs,1,NULL,1),.args=SSUBSCRIBE_Args},
-{MAKE_CMD("subscribe","Listens for messages published to channels.","O(N) 
where N is the number of channels to subscribe 
to.","2.0.0",CMD_DOC_NONE,NULL,NULL,"pubsub",COMMAND_GROUP_PUBSUB,SUBSCRIBE_History,0,SUBSCRIBE_Tips,0,subscribeCommand,-2,CMD_PUBSUB|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,0,SUBSCRIBE_Keyspecs,0,NULL,1),.args=SUBSCRIBE_Args},
+{MAKE_CMD("ssubscribe","Listens for messages published to shard 
channels.","O(N) where N is the number of shard channels to subscribe 
to.","7.0.0",CMD_DOC_NONE,NULL,NULL,"pubsub",COMMAND_GROUP_PUBSUB,SSUBSCRIBE_History,0,SSUBSCRIBE_Tips,0,ssubscribeCommand,-2,CMD_PUBSUB|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_DENYOOM,0,SSUBSCRIBE_Keyspecs,1,NULL,1),.args=SSUBSCRIBE_Args},
+{MAKE_CMD("subscribe","Listens for messages published to channels.","O(N) 
where N is the number of channels to subscribe 
to.","2.0.0",CMD_DOC_NONE,NULL,NULL,"pubsub",COMMAND_GROUP_PUBSUB,SUBSCRIBE_History,0,SUBSCRIBE_Tips,0,subscribeCommand,-2,CMD_PUBSUB|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL|CMD_DENYOOM,0,SUBSCRIBE_Keyspecs,0,NULL,1),.args=SUBSCRIBE_Args},
 {MAKE_CMD("sunsubscribe","Stops listening to messages posted to shard 
channels.","O(N) where N is the number of shard channels to 
unsubscribe.","7.0.0",CMD_DOC_NONE,NULL,NULL,"pubsub",COMMAND_GROUP_PUBSUB,SUNSUBSCRIBE_History,0,SUNSUBSCRIBE_Tips,0,sunsubscribeCommand,-1,CMD_PUBSUB|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,0,SUNSUBSCRIBE_Keyspecs,1,NULL,1),.args=SUNSUBSCRIBE_Args},
 {MAKE_CMD("unsubscribe","Stops listening to messages posted to 
channels.","O(N) where N is the number of channels to 
unsubscribe.","2.0.0",CMD_DOC_NONE,NULL,NULL,"pubsub",COMMAND_GROUP_PUBSUB,UNSUBSCRIBE_History,0,UNSUBSCRIBE_Tips,0,unsubscribeCommand,-1,CMD_PUBSUB|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,0,UNSUBSCRIBE_Keyspecs,0,NULL,1),.args=UNSUBSCRIBE_Args},
 /* scripting */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/src/config.c new/redis-8.6.3/src/config.c
--- old/redis-8.6.2/src/config.c        2026-03-24 13:22:41.000000000 +0100
+++ new/redis-8.6.3/src/config.c        2026-05-05 15:23:21.000000000 +0200
@@ -24,6 +24,7 @@
 #include <string.h>
 #include <locale.h>
 #include <ctype.h>
+#include <arpa/inet.h>
 
 /*-----------------------------------------------------------------------------
  * Config file name-value maps.
@@ -2452,6 +2453,23 @@
     return 1;
 }
 
+/* Validation function for cluster-announce-ip.
+ * Ensures the IP address is valid and rejects control characters. */
+static int isValidClusterAnnounceIp(char *val, const char **err) {
+    unsigned char buf[sizeof(struct in6_addr)];
+    /* Empty string is allowed - it will be converted to NULL by 
EMPTY_STRING_IS_NULL flag */
+    if (val[0] == '\0') {
+        return 1;
+    }
+
+    if (inet_pton(AF_INET, val, buf) != 1 &&
+        inet_pton(AF_INET6, val, buf) != 1) {
+        *err = "Cluster announce IP must be a valid IPv4 or IPv6 address";
+        return 0;
+    }
+    return 1;
+}
+
 /* Validate specified string is a valid proc-title-template */
 static int isValidProcTitleTemplate(char *val, const char **err) {
     if (!validateProcTitleTemplate(val)) {
@@ -3159,7 +3177,7 @@
     createStringConfig("pidfile", NULL, IMMUTABLE_CONFIG, 
EMPTY_STRING_IS_NULL, server.pidfile, NULL, NULL, NULL),
     createStringConfig("replica-announce-ip", "slave-announce-ip", 
MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.slave_announce_ip, NULL, NULL, 
NULL),
     createStringConfig("masteruser", NULL, MODIFIABLE_CONFIG | 
SENSITIVE_CONFIG, EMPTY_STRING_IS_NULL, server.masteruser, NULL, NULL, NULL),
-    createStringConfig("cluster-announce-ip", NULL, MODIFIABLE_CONFIG, 
EMPTY_STRING_IS_NULL, server.cluster_announce_ip, NULL, NULL, updateClusterIp),
+    createStringConfig("cluster-announce-ip", NULL, MODIFIABLE_CONFIG, 
EMPTY_STRING_IS_NULL, server.cluster_announce_ip, NULL, 
isValidClusterAnnounceIp, updateClusterIp),
     createStringConfig("cluster-config-file", NULL, IMMUTABLE_CONFIG, 
ALLOW_EMPTY_STRING, server.cluster_configfile, "nodes.conf", NULL, NULL),
     createStringConfig("cluster-announce-hostname", NULL, MODIFIABLE_CONFIG, 
EMPTY_STRING_IS_NULL, server.cluster_announce_hostname, NULL, 
isValidAnnouncedHostname, updateClusterHostname),
     createStringConfig("cluster-announce-human-nodename", NULL, 
MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, 
server.cluster_announce_human_nodename, NULL, isValidAnnouncedNodename, 
updateClusterHumanNodename),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/src/eval.c new/redis-8.6.3/src/eval.c
--- old/redis-8.6.2/src/eval.c  2026-03-24 13:22:41.000000000 +0100
+++ new/redis-8.6.3/src/eval.c  2026-05-05 15:23:21.000000000 +0200
@@ -1502,7 +1502,9 @@
     sdsfree(code);
     sdsfree(expr);
     if (lua_pcall(lua,0,1,0)) {
-        ldbLog(sdscatfmt(sdsempty(),"<error> %s",lua_tostring(lua,-1)));
+        const char *err = lua_tostring(lua,-1);
+        ldbLog(sdscatfmt(sdsempty(),"<error> %s",
+            err ? err : "(error object is not a string)"));
         lua_pop(lua,1);
         return;
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/src/rdb.c new/redis-8.6.3/src/rdb.c
--- old/redis-8.6.2/src/rdb.c   2026-03-24 13:22:41.000000000 +0100
+++ new/redis-8.6.3/src/rdb.c   2026-05-05 15:23:21.000000000 +0200
@@ -2834,11 +2834,12 @@
 
                         /* search for duplicate records */
                         sds field = sdstrynewlen(fstr, flen);
-                        if (!field || dictAdd(dupSearchDict, field, NULL) != 
DICT_OK ||
-                            !lpSafeToAdd(lp, (size_t)flen + vlen)) {
+                        if (!field || !lpSafeToAdd(lp, (size_t)flen + vlen) ||
+                            dictAdd(dupSearchDict, field, NULL) != DICT_OK) {
                             rdbReportCorruptRDB("Hash zipmap with dup 
elements, or big length (%u)", flen);
                             dictRelease(dupSearchDict);
                             sdsfree(field);
+                            lpFree(lp);
                             zfree(encoded);
                             o->ptr = NULL;
                             decrRefCount(o);
@@ -3335,7 +3336,6 @@
                         rdbReportCorruptRDB("Duplicated consumer PEL entry "
                                                 " loading a stream consumer "
                                                 "group");
-                        streamFreeNACK(s, nack);
                         decrRefCount(o);
                         return NULL;
                     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/src/replication.c 
new/redis-8.6.3/src/replication.c
--- old/redis-8.6.2/src/replication.c   2026-03-24 13:22:41.000000000 +0100
+++ new/redis-8.6.3/src/replication.c   2026-05-05 15:23:21.000000000 +0200
@@ -2197,6 +2197,11 @@
 /* Asynchronously read the SYNC payload we receive from a master */
 #define REPL_MAX_WRITTEN_BEFORE_FSYNC (1024*1024*8) /* 8 MB */
 void readSyncBulkPayload(connection *conn) {
+    /* During full sync, the functions engine is freed right before loading
+     * the RDB. To avoid this happening while a function is still running,
+     * delay full sync processing until it finishes. */
+    if (isInsideYieldingLongCommand()) return;
+
     char buf[PROTO_IOBUF_LEN];
     ssize_t nread, readlen, nwritten;
     int use_diskless_load = useDisklessLoad();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/src/sds.c new/redis-8.6.3/src/sds.c
--- old/redis-8.6.2/src/sds.c   2026-03-24 13:22:41.000000000 +0100
+++ new/redis-8.6.3/src/sds.c   2026-05-05 15:23:21.000000000 +0200
@@ -105,7 +105,14 @@
     int hdrlen = sdsHdrSize(type);
     size_t bufsize;
 
-    assert(initlen + hdrlen + 1 > initlen); /* Catch size_t overflow */
+    if (trymalloc) {
+        /* protect against size_t overflow */
+        if (initlen + hdrlen + 1 <= initlen) 
+            return NULL;
+    } else {
+        assert(initlen + hdrlen + 1 > initlen); /* Catch size_t overflow */
+    }
+    
     sh = trymalloc?
         s_trymalloc_usable(hdrlen+initlen+1, &bufsize) :
         s_malloc_usable(hdrlen+initlen+1, &bufsize);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/src/version.h 
new/redis-8.6.3/src/version.h
--- old/redis-8.6.2/src/version.h       2026-03-24 13:22:41.000000000 +0100
+++ new/redis-8.6.3/src/version.h       2026-05-05 15:23:21.000000000 +0200
@@ -1,2 +1,2 @@
-#define REDIS_VERSION "8.6.2"
-#define REDIS_VERSION_NUM 0x00080602
+#define REDIS_VERSION "8.6.3"
+#define REDIS_VERSION_NUM 0x00080603
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/src/zipmap.c new/redis-8.6.3/src/zipmap.c
--- old/redis-8.6.2/src/zipmap.c        2026-03-24 13:22:41.000000000 +0100
+++ new/redis-8.6.3/src/zipmap.c        2026-05-05 15:23:21.000000000 +0200
@@ -387,6 +387,10 @@
 
         /* read the field name length */
         l = zipmapDecodeLength(p);
+        /* Sanity check: length < 254 must be encoded in 1 byte, not 5 bytes */
+        if (l < ZIPMAP_BIGLEN && s != 1)
+            return 0;
+
         p += s; /* skip the encoded field size */
         p += l; /* skip the field */
 
@@ -402,6 +406,9 @@
 
         /* read the value length */
         l = zipmapDecodeLength(p);
+        /* Sanity check: length < 254 must be encoded in 1 byte, not 5 bytes */
+        if (l < ZIPMAP_BIGLEN && s != 1)
+            return 0;
         p += s; /* skip the encoded value size*/
         e = *p++; /* skip the encoded free space (always encoded in one byte) 
*/
         p += l+e; /* skip the value and free space */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/tests/integration/corrupt-dump.tcl 
new/redis-8.6.3/tests/integration/corrupt-dump.tcl
--- old/redis-8.6.2/tests/integration/corrupt-dump.tcl  2026-03-24 
13:22:41.000000000 +0100
+++ new/redis-8.6.3/tests/integration/corrupt-dump.tcl  2026-05-05 
15:23:21.000000000 +0200
@@ -965,6 +965,89 @@
     }
 }
 
+test {corrupt payload: zipmap - element wouldn't fit in listpack} {
+    # Redis converts legacy zipmap encoded hashes to listpacks.
+    # This test creates a zipmap entry with a 1GB value which cannot
+    # fit into a listpack and verifies that RESTORE fails.
+
+    start_server [list overrides [list loglevel verbose use-exit-on-panic yes 
crash-memcheck-enabled no proto-max-bulk-len 2147483648 
client-query-buffer-limit 2147483648]] {
+        proc zipmap_encode_len {len} {
+            if {$len < 254} {
+                return [binary format c $len]
+            } else {
+                return [binary format ci 254 $len]
+            }
+        }
+        r config set sanitize-dump-payload no
+
+        # Generates Zipmap with 1GB value - should fail lpSafeToAdd check
+        set val_len [expr {1024 * 1024 * 1024 + 1}]
+
+        # Zipmap has 1 element
+        set zm [binary format c 1]
+        # Field is 1 byte long
+        append zm [zipmap_encode_len 1]
+        append zm "k"
+        # Value is 1GB long
+        append zm [zipmap_encode_len $val_len]
+        append zm [binary format c 0]
+        append zm [string repeat "A" $val_len]
+        # ZIPMAP_END marker
+        append zm [binary format c 255]
+        # Prepend RDB header
+        set zm_len [string length $zm]
+        set rdb_len [binary format cI 0x80 $zm_len]
+        set dump [binary format c 9]
+        append dump $rdb_len
+        append dump $zm
+        append dump [binary format s 9]
+        append dump [binary format w 0]
+
+        catch {r RESTORE _hash 0 $dump} err
+        assert_match "*Bad data format*" $err
+    }
+} {} {large-memory}
+
+test {corrupt payload: zipmap - 5 bytes length encoding for a small field} {
+    start_server [list overrides [list loglevel verbose use-exit-on-panic yes 
crash-memcheck-enabled no]] {
+        catch {
+            r restore key 0 
"\x09\x11\x01\xfe\x04\x00\x00\x00\x01\x00\xff\x00\x04\x00\x76\x61\x6c\x31\xff\x09\x00\xf9\xd5\xa4\xf7\x7d\x00\x3f\x1b"
+        } err
+        assert_match "*Bad data format*" $err
+        verify_log_message 0 "*integrity check failed*" 0
+    }
+}
+
+test {corrupt payload: zipmap - 5 bytes length encoding for a small value} {
+    start_server [list overrides [list loglevel verbose use-exit-on-panic yes 
crash-memcheck-enabled no]] {
+        catch {
+            r restore key 0 
"\x09\x0e\x01\x01\x6b\xfe\x04\x00\x00\x00\x00\x76\x61\x6c\x31\xff\x09\x00\xd0\xf9\xe4\x1d\xe4\xfb\x11\x4c"
+        } err
+        assert_match "*Bad data format*" $err
+        verify_log_message 0 "*integrity check failed*" 0
+    }
+}
+
+test {corrupt payload: zipmap - 5 bytes length encoding and a huge field} {
+    start_server [list overrides [list loglevel verbose use-exit-on-panic yes 
crash-memcheck-enabled no] ] {
+        catch {
+            r restore key 0 
"\x09\x41\x15\x02\x04\x6b\x65\x79\x31\x04\x00\x76\x61\x6c\x31\xfe\x04\x00\x00\x00\xfe\xff\xff\xff\xfd\x00\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42
 
\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\xff\x09\x00\x54\x2f\x0a\xca\x4e\x5c\x49\x9f"
+        } err
+        assert_match "*Bad data format*" $err
+        verify_log_message 0 "*integrity check failed*" 0
+    }
+}
+
+test {corrupt payload: stream - duplicated consumer PEL entry} {
+    start_server [list overrides [list loglevel verbose use-exit-on-panic yes 
crash-memcheck-enabled no] ] {
+        catch {
+            r restore key 0 
"\x15\x01\x10\x00\x00\x01\x9b\x0d\x56\xa9\xb7\x00\x00\x00\x00\x00\x00\x00\x00\xc3\x39\x40\x42\x15\x42\x00\x00\x00\x11\x00\x02\x01\x00\x01\x01\x01\x86\x66\x69\x65\x6c\x64\x31\x07\x00\x01\x40\x0f\x0a\x00\x01\x86\x76\x61\x6c\x75\x65\x31\x07\x04\x20\x0b\x02\xcd\xd9\x02\xe0\x01\x22\x01\x32\x07\x80\x1a\x04\x32\x07\x06\x01\xff\x02\x81\x00\x00\x01\x9b\x0d\x56\xb7\x90\x00\x81\x00\x00\x01\x9b\x0d\x56\xa9\xb7\x00\x00\x00\x02\x01\x07\x6d\x79\x67\x72\x6f\x75\x70\x81\x00\x00\x01\x9b\x0d\x56\xb7\x90\x00\x02\x02\x00\x00\x01\x9b\x0d\x56\xa9\xb7\x00\x00\x00\x00\x00\x00\x00\x00\x80\xd9\x56\x0d\x9b\x01\x00\x00\x01\x00\x00\x01\x9b\x0d\x56\xb7\x90\x00\x00\x00\x00\x00\x00\x00\x00\x80\xd9\x56\x0d\x9b\x01\x00\x00\x01\x01\x09\x63\x6f\x6e\x73\x75\x6d\x65\x72\x31\x80\xd9\x56\x0d\x9b\x01\x00\x00\x80\xd9\x56\x0d\x9b\x01\x00\x00\x02\x00\x00\x01\x9b\x0d\x56\xa9\xb7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x9b\x0d\x56\xa9\xb7\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00
 \x00\x00\x00\x09\x00\x4b\xe0\x99\x30\x67\x4d\xe5\x87"
+        } err
+        assert_match "*Bad data format*" $err
+        verify_log_message 0 "*Duplicated consumer PEL entry*" 0
+    }
+}
+
 
 } ;# tags
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/tests/integration/replication.tcl 
new/redis-8.6.3/tests/integration/replication.tcl
--- old/redis-8.6.2/tests/integration/replication.tcl   2026-03-24 
13:22:41.000000000 +0100
+++ new/redis-8.6.3/tests/integration/replication.tcl   2026-05-05 
15:23:21.000000000 +0200
@@ -1872,3 +1872,80 @@
         }
     }
 }
+
+# Fullsync should not free the functions lib ctx while the replica has 
+# a timed out function that is still running.
+foreach type {script function} {
+    start_server {tags {"repl external:skip"}} {
+        start_server {} {
+            set master [srv -1 client]
+            set master_host [srv -1 host]
+            set master_port [srv -1 port]
+            set replica [srv 0 client]
+
+            test "Fullsync should not free scripting engine on a replica while 
a $type is running" {
+                $master config set repl-diskless-sync yes
+                $master config set repl-diskless-sync-delay 0
+                # Set small client output buffer limit to trigger fullsync 
quickly
+                $master config set client-output-buffer-limit "replica 1k 1k 0"
+                $replica config set repl-diskless-load yes
+                $replica config set busy-reply-threshold 1 ;# script timeout 
in 1 ms
+
+                # Load function
+                if {$type eq "function"} {
+                    $master function load replace {#!lua name=blocklib
+                        redis.register_function{
+                            function_name='blockfunc',
+                            callback=function() while true do end end,
+                            flags={'no-writes'}
+                        }
+                    }
+                }
+
+                # Start replication
+                $replica replicaof $master_host $master_port
+                wait_for_sync $replica
+
+                # Run the blocking script on replica
+                set rd [redis_deferring_client]
+                if {$type eq "script"} {
+                    $rd eval {while true do end} 0
+                } else {
+                    $rd fcall_ro blockfunc 0
+                }
+
+                # Verify replica replies with BUSY
+                wait_for_condition 50 100 {
+                    [catch {$replica ping} e] == 1 && [string match {*BUSY*} 
$e]
+                } else {
+                    fail "$type didn't become busy"
+                }
+
+                # Fills client output buffer and triggers fullsync
+                populate 5 bigkey 1000000 -1
+                wait_for_condition 50 100 {
+                    [s -1 sync_full] >= 2
+                } else {
+                    fail "Fullsync was not triggered"
+                }
+                
+                # Verify replica is still running the function
+                after 1000
+                catch {$replica ping} e
+                assert_match {*BUSY*} $e "replica should still reply with BUSY"
+
+                if {$type eq "script"} {
+                    $replica script kill
+                } else {
+                    $replica function kill
+                }
+
+                # Verify replica is responsive again
+                catch {$rd read} result
+                $rd close
+                wait_for_sync $replica
+                assert_equal [$replica ping] "PONG"
+            }
+        }
+    }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/tests/unit/client-eviction.tcl 
new/redis-8.6.3/tests/unit/client-eviction.tcl
--- old/redis-8.6.2/tests/unit/client-eviction.tcl      2026-03-24 
13:22:41.000000000 +0100
+++ new/redis-8.6.3/tests/unit/client-eviction.tcl      2026-05-05 
15:23:21.000000000 +0200
@@ -619,5 +619,34 @@
     }
 }
 
+start_server {} {
+    r flushall
+    r client no-evict on
+    r config set maxmemory-clients 0
+
+    test "Verify blocked client eviction during unblock does not cause 
use-after-free" {
+        # Create a deferring client that will be blocked on stream
+        # Use a long stream name to make client memory usage exceed 200000 
bytes
+        set rd [redis_deferring_client]
+        $rd XREAD BLOCK 0 STREAMS mystream stream_[string repeat x 200000] $ $
+
+        # Wait for the client to be blocked
+        wait_for_condition 50 100 {
+            [s blocked_clients] eq {1}
+        } else {
+            fail "Client was not blocked"
+        }
+
+        # Now lower MAXMEMORY-CLIENTS to a low value and use
+        # XADD to unblock the blocked client, triggering eviction.
+        r MULTI
+        r CONFIG SET MAXMEMORY-CLIENTS 100000 ;# Put in MULTI to defer blocked 
client eviction until after EXEC
+        r XADD mystream * field val
+        r EXEC
+        r PING
+        $rd close
+    }
+}
+
 } ;# tags
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/redis-8.6.2/tests/unit/cluster/announced-endpoints.tcl 
new/redis-8.6.3/tests/unit/cluster/announced-endpoints.tcl
--- old/redis-8.6.2/tests/unit/cluster/announced-endpoints.tcl  2026-03-24 
13:22:41.000000000 +0100
+++ new/redis-8.6.3/tests/unit/cluster/announced-endpoints.tcl  2026-05-05 
15:23:21.000000000 +0200
@@ -72,4 +72,88 @@
             fail "Cluster announced port was not updated in cluster slots"
         }
     }
+
+    # Tests for cluster-announce-ip validation
+    test "cluster-announce-ip validation" {
+        catch {R 0 config set cluster-announce-ip "192.168.1.100\nnext"} err
+        assert_match "*valid IPv4 or IPv6*" $err
+
+        catch {R 0 config set cluster-announce-ip "10.0.0.1\ttab"} err
+        assert_match "*valid IPv4 or IPv6*" $err
+
+        catch {R 0 config set cluster-announce-ip "1.2.3.4\r\n"} err
+        assert_match "*valid IPv4 or IPv6*" $err
+
+        catch {R 0 config set cluster-announce-ip "redis-node-1.example.com"} 
err
+        assert_match "*valid IPv4 or IPv6*" $err
+
+        catch {R 0 config set cluster-announce-ip "192.168.1"} err
+        assert_match "*valid IPv4 or IPv6*" $err
+
+        # Accept valid IPv4
+        R 0 config set cluster-announce-ip "192.168.1.100"
+        assert_equal "192.168.1.100" [lindex [R 0 config get 
cluster-announce-ip] 1]
+
+        # Accept valid IPv6
+        R 0 config set cluster-announce-ip "2001:db8::1"
+        assert_equal "2001:db8::1" [lindex [R 0 config get 
cluster-announce-ip] 1]
+
+        # Can be cleared
+        R 0 config set cluster-announce-ip ""
+        assert_equal "" [lindex [R 0 config get cluster-announce-ip] 1]
+    }
+
+    # Tests for cluster-announce-human-nodename validation
+    test "cluster-announce-human-nodename validation" {
+        # Reject control characters
+        catch {R 0 config set cluster-announce-human-nodename "badchar\nnext"} 
err
+        assert_match "*invalid character*" $err
+
+        catch {R 0 config set cluster-announce-human-nodename "bad\ttab"} err
+        assert_match "*invalid character*" $err
+
+        catch {R 0 config set cluster-announce-human-nodename "bad\r\nline"} 
err
+        assert_match "*invalid character*" $err
+
+        # Reject delimiter characters (comma, equals, space)
+        catch {R 0 config set cluster-announce-human-nodename "bad,comma"} err
+        assert_match "*invalid character*" $err
+
+        catch {R 0 config set cluster-announce-human-nodename "bad=equals"} err
+        assert_match "*invalid character*" $err
+
+        catch {R 0 config set cluster-announce-human-nodename "bad space"} err
+        assert_match "*invalid character*" $err
+
+        # Reject quote characters (double quote, single quote, backslash)
+        catch {R 0 config set cluster-announce-human-nodename "bad\"quote"} err
+        assert_match "*invalid character*" $err
+
+        catch {R 0 config set cluster-announce-human-nodename "bad'quote"} err
+        assert_match "*invalid character*" $err
+
+        catch {R 0 config set cluster-announce-human-nodename "bad\\slash"} err
+        assert_match "*invalid character*" $err
+
+        # Accept valid names
+        R 0 config set cluster-announce-human-nodename "my-redis-node-1"
+        assert_equal "my-redis-node-1" [lindex [R 0 config get 
cluster-announce-human-nodename] 1]
+    }
+
+    # DoS prevention test: verify server can restart after CLUSTER SAVECONFIG
+    test "cluster-announce-ip persists correctly with CLUSTER SAVECONFIG" {
+        R 0 config set cluster-announce-ip "192.168.1.100"
+        R 0 cluster saveconfig
+
+        # Verify the IP appears in CLUSTER NODES output
+        assert_match "*192.168.1.100*" [R 0 cluster nodes]
+    }
+
+    test "cluster-announce-human-nodename persists correctly with CLUSTER 
SAVECONFIG" {
+        R 0 config set cluster-announce-human-nodename "production-node-1"
+        R 0 cluster saveconfig
+
+        # Verify the nodename is set correctly
+        assert_equal "production-node-1" [lindex [R 0 config get 
cluster-announce-human-nodename] 1]
+    }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/tests/unit/dump.tcl 
new/redis-8.6.3/tests/unit/dump.tcl
--- old/redis-8.6.2/tests/unit/dump.tcl 2026-03-24 13:22:41.000000000 +0100
+++ new/redis-8.6.3/tests/unit/dump.tcl 2026-05-05 15:23:21.000000000 +0200
@@ -158,6 +158,19 @@
         close_replication_stream $repl
     } {} {needs:repl}
 
+    test {RESTORE fail with invalid payload size} {
+        # Payload with mismatched size: claims 0xFFFFFFFFFFFFFFF7 bytes (max 
uint64 - 8) but provides no data
+        # \x00 = String type
+        # \x81 = 64-bit length marker
+        # \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xF7 = 18446744073709551607 in big-endian
+        # \x0c\x00 = RDB version
+        # \x00... = fake CRC64
+        set encoded 
"\x00\x81\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xF7\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+        r del test
+        catch {r restore test 0 $encoded} e
+        set e
+    } {*Bad data format*}
+
     test {DUMP of non existing key returns nil} {
         r dump nonexisting_key
     } {}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-8.6.2/tests/unit/pubsub.tcl 
new/redis-8.6.3/tests/unit/pubsub.tcl
--- old/redis-8.6.2/tests/unit/pubsub.tcl       2026-03-24 13:22:41.000000000 
+0100
+++ new/redis-8.6.3/tests/unit/pubsub.tcl       2026-05-05 15:23:21.000000000 
+0200
@@ -1012,5 +1012,134 @@
         assert_equal [r publish foo vaz] {1}
         assert_equal [r read] {message foo vaz}
     } {} {resp3}
+}
+
+start_server {tags {"pubsub network"}} {
+    # Helper proc for tests that subscribe multiple times until hitting OOM
+    proc test_subscribe_oom_loop {cmd description clients} {
+        test "$cmd $description fails with OOM when memory limit exceeded" {
+            # Set 10MB memory limit
+            r config set maxmemory 10485760
+            r config set maxmemory-policy noeviction
+            
+            # Create clients
+            if {$clients == 1} {
+                set rd [redis_deferring_client]
+            } else {
+                set rd1 [redis_deferring_client]
+                set rd2 [redis_deferring_client]
+            }
+            
+            set base_str [string repeat "a" 2048]
+            set success_count 0
+            set oom_occurred 0
+            
+            # Try to subscribe until we hit OOM
+            for {set i 0} {$i < 5000} {incr i} {
+                # Select client
+                if {$clients == 1} {
+                    set client $rd
+                } else {
+                    set client [expr {$i % 2 ? $rd1 : $rd2}]
+                }
+                
+                # Build channel/pattern name
+                if {$cmd eq "psubscribe"} {
+                    set channel_name "${base_str}${i}*"
+                } else {
+                    set channel_name "${base_str}${i}"
+                }
+                
+                $client $cmd $channel_name
+                if {[catch {$client read} err]} {
+                    if {[string match "*OOM command not allowed*" $err]} {
+                        set oom_occurred 1
+                        break
+                    }
+                    error "Unexpected error: $err"
+                }
+                incr success_count
+            }
+            
+            # Verify we had at least one success and hit OOM
+            assert {$success_count > 10}
+            assert {$oom_occurred == 1}
+            
+            # Close clients
+            if {$clients == 1} {
+                $rd close
+            } else {
+                $rd1 close
+                $rd2 close
+            }
+        }
+    }
+
+    # Helper proc for tests with single large channel that immediately fails
+    proc test_subscribe_large_channel_oom {cmd channel_type} {
+        test "$cmd with large $channel_type name fails due to OOM" {
+            # Set maxmemory to 2MB
+            r config set maxmemory 2097152
+            r config set maxmemory-policy noeviction
+            
+            # Create large channel/pattern name: 2MB
+            set channel_name [string repeat "a" 2097152]
+            
+            # Create a single pubsub client
+            set rd [redis_deferring_client]
+            
+            # Subscribe should fail with OOM error
+            $rd $cmd $channel_name
+            assert_error "*OOM command not allowed when used memory > 
'maxmemory'*" {$rd read}
+            
+            # Cleanup
+            $rd close
+        }
+    }
+
+    # Helper proc for tests with small success then large failure
+    proc test_subscribe_small_then_large_oom {cmd channel_type} {
+        test "$cmd succeeds with small $channel_type but fails with large 
$channel_type due to OOM" {
+            # Set maxmemory to 5MB
+            r config set maxmemory 5242880
+            r config set maxmemory-policy noeviction
+            
+            # Create channel names: first 10KB, second 5MB
+            set channel1 [string repeat "a" 10240]
+            set channel2 [string repeat "b" 5242880]
+            
+            # Create a single pubsub client
+            set rd [redis_deferring_client]
+            
+            # First subscribe should succeed (10KB)
+            $rd $cmd $channel1
+            set reply1 [$rd read]
+            assert_equal [list $cmd] [lindex $reply1 0]
+            
+            # Second subscribe should fail with OOM error (5MB exceeds limit)
+            $rd $cmd $channel2
+            assert_error "*OOM command not allowed when used memory > 
'maxmemory'*" {$rd read}
+            
+            # Cleanup
+            $rd close
+        }
+    }
+
+    # Multiple subscriptions until OOM tests
+    test_subscribe_oom_loop "subscribe" "" 1
+    test_subscribe_oom_loop "ssubscribe" "" 1
+    test_subscribe_oom_loop "psubscribe" "" 1
+    test_subscribe_oom_loop "subscribe" "with 2 clients" 2
+    test_subscribe_oom_loop "ssubscribe" "with 2 clients" 2
+    test_subscribe_oom_loop "psubscribe" "with 2 clients" 2
+
+    # Single large channel immediate OOM tests
+    test_subscribe_large_channel_oom "subscribe" "channel"
+    test_subscribe_large_channel_oom "psubscribe" "pattern"
+    test_subscribe_large_channel_oom "ssubscribe" "shard channel"
 
+    # Small success then large failure tests
+    test_subscribe_small_then_large_oom "subscribe" "channel"
+    test_subscribe_small_then_large_oom "psubscribe" "pattern"
+    test_subscribe_small_then_large_oom "ssubscribe" "channel"
 }

++++++ redis.hashes ++++++
--- /var/tmp/diff_new_pack.7Q0dHy/_old  2026-05-06 19:18:37.302876416 +0200
+++ /var/tmp/diff_new_pack.7Q0dHy/_new  2026-05-06 19:18:37.306876581 +0200
@@ -221,4 +221,10 @@
 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
 hash redis-8.6.2.tar.gz sha256 
cea46526594fe05f05b9ff733179eb1263deccf4269059cf081fdef222634c88 
http://download.redis.io/releases/redis-8.6.2.tar.gz
+hash redis-6.2.22.tar.gz sha256 
3ce191a727505b2d711bb45cfde8d9eeab1e061bdc0e5cb56a50201069a9729d 
http://download.redis.io/releases/redis-6.2.22.tar.gz
+hash redis-7.2.14.tar.gz sha256 
21326da3f66c0aead4c8204c0ac52ff905337a77cadd169f75ac22835ea30025 
http://download.redis.io/releases/redis-7.2.14.tar.gz
+hash redis-7.4.9.tar.gz sha256 
a71a67b47b2705d3448f0400573e3ad5c4c9f8c18236f426dc6acc7284bf42ad 
http://download.redis.io/releases/redis-7.4.9.tar.gz
+hash redis-8.2.6.tar.gz sha256 
78dd7326c5c959202c6c3849d3ea9c61896d78d647c20f6542b52c0917f96eac 
http://download.redis.io/releases/redis-8.2.6.tar.gz
+hash redis-8.4.3.tar.gz sha256 
aab9cc0f268354813d77ac29ae4fe86646f60590a21ea96a8d8caff38bd2efaa 
http://download.redis.io/releases/redis-8.4.3.tar.gz
+hash redis-8.6.3.tar.gz sha256 
9f54d4458c52be5472cdd1347d737f1d488b520fc3d0911cba47302de8d836e2 
http://download.redis.io/releases/redis-8.6.3.tar.gz
 

Reply via email to