Skip to content

Commit 0802fcd

Browse files
azurelinux-securityKanishk Bansaljslobodzian
authored
[AutoPR- Security] Patch redis for CVE-2025-32023 (microsoft#14236)
Signed-off-by: Kanishk Bansal <[email protected]> Co-authored-by: Kanishk Bansal <[email protected]> Co-authored-by: jslobodzian <[email protected]>
1 parent 7f9245b commit 0802fcd

File tree

2 files changed

+217
-1
lines changed

2 files changed

+217
-1
lines changed

SPECS/redis/CVE-2025-32023.patch

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
From 4faf8424d0dddb95792b7111cfd1b8f87f91f111 Mon Sep 17 00:00:00 2001
2+
From: Azure Linux Security Servicing Account
3+
4+
Date: Wed, 9 Jul 2025 07:19:35 +0000
5+
Subject: [PATCH] Fix CVE CVE-2025-32023 in redis
6+
7+
Upstream Patch Reference: https://github.com/redis/redis/commit/50188747cbfe43528d2719399a2a3c9599169445.diff
8+
---
9+
10+
src/hyperloglog.c | 47 +++++++++++++++++++++++++++++++----
11+
tests/unit/hyperloglog.tcl | 51 ++++++++++++++++++++++++++++++++++++++
12+
2 files changed, 93 insertions(+), 5 deletions(-)
13+
14+
diff --git a/src/hyperloglog.c b/src/hyperloglog.c
15+
index 2f8c02e2cf2..d6a87822d19 100644
16+
--- a/src/hyperloglog.c
17+
+++ b/src/hyperloglog.c
18+
@@ -579,6 +579,7 @@ int hllSparseToDense(robj *o) {
19+
struct hllhdr *hdr, *oldhdr = (struct hllhdr*)sparse;
20+
int idx = 0, runlen, regval;
21+
uint8_t *p = (uint8_t*)sparse, *end = p+sdslen(sparse);
22+
+ int valid = 1;
23+
24+
/* If the representation is already the right one return ASAP. */
25+
hdr = (struct hllhdr*) sparse;
26+
@@ -598,16 +599,27 @@ int hllSparseToDense(robj *o) {
27+
while(p < end) {
28+
if (HLL_SPARSE_IS_ZERO(p)) {
29+
runlen = HLL_SPARSE_ZERO_LEN(p);
30+
+ if ((runlen + idx) > HLL_REGISTERS) { /* Overflow. */
31+
+ valid = 0;
32+
+ break;
33+
+ }
34+
idx += runlen;
35+
p++;
36+
} else if (HLL_SPARSE_IS_XZERO(p)) {
37+
runlen = HLL_SPARSE_XZERO_LEN(p);
38+
+ if ((runlen + idx) > HLL_REGISTERS) { /* Overflow. */
39+
+ valid = 0;
40+
+ break;
41+
+ }
42+
idx += runlen;
43+
p += 2;
44+
} else {
45+
runlen = HLL_SPARSE_VAL_LEN(p);
46+
regval = HLL_SPARSE_VAL_VALUE(p);
47+
- if ((runlen + idx) > HLL_REGISTERS) break; /* Overflow. */
48+
+ if ((runlen + idx) > HLL_REGISTERS) { /* Overflow. */
49+
+ valid = 0;
50+
+ break;
51+
+ }
52+
while(runlen--) {
53+
HLL_DENSE_SET_REGISTER(hdr->registers,idx,regval);
54+
idx++;
55+
@@ -618,7 +630,7 @@ int hllSparseToDense(robj *o) {
56+
57+
/* If the sparse representation was valid, we expect to find idx
58+
* set to HLL_REGISTERS. */
59+
- if (idx != HLL_REGISTERS) {
60+
+ if (!valid || idx != HLL_REGISTERS) {
61+
sdsfree(dense);
62+
return C_ERR;
63+
}
64+
@@ -915,27 +927,40 @@ int hllSparseAdd(robj *o, unsigned char *ele, size_t elesize) {
65+
void hllSparseRegHisto(uint8_t *sparse, int sparselen, int *invalid, int* reghisto) {
66+
int idx = 0, runlen, regval;
67+
uint8_t *end = sparse+sparselen, *p = sparse;
68+
+ int valid = 1;
69+
70+
while(p < end) {
71+
if (HLL_SPARSE_IS_ZERO(p)) {
72+
runlen = HLL_SPARSE_ZERO_LEN(p);
73+
+ if ((runlen + idx) > HLL_REGISTERS) { /* Overflow. */
74+
+ valid = 0;
75+
+ break;
76+
+ }
77+
idx += runlen;
78+
reghisto[0] += runlen;
79+
p++;
80+
} else if (HLL_SPARSE_IS_XZERO(p)) {
81+
runlen = HLL_SPARSE_XZERO_LEN(p);
82+
+ if ((runlen + idx) > HLL_REGISTERS) { /* Overflow. */
83+
+ valid = 0;
84+
+ break;
85+
+ }
86+
idx += runlen;
87+
reghisto[0] += runlen;
88+
p += 2;
89+
} else {
90+
runlen = HLL_SPARSE_VAL_LEN(p);
91+
regval = HLL_SPARSE_VAL_VALUE(p);
92+
+ if ((runlen + idx) > HLL_REGISTERS) { /* Overflow. */
93+
+ valid = 0;
94+
+ break;
95+
+ }
96+
idx += runlen;
97+
reghisto[regval] += runlen;
98+
p++;
99+
}
100+
}
101+
- if (idx != HLL_REGISTERS && invalid) *invalid = 1;
102+
+ if ((!valid || idx != HLL_REGISTERS) && invalid) *invalid = 1;
103+
}
104+
105+
/* ========================= HyperLogLog Count ==============================
106+
@@ -1204,22 +1229,34 @@ int hllMerge(uint8_t *max, robj *hll) {
107+
} else {
108+
uint8_t *p = hll->ptr, *end = p + sdslen(hll->ptr);
109+
long runlen, regval;
110+
+ int valid = 1;
111+
112+
p += HLL_HDR_SIZE;
113+
i = 0;
114+
while(p < end) {
115+
if (HLL_SPARSE_IS_ZERO(p)) {
116+
runlen = HLL_SPARSE_ZERO_LEN(p);
117+
+ if ((runlen + i) > HLL_REGISTERS) { /* Overflow. */
118+
+ valid = 0;
119+
+ break;
120+
+ }
121+
i += runlen;
122+
p++;
123+
} else if (HLL_SPARSE_IS_XZERO(p)) {
124+
runlen = HLL_SPARSE_XZERO_LEN(p);
125+
+ if ((runlen + i) > HLL_REGISTERS) { /* Overflow. */
126+
+ valid = 0;
127+
+ break;
128+
+ }
129+
i += runlen;
130+
p += 2;
131+
} else {
132+
runlen = HLL_SPARSE_VAL_LEN(p);
133+
regval = HLL_SPARSE_VAL_VALUE(p);
134+
- if ((runlen + i) > HLL_REGISTERS) break; /* Overflow. */
135+
+ if ((runlen + i) > HLL_REGISTERS) { /* Overflow. */
136+
+ valid = 0;
137+
+ break;
138+
+ }
139+
while(runlen--) {
140+
if (regval > max[i]) max[i] = regval;
141+
i++;
142+
@@ -1227,7 +1264,7 @@ int hllMerge(uint8_t *max, robj *hll) {
143+
p++;
144+
}
145+
}
146+
- if (i != HLL_REGISTERS) return C_ERR;
147+
+ if (!valid || i != HLL_REGISTERS) return C_ERR;
148+
}
149+
return C_OK;
150+
}
151+
diff --git a/tests/unit/hyperloglog.tcl b/tests/unit/hyperloglog.tcl
152+
index f1bbeace9d1..76c0a8d8d2c 100644
153+
--- a/tests/unit/hyperloglog.tcl
154+
+++ b/tests/unit/hyperloglog.tcl
155+
@@ -137,6 +137,57 @@ start_server {tags {"hll"}} {
156+
set e
157+
} {*WRONGTYPE*}
158+
159+
+ test {Corrupted sparse HyperLogLogs doesn't cause overflow and out-of-bounds with XZERO opcode} {
160+
+ r del hll
161+
+
162+
+ # Create a sparse-encoded HyperLogLog header
163+
+ set pl [string cat "HYLL" [binary format c12 {1 0 0 0 0 0 0 0 0 0 0 0}]]
164+
+
165+
+ # Create an XZERO opcode with the maximum run length of 16384(2^14)
166+
+ set runlen [expr 16384 - 1]
167+
+ set chunk [binary format cc [expr {0b01000000 | ($runlen >> 8)}] [expr {$runlen & 0xff}]]
168+
+ # Fill the HLL with more than 131072(2^17) XZERO opcodes to make the total
169+
+ # run length exceed 4GB, will cause an integer overflow.
170+
+ set repeat [expr 131072 + 1000]
171+
+ for {set i 0} {$i < $repeat} {incr i} {
172+
+ append pl $chunk
173+
+ }
174+
+
175+
+ # Create a VAL opcode with a value that will cause out-of-bounds.
176+
+ append pl [binary format c 0b11111111]
177+
+ r set hll $pl
178+
+
179+
+ # This should not overflow and out-of-bounds.
180+
+ assert_error {*INVALIDOBJ*} {r pfcount hll hll}
181+
+ assert_error {*INVALIDOBJ*} {r pfdebug getreg hll}
182+
+ r ping
183+
+ }
184+
+
185+
+ test {Corrupted sparse HyperLogLogs doesn't cause overflow and out-of-bounds with ZERO opcode} {
186+
+ r del hll
187+
+
188+
+ # Create a sparse-encoded HyperLogLog header
189+
+ set pl [string cat "HYLL" [binary format c12 {1 0 0 0 0 0 0 0 0 0 0 0}]]
190+
+
191+
+ # # Create an ZERO opcode with the maximum run length of 64(2^6)
192+
+ set chunk [binary format c [expr {0b00000000 | 0x3f}]]
193+
+ # Fill the HLL with more than 33554432(2^17) ZERO opcodes to make the total
194+
+ # run length exceed 4GB, will cause an integer overflow.
195+
+ set repeat [expr 33554432 + 1000]
196+
+ for {set i 0} {$i < $repeat} {incr i} {
197+
+ append pl $chunk
198+
+ }
199+
+
200+
+ # Create a VAL opcode with a value that will cause out-of-bounds.
201+
+ append pl [binary format c 0b11111111]
202+
+ r set hll $pl
203+
+
204+
+ # This should not overflow and out-of-bounds.
205+
+ assert_error {*INVALIDOBJ*} {r pfcount hll hll}
206+
+ assert_error {*INVALIDOBJ*} {r pfdebug getreg hll}
207+
+ r ping
208+
+ }
209+
+
210+
test {Corrupted dense HyperLogLogs are detected: Wrong length} {
211+
r del hll
212+
r pfadd hll a b c

SPECS/redis/redis.spec

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Summary: advanced key-value store
22
Name: redis
33
Version: 6.2.18
4-
Release: 1%{?dist}
4+
Release: 2%{?dist}
55
License: BSD
66
Vendor: Microsoft Corporation
77
Distribution: Mariner
@@ -10,6 +10,7 @@ URL: https://redis.io/
1010
Source0: https://download.redis.io/releases/%{name}-%{version}.tar.gz
1111
Patch0: redis-conf.patch
1212
Patch1: disable_active_defrag_big_keys.patch
13+
Patch2: CVE-2025-32023.patch
1314
BuildRequires: gcc
1415
BuildRequires: make
1516
BuildRequires: openssl-devel
@@ -84,6 +85,9 @@ exit 0
8485
%config(noreplace) %attr(0640, %{name}, %{name}) %{_sysconfdir}/redis.conf
8586

8687
%changelog
88+
* Wed Jul 09 2025 Azure Linux Security Servicing Account <[email protected]> - 6.2.18-2
89+
- Patch for CVE-2025-32023
90+
8791
* Wed Apr 30 2025 CBL-Mariner Servicing Account <[email protected]> - 6.2.18-1
8892
- Auto-upgrade to 6.2.18 - for CVE-2025-21605
8993

0 commit comments

Comments
 (0)