summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2023-06-09 08:41:05 +0000
committerCoprDistGit <infra@openeuler.org>2023-06-09 08:41:05 +0000
commit4d2e143b15fdc8f316a1eef5a8b1053981f6d256 (patch)
tree10203472e783180b6364499f88ef2906b18b0049
parentd7609b0abb011ea9d856ca663892f0f88d211f78 (diff)
automatic import of redisopeneuler20.03
-rw-r--r--.gitignore1
-rw-r--r--Aesthetic-changes-to-PR.patch185
-rw-r--r--CVE-2019-10193.patch30
-rw-r--r--CVE-2020-14147.patch50
-rw-r--r--CVE-2021-21309.patch150
-rw-r--r--CVE-2021-29478.patch35
-rw-r--r--CVE-2021-32672.patch132
-rw-r--r--CVE-2021-3470.patch39
-rw-r--r--CVE-2022-36021.patch92
-rw-r--r--CVE-2023-28856.patch49
-rw-r--r--huawei-deps-jemalloc-support-riscv.patch62
-rw-r--r--improved-HyperLogLog-cardinality-estimation.patch328
-rw-r--r--modify-aarch64-architecture-jemalloc-page-size-from-4k-to-64k.patch13
-rw-r--r--redis-sentinel.service14
-rw-r--r--redis.logrotate9
-rw-r--r--redis.service15
-rw-r--r--redis.spec181
-rw-r--r--sources1
18 files changed, 1386 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e69de29..ca52092 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/redis-4.0.14.tar.gz
diff --git a/Aesthetic-changes-to-PR.patch b/Aesthetic-changes-to-PR.patch
new file mode 100644
index 0000000..77e848e
--- /dev/null
+++ b/Aesthetic-changes-to-PR.patch
@@ -0,0 +1,185 @@
+From 7413dc16572ffd672835c1391b08409472771093 Mon Sep 17 00:00:00 2001
+From: antirez <antirez@gmail.com>
+Date: Fri, 16 Mar 2018 16:57:53 +0100
+Subject: [PATCH] Aesthetic changes to PR #4749.
+
+---
+ src/hyperloglog.c | 80 +++++++++++++++++++++++------------------------
+ 1 file changed, 40 insertions(+), 40 deletions(-)
+
+diff --git a/src/hyperloglog.c b/src/hyperloglog.c
+index 77109c8..68d591c 100644
+--- a/src/hyperloglog.c
++++ b/src/hyperloglog.c
+@@ -403,7 +403,7 @@ uint64_t MurmurHash64A (const void * key, int len, unsigned int seed) {
+
+ #if (BYTE_ORDER == LITTLE_ENDIAN)
+ #ifdef USE_ALIGNED_ACCESS
+- memcpy(&k,data,sizeof(uint64_t));
++ memcpy(&k,data,sizeof(uint64_t));
+ #else
+ k = *((uint64_t*)data);
+ #endif
+@@ -512,7 +512,7 @@ int hllDenseAdd(uint8_t *registers, unsigned char *ele, size_t elesize) {
+ }
+
+ /* Compute the register histogram in the dense representation. */
+-void hllDenseRegHisto(uint8_t *registers, int* regHisto) {
++void hllDenseRegHisto(uint8_t *registers, int* reghisto) {
+ int j;
+
+ /* Redis default is to use 16384 registers 6 bits each. The code works
+@@ -541,22 +541,22 @@ void hllDenseRegHisto(uint8_t *registers, int* regHisto) {
+ r14 = (r[10] >> 4 | r[11] << 4) & 63;
+ r15 = (r[11] >> 2) & 63;
+
+- regHisto[r0] += 1;
+- regHisto[r1] += 1;
+- regHisto[r2] += 1;
+- regHisto[r3] += 1;
+- regHisto[r4] += 1;
+- regHisto[r5] += 1;
+- regHisto[r6] += 1;
+- regHisto[r7] += 1;
+- regHisto[r8] += 1;
+- regHisto[r9] += 1;
+- regHisto[r10] += 1;
+- regHisto[r11] += 1;
+- regHisto[r12] += 1;
+- regHisto[r13] += 1;
+- regHisto[r14] += 1;
+- regHisto[r15] += 1;
++ reghisto[r0]++;
++ reghisto[r1]++;
++ reghisto[r2]++;
++ reghisto[r3]++;
++ reghisto[r4]++;
++ reghisto[r5]++;
++ reghisto[r6]++;
++ reghisto[r7]++;
++ reghisto[r8]++;
++ reghisto[r9]++;
++ reghisto[r10]++;
++ reghisto[r11]++;
++ reghisto[r12]++;
++ reghisto[r13]++;
++ reghisto[r14]++;
++ reghisto[r15]++;
+
+ r += 12;
+ }
+@@ -564,7 +564,7 @@ void hllDenseRegHisto(uint8_t *registers, int* regHisto) {
+ for(j = 0; j < HLL_REGISTERS; j++) {
+ unsigned long reg;
+ HLL_DENSE_GET_REGISTER(reg,registers,j);
+- regHisto[reg] += 1;
++ reghisto[reg]++;
+ }
+ }
+ }
+@@ -904,7 +904,7 @@ int hllSparseAdd(robj *o, unsigned char *ele, size_t elesize) {
+ }
+
+ /* Compute the register histogram in the sparse representation. */
+-void hllSparseRegHisto(uint8_t *sparse, int sparselen, int *invalid, int* regHisto) {
++void hllSparseRegHisto(uint8_t *sparse, int sparselen, int *invalid, int* reghisto) {
+ int idx = 0, runlen, regval;
+ uint8_t *end = sparse+sparselen, *p = sparse;
+
+@@ -912,18 +912,18 @@ void hllSparseRegHisto(uint8_t *sparse, int sparselen, int *invalid, int* regHis
+ if (HLL_SPARSE_IS_ZERO(p)) {
+ runlen = HLL_SPARSE_ZERO_LEN(p);
+ idx += runlen;
+- regHisto[0] += runlen;
++ reghisto[0] += runlen;
+ p++;
+ } else if (HLL_SPARSE_IS_XZERO(p)) {
+ runlen = HLL_SPARSE_XZERO_LEN(p);
+ idx += runlen;
+- regHisto[0] += runlen;
++ reghisto[0] += runlen;
+ p += 2;
+ } else {
+ runlen = HLL_SPARSE_VAL_LEN(p);
+ regval = HLL_SPARSE_VAL_VALUE(p);
+ idx += runlen;
+- regHisto[regval] += runlen;
++ reghisto[regval] += runlen;
+ p++;
+ }
+ }
+@@ -938,24 +938,24 @@ void hllSparseRegHisto(uint8_t *sparse, int sparselen, int *invalid, int* regHis
+
+ /* Implements the register histogram calculation for uint8_t data type
+ * which is only used internally as speedup for PFCOUNT with multiple keys. */
+-void hllRawRegHisto(uint8_t *registers, int* regHisto) {
++void hllRawRegHisto(uint8_t *registers, int* reghisto) {
+ uint64_t *word = (uint64_t*) registers;
+ uint8_t *bytes;
+ int j;
+
+ for (j = 0; j < HLL_REGISTERS/8; j++) {
+ if (*word == 0) {
+- regHisto[0] += 8;
++ reghisto[0] += 8;
+ } else {
+ bytes = (uint8_t*) word;
+- regHisto[bytes[0]] += 1;
+- regHisto[bytes[1]] += 1;
+- regHisto[bytes[2]] += 1;
+- regHisto[bytes[3]] += 1;
+- regHisto[bytes[4]] += 1;
+- regHisto[bytes[5]] += 1;
+- regHisto[bytes[6]] += 1;
+- regHisto[bytes[7]] += 1;
++ reghisto[bytes[0]]++;
++ reghisto[bytes[1]]++;
++ reghisto[bytes[2]]++;
++ reghisto[bytes[3]]++;
++ reghisto[bytes[4]]++;
++ reghisto[bytes[5]]++;
++ reghisto[bytes[6]]++;
++ reghisto[bytes[7]]++;
+ }
+ word++;
+ }
+@@ -1011,16 +1011,16 @@ uint64_t hllCount(struct hllhdr *hdr, int *invalid) {
+ double E;
+ int j;
+ double alphaInf = 0.5 / log(2.);
+- int regHisto[HLL_Q+2] = {0};
++ int reghisto[HLL_Q+2] = {0};
+
+ /* Compute register histogram */
+ if (hdr->encoding == HLL_DENSE) {
+- hllDenseRegHisto(hdr->registers,regHisto);
++ hllDenseRegHisto(hdr->registers,reghisto);
+ } else if (hdr->encoding == HLL_SPARSE) {
+ hllSparseRegHisto(hdr->registers,
+- sdslen((sds)hdr)-HLL_HDR_SIZE,invalid,regHisto);
++ sdslen((sds)hdr)-HLL_HDR_SIZE,invalid,reghisto);
+ } else if (hdr->encoding == HLL_RAW) {
+- hllRawRegHisto(hdr->registers,regHisto);
++ hllRawRegHisto(hdr->registers,reghisto);
+ } else {
+ serverPanic("Unknown HyperLogLog encoding in hllCount()");
+ }
+@@ -1028,12 +1028,12 @@ uint64_t hllCount(struct hllhdr *hdr, int *invalid) {
+ /* Estimate cardinality form register histogram. See:
+ * "New cardinality estimation algorithms for HyperLogLog sketches"
+ * Otmar Ertl, arXiv:1702.01284 */
+- double z = m * hllTau((m-regHisto[HLL_Q+1])/(double)m);
++ double z = m * hllTau((m-reghisto[HLL_Q+1])/(double)m);
+ for (j = HLL_Q; j >= 1; --j) {
+- z += regHisto[j];
++ z += reghisto[j];
+ z *= 0.5;
+ }
+- z += m * hllSigma(regHisto[0]/(double)m);
++ z += m * hllSigma(reghisto[0]/(double)m);
+ E = llroundl(alphaInf*m*m/z);
+
+ return (uint64_t) E;
+--
+2.23.0
+
diff --git a/CVE-2019-10193.patch b/CVE-2019-10193.patch
new file mode 100644
index 0000000..80edfd3
--- /dev/null
+++ b/CVE-2019-10193.patch
@@ -0,0 +1,30 @@
+From 4c7eda965af7f231148219267c9b039d06cab519 Mon Sep 17 00:00:00 2001
+From: antirez <antirez@gmail.com>
+Date: Fri, 15 Mar 2019 17:10:16 +0100
+Subject: [PATCH] HyperLogLog: enlarge reghisto variable for safety.
+
+---
+ src/hyperloglog.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/src/hyperloglog.c b/src/hyperloglog.c
+index 68d591c..24cf81a 100644
+--- a/src/hyperloglog.c
++++ b/src/hyperloglog.c
+@@ -1011,7 +1011,12 @@ uint64_t hllCount(struct hllhdr *hdr, int *invalid) {
+ double E;
+ int j;
+ double alphaInf = 0.5 / log(2.);
+- int reghisto[HLL_Q+2] = {0};
++ /* Note that reghisto could be just HLL_Q+1, becuase this is the
++ * maximum frequency of the "000...1" sequence the hash function is
++ * able to return. However it is slow to check for sanity of the
++ * input: instead we history array at a safe size: overflows will
++ * just write data to wrong, but correctly allocated, places. */
++ int reghisto[64] = {0};
+
+ /* Compute register histogram */
+ if (hdr->encoding == HLL_DENSE) {
+--
+2.23.0
+
diff --git a/CVE-2020-14147.patch b/CVE-2020-14147.patch
new file mode 100644
index 0000000..7225224
--- /dev/null
+++ b/CVE-2020-14147.patch
@@ -0,0 +1,50 @@
+From ef764dde1cca2f25d00686673d1bc89448819571 Mon Sep 17 00:00:00 2001
+From: Seunghoon Woo <toad58@nate.com>
+Date: Mon, 10 Feb 2020 16:32:46 +0900
+Subject: [PATCH] [FIX] revisit CVE-2015-8080 vulnerability
+
+---
+ deps/lua/src/lua_struct.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/deps/lua/src/lua_struct.c b/deps/lua/src/lua_struct.c
+index 4d5f027b85c..c58c8e72b08 100644
+--- a/deps/lua/src/lua_struct.c
++++ b/deps/lua/src/lua_struct.c
+@@ -89,12 +89,14 @@ typedef struct Header {
+ } Header;
+
+
+-static int getnum (const char **fmt, int df) {
++static int getnum (lua_State *L, const char **fmt, int df) {
+ if (!isdigit(**fmt)) /* no number? */
+ return df; /* return default value */
+ else {
+ int a = 0;
+ do {
++ if (a > (INT_MAX / 10) || a * 10 > (INT_MAX - (**fmt - '0')))
++ luaL_error(L, "integral size overflow");
+ a = a*10 + *((*fmt)++) - '0';
+ } while (isdigit(**fmt));
+ return a;
+@@ -115,9 +117,9 @@ static size_t optsize (lua_State *L, char opt, const char **fmt) {
+ case 'f': return sizeof(float);
+ case 'd': return sizeof(double);
+ case 'x': return 1;
+- case 'c': return getnum(fmt, 1);
++ case 'c': return getnum(L, fmt, 1);
+ case 'i': case 'I': {
+- int sz = getnum(fmt, sizeof(int));
++ int sz = getnum(L, fmt, sizeof(int));
+ if (sz > MAXINTSIZE)
+ luaL_error(L, "integral size %d is larger than limit of %d",
+ sz, MAXINTSIZE);
+@@ -150,7 +152,7 @@ static void controloptions (lua_State *L, int opt, const char **fmt,
+ case '>': h->endian = BIG; return;
+ case '<': h->endian = LITTLE; return;
+ case '!': {
+- int a = getnum(fmt, MAXALIGN);
++ int a = getnum(L, fmt, MAXALIGN);
+ if (!isp2(a))
+ luaL_error(L, "alignment %d is not a power of 2", a);
+ h->align = a;
diff --git a/CVE-2021-21309.patch b/CVE-2021-21309.patch
new file mode 100644
index 0000000..6e91579
--- /dev/null
+++ b/CVE-2021-21309.patch
@@ -0,0 +1,150 @@
+From 48f04a82a0ac542341fb644a4cfbebadd5c59a33 Mon Sep 17 00:00:00 2001
+From: Yossi Gottlieb <yossigo@gmail.com>
+Date: Mon, 22 Feb 2021 15:41:32 +0200
+Subject: [PATCH] Fix integer overflow (CVE-2021-21309). (#8522)
+
+On 32-bit systems, setting the proto-max-bulk-len config parameter to a high value may result with integer overflow and a subsequent heap overflow when parsing an input bulk (CVE-2021-21309).
+
+This fix has two parts:
+
+Set a reasonable limit to the config parameter.
+Add additional checks to prevent the problem in other potential but unknown code paths.
+
+(cherry picked from commit d32f2e9999ce003bad0bd2c3bca29f64dcce4433)
+
+Fix MSVR reported issue.
+---
+ src/config.c | 16 ++++++++--------
+ src/sds.c | 3 +++
+ src/zmalloc.c | 10 ++++++++++
+ 3 files changed, 21 insertions(+), 8 deletions(-)
+
+diff --git a/src/config.c b/src/config.c
+index 5f22442ecc5..0814768b9d9 100644
+--- a/src/config.c
++++ b/src/config.c
+@@ -817,10 +817,10 @@ void loadServerConfig(char *filename, ch
+ if (max != LLONG_MAX && ll > max) goto badfmt; \
+ _var = ll;
+
+-#define config_set_memory_field(_name,_var) \
++#define config_set_memory_field(_name,_var,min,max) \
+ } else if (!strcasecmp(c->argv[2]->ptr,_name)) { \
+ ll = memtoll(o->ptr,&err); \
+- if (err || ll < 0) goto badfmt; \
++ if (err || ll < (long long) (min) || ll > (long long) (max)) goto badfmt; \
+ _var = ll;
+
+ #define config_set_enum_field(_name,_var,_enumvar) \
+@@ -1063,7 +1063,7 @@ void configSetCommand(client *c) {
+ } config_set_numerical_field(
+ "active-defrag-threshold-upper",server.active_defrag_threshold_upper,0,1000) {
+ } config_set_memory_field(
+- "active-defrag-ignore-bytes",server.active_defrag_ignore_bytes) {
++ "active-defrag-ignore-bytes",server.active_defrag_ignore_bytes,0,LONG_MAX) {
+ } config_set_numerical_field(
+ "active-defrag-cycle-min",server.active_defrag_cycle_min,1,99) {
+ } config_set_numerical_field(
+@@ -1139,7 +1139,7 @@ void configSetCommand(client *c) {
+
+ /* Memory fields.
+ * config_set_memory_field(name,var) */
+- } config_set_memory_field("maxmemory",server.maxmemory) {
++ } config_set_memory_field("maxmemory",server.maxmemory,0,LONG_MAX) {
+ if (server.maxmemory) {
+ if (server.maxmemory < zmalloc_used_memory()) {
+ serverLog(LL_WARNING,"WARNING: the new maxmemory value set via CONFIG SET is smaller than the current memory usage. This will result in keys eviction and/or inability to accept new write commands depending on the maxmemory-policy.");
+@@ -1147,12 +1147,12 @@ void configSetCommand(client *c) {
+ freeMemoryIfNeeded();
+ }
+ } config_set_memory_field(
+- "proto-max-bulk-len",server.proto_max_bulk_len) {
++ "proto-max-bulk-len",server.proto_max_bulk_len,1024*1024,LONG_MAX/2) {
+ } config_set_memory_field(
+- "client-query-buffer-limit",server.client_max_querybuf_len) {
+- } config_set_memory_field("repl-backlog-size",ll) {
++ "client-query-buffer-limit",server.client_max_querybuf_len,0,LONG_MAX) {
++ } config_set_memory_field("repl-backlog-size",ll,0,LONG_MAX) {
+ resizeReplicationBacklog(ll);
+- } config_set_memory_field("auto-aof-rewrite-min-size",ll) {
++ } config_set_memory_field("auto-aof-rewrite-min-size",ll,0,LONG_MAX) {
+ server.aof_rewrite_min_size = ll;
+
+ /* Enumeration fields.
+diff --git a/src/sds.c b/src/sds.c
+index cd60946bdd3..12c9da356d9 100644
+--- a/src/sds.c
++++ b/src/sds.c
+@@ -91,6 +91,7 @@ sds sdsnewlen(const void *init, size_t initlen) {
+ int hdrlen = sdsHdrSize(type);
+ unsigned char *fp; /* flags pointer. */
+
++ assert(hdrlen+initlen+1 > initlen); /* Catch size_t overflow */
+ sh = s_malloc(hdrlen+initlen+1);
+ if (!init)
+ memset(sh, 0, hdrlen+initlen+1);
+@@ -207,6 +208,7 @@ sds sdsMakeRoomFor(sds s, size_t addlen) {
+ len = sdslen(s);
+ sh = (char*)s-sdsHdrSize(oldtype);
+ newlen = (len+addlen);
++ assert(newlen > len); /* Catch size_t overflow */
+ if (newlen < SDS_MAX_PREALLOC)
+ newlen *= 2;
+ else
+@@ -220,6 +222,7 @@ sds sdsMakeRoomFor(sds s, size_t addlen) {
+ if (type == SDS_TYPE_5) type = SDS_TYPE_8;
+
+ hdrlen = sdsHdrSize(type);
++ assert(hdrlen+newlen+1 > len); /* Catch size_t overflow */
+ if (oldtype==type) {
+ newsh = s_realloc(sh, hdrlen+newlen+1);
+ if (newsh == NULL) return NULL;
+diff --git a/src/zmalloc.c b/src/zmalloc.c
+index 972db79d7ab..29e68180f0d 100644
+--- a/src/zmalloc.c
++++ b/src/zmalloc.c
+@@ -55,6 +55,12 @@ void zlibc_free(void *ptr) {
+ #endif
+ #endif
+
++#if PREFIX_SIZE > 0
++#define ASSERT_NO_SIZE_OVERFLOW(sz) assert((sz) + PREFIX_SIZE > (sz))
++#else
++#define ASSERT_NO_SIZE_OVERFLOW(sz)
++#endif
++
+ /* Explicitly override malloc/free etc when using tcmalloc. */
+ #if defined(USE_TCMALLOC)
+ #define malloc(size) tc_malloc(size)
+@@ -95,6 +101,7 @@ static void zmalloc_default_oom(size_t size) {
+ static void (*zmalloc_oom_handler)(size_t) = zmalloc_default_oom;
+
+ void *zmalloc(size_t size) {
++ ASSERT_NO_SIZE_OVERFLOW(size);
+ void *ptr = malloc(size+PREFIX_SIZE);
+
+ if (!ptr) zmalloc_oom_handler(size);
+@@ -113,6 +120,7 @@ void *zmalloc(size_t size) {
+ * Currently implemented only for jemalloc. Used for online defragmentation. */
+ #ifdef HAVE_DEFRAG
+ void *zmalloc_no_tcache(size_t size) {
++ ASSERT_NO_SIZE_OVERFLOW(size);
+ void *ptr = mallocx(size+PREFIX_SIZE, MALLOCX_TCACHE_NONE);
+ if (!ptr) zmalloc_oom_handler(size);
+ update_zmalloc_stat_alloc(zmalloc_size(ptr));
+@@ -127,6 +135,7 @@ void zfree_no_tcache(void *ptr) {
+ #endif
+
+ void *zcalloc(size_t size) {
++ ASSERT_NO_SIZE_OVERFLOW(size);
+ void *ptr = calloc(1, size+PREFIX_SIZE);
+
+ if (!ptr) zmalloc_oom_handler(size);
+@@ -141,6 +150,7 @@ void *zcalloc(size_t size) {
+ }
+
+ void *zrealloc(void *ptr, size_t size) {
++ ASSERT_NO_SIZE_OVERFLOW(size);
+ #ifndef HAVE_MALLOC_SIZE
+ void *realptr;
+ #endif
diff --git a/CVE-2021-29478.patch b/CVE-2021-29478.patch
new file mode 100644
index 0000000..c7002c2
--- /dev/null
+++ b/CVE-2021-29478.patch
@@ -0,0 +1,35 @@
+From ef78ba0a7793a0b6be026ec77ef3c7e919efa08a Mon Sep 17 00:00:00 2001
+From: Oran Agra <oran@redislabs.com>
+Date: Mon, 3 May 2021 08:27:22 +0300
+Subject: [PATCH] Fix integer overflow in intset (CVE-2021-29478)
+
+An integer overflow bug in Redis 6.2 could be exploited to corrupt the heap and
+potentially result with remote code execution.
+
+The vulnerability involves changing the default set-max-intset-entries
+configuration value, creating a large set key that consists of integer values
+and using the COPY command to duplicate it.
+
+The integer overflow bug exists in all versions of Redis starting with 2.6,
+where it could result with a corrupted RDB or DUMP payload, but not exploited
+through COPY (which did not exist before 6.2).
+---
+ src/intset.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/intset.c b/src/intset.c
+index 198c90a..8d35536 100644
+--- a/src/intset.c
++++ b/src/intset.c
+@@ -278,7 +278,7 @@ uint32_t intsetLen(const intset *is) {
+
+ /* Return intset blob size in bytes. */
+ size_t intsetBlobLen(intset *is) {
+- return sizeof(intset)+intrev32ifbe(is->length)*intrev32ifbe(is->encoding);
++ return sizeof(intset)+(size_t)intrev32ifbe(is->length)*intrev32ifbe(is->encoding);
+ }
+
+ #ifdef REDIS_TEST
+--
+2.23.0
+
diff --git a/CVE-2021-32672.patch b/CVE-2021-32672.patch
new file mode 100644
index 0000000..9c4780a
--- /dev/null
+++ b/CVE-2021-32672.patch
@@ -0,0 +1,132 @@
+From 6ac3c0b7abd35f37201ed2d6298ecef4ea1ae1dd Mon Sep 17 00:00:00 2001
+From: "meir@redislabs.com" <meir@redislabs.com>
+Date: Sun, 13 Jun 2021 14:29:20 +0300
+Subject: [PATCH] Fix protocol parsing on 'ldbReplParseCommand'
+ (CVE-2021-32672)
+
+The protocol parsing on 'ldbReplParseCommand' (LUA debugging)Assumed protocol correctness. This means that if the following
+is given:
+*1
+$100
+test
+The parser will try to read additional 94 unallocated bytes after
+the client buffer.
+This commit fixes this issue by validating that there are actually enough
+bytes to read. It also limits the amount of data that can be sent by
+the debugger client to 1M so the client will not be able to explode
+the memory.
+---
+ src/scripting.c | 29 +++++++++++++++++++++++++----
+ tests/unit/scripting.tcl | 14 ++++++++++++++
+ 2 files changed, 39 insertions(+), 4 deletions(-)
+
+diff --git a/src/scripting.c b/src/scripting.c
+index a781e68..ecb6811 100644
+--- a/src/scripting.c
++++ b/src/scripting.c
+@@ -1784,7 +1784,8 @@ int ldbDelBreakpoint(int line) {
+ /* Expect a valid multi-bulk command in the debugging client query buffer.
+ * On success the command is parsed and returned as an array of SDS strings,
+ * otherwise NULL is returned and there is to read more buffer. */
+-sds *ldbReplParseCommand(int *argcp) {
++sds *ldbReplParseCommand(int *argcp, char** err) {
++ static char* protocol_error = "protocol error";
+ sds *argv = NULL;
+ int argc = 0;
+ if (sdslen(ldb.cbuf) == 0) return NULL;
+@@ -1801,7 +1802,7 @@ sds *ldbReplParseCommand(int *argcp) {
+ /* Seek and parse *<count>\r\n. */
+ p = strchr(p,'*'); if (!p) goto protoerr;
+ char *plen = p+1; /* Multi bulk len pointer. */
+- p = strstr(p,"\r\n"); if (!p) goto protoerr;
++ p = strstr(p,"\r\n"); if (!p) goto keep_reading;
+ *p = '\0'; p += 2;
+ *argcp = atoi(plen);
+ if (*argcp <= 0 || *argcp > 1024) goto protoerr;
+@@ -1810,12 +1811,16 @@ sds *ldbReplParseCommand(int *argcp) {
+ argv = zmalloc(sizeof(sds)*(*argcp));
+ argc = 0;
+ while(argc < *argcp) {
++ // reached the end but there should be more data to read
++ if (*p == '\0') goto keep_reading;
++
+ if (*p != '$') goto protoerr;
+ plen = p+1; /* Bulk string len pointer. */
+- p = strstr(p,"\r\n"); if (!p) goto protoerr;
++ p = strstr(p,"\r\n"); if (!p) goto keep_reading;
+ *p = '\0'; p += 2;
+ int slen = atoi(plen); /* Length of this arg. */
+ if (slen <= 0 || slen > 1024) goto protoerr;
++ if ((size_t)(p + slen + 2 - copy) > sdslen(copy) ) goto keep_reading;
+ argv[argc++] = sdsnewlen(p,slen);
+ p += slen; /* Skip the already parsed argument. */
+ if (p[0] != '\r' || p[1] != '\n') goto protoerr;
+@@ -1825,6 +1830,8 @@ sds *ldbReplParseCommand(int *argcp) {
+ return argv;
+
+ protoerr:
++ *err = protocol_error;
++keep_reading:
+ sdsfreesplitres(argv,argc);
+ sdsfree(copy);
+ return NULL;
+@@ -2246,12 +2253,17 @@ void ldbMaxlen(sds *argv, int argc) {
+ int ldbRepl(lua_State *lua) {
+ sds *argv;
+ int argc;
++ char* err = NULL;
+
+ /* We continue processing commands until a command that should return
+ * to the Lua interpreter is found. */
+ while(1) {
+- while((argv = ldbReplParseCommand(&argc)) == NULL) {
++ while((argv = ldbReplParseCommand(&argc, &err)) == NULL) {
+ char buf[1024];
++ if (err) {
++ lua_pushstring(lua, err);
++ lua_error(lua);
++ }
+ int nread = read(ldb.fd,buf,sizeof(buf));
+ if (nread <= 0) {
+ /* Make sure the script runs without user input since the
+@@ -2261,6 +2273,15 @@ int ldbRepl(lua_State *lua) {
+ return C_ERR;
+ }
+ ldb.cbuf = sdscatlen(ldb.cbuf,buf,nread);
++ /* after 1M we will exit with an error
++ * so that the client will not blow the memory
++ */
++ if (sdslen(ldb.cbuf) > 1<<20) {
++ sdsfree(ldb.cbuf);
++ ldb.cbuf = sdsempty();
++ lua_pushstring(lua, "max client buffer reached");
++ lua_error(lua);
++ }
+ }
+
+ /* Flush the old buffer. */
+diff --git a/tests/unit/scripting.tcl b/tests/unit/scripting.tcl
+index be82e15..48c9f1f 100644
+--- a/tests/unit/scripting.tcl
++++ b/tests/unit/scripting.tcl
+@@ -733,3 +733,17 @@ start_server {tags {"scripting repl"}} {
+ }
+ }
+
++start_server {tags {"scripting needs:debug external:skip"}} {
++ test {Test scripting debug protocol parsing} {
++ r script debug sync
++ r eval {return 'hello'} 0
++ catch {r 'hello\0world'} e
++ assert_match {*Unknown Redis Lua debugger command*} $e
++ catch {r 'hello\0'} e
++ assert_match {*Unknown Redis Lua debugger command*} $e
++ catch {r '\0hello'} e
++ assert_match {*Unknown Redis Lua debugger command*} $e
++ catch {r '\0hello\0'} e
++ assert_match {*Unknown Redis Lua debugger command*} $e
++ }
++}
+--
+2.27.0
+
diff --git a/CVE-2021-3470.patch b/CVE-2021-3470.patch
new file mode 100644
index 0000000..d49e271
--- /dev/null
+++ b/CVE-2021-3470.patch
@@ -0,0 +1,39 @@
+From a714d2561b78985ec85f3056aac83c603cbaaa5f Mon Sep 17 00:00:00 2001
+From: wang_yue111 <648774160@qq.com>
+Date: Wed, 7 Apr 2021 10:00:53 +0800
+Subject: [PATCH] Fix wrong zmalloc_size() assumption. (#7963)
+
+When using a system with no malloc_usable_size(), zmalloc_size() assumed
+that the heap allocator always returns blocks that are long-padded.
+
+This may not always be the case, and will result with zmalloc_size()
+returning a size that is bigger than allocated. At least in one case
+this leads to out of bound write, process crash and a potential security
+vulnerability.
+
+Effectively this does not affect the vast majority of users, who use
+jemalloc or glibc.
+
+This problem along with a (different) fix was reported by Drew DeVault.
+
+---
+ src/zmalloc.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/src/zmalloc.c b/src/zmalloc.c
+index cc47f71..67b1b65 100644
+--- a/src/zmalloc.c
++++ b/src/zmalloc.c
+@@ -186,9 +186,6 @@ void *zrealloc(void *ptr, size_t size) {
+ size_t zmalloc_size(void *ptr) {
+ void *realptr = (char*)ptr-PREFIX_SIZE;
+ size_t size = *((size_t*)realptr);
+- /* Assume at least that all the allocations are padded at sizeof(long) by
+- * the underlying allocator. */
+- if (size&(sizeof(long)-1)) size += sizeof(long)-(size&(sizeof(long)-1));
+ return size+PREFIX_SIZE;
+ }
+ #endif
+--
+2.23.0
+
diff --git a/CVE-2022-36021.patch b/CVE-2022-36021.patch
new file mode 100644
index 0000000..0eb5b30
--- /dev/null
+++ b/CVE-2022-36021.patch
@@ -0,0 +1,92 @@
+From dcbfcb916ca1a269b3feef86ee86835294758f84 Mon Sep 17 00:00:00 2001
+From: Oran Agra <oran@redislabs.com>
+Date: Tue, 28 Feb 2023 15:15:26 +0200
+Subject: [PATCH] String pattern matching had exponential time complexity on
+ pathological patterns (CVE-2022-36021) (#11858)
+
+Authenticated users can use string matching commands with a
+specially crafted pattern to trigger a denial-of-service attack on Redis,
+causing it to hang and consume 100% CPU time.
+
+Co-authored-by: Tom Levy <tomlevy93@gmail.com>
+---
+ src/util.c | 27 +++++++++++++++++++++++----
+ tests/unit/keyspace.tcl | 6 ++++++
+ 2 files changed, 29 insertions(+), 4 deletions(-)
+
+diff --git a/src/util.c b/src/util.c
+index d33f4522a507..26d92b92290e 100644
+--- a/src/util.c
++++ b/src/util.c
+@@ -44,8 +44,8 @@
+ #include "sha1.h"
+
+ /* Glob-style pattern matching. */
+-int stringmatchlen(const char *pattern, int patternLen,
+- const char *string, int stringLen, int nocase)
++static int stringmatchlen_impl(const char *pattern, int patternLen,
++ const char *string, int stringLen, int nocase, int *skipLongerMatches)
+ {
+ while(patternLen && stringLen) {
+ switch(pattern[0]) {
+@@ -57,12 +57,24 @@
+ if (patternLen == 1)
+ return 1; /* match */
+ while(stringLen) {
+- if (stringmatchlen(pattern+1, patternLen-1,
+- string, stringLen, nocase))
++ if (stringmatchlen_impl(pattern+1, patternLen-1,
++ string, stringLen, nocase, skipLongerMatches))
+ return 1; /* match */
++ if (*skipLongerMatches)
++ return 0; /* no match */
+ string++;
+ stringLen--;
+ }
++ /* There was no match for the rest of the pattern starting
++ * from anywhere in the rest of the string. If there were
++ * any '*' earlier in the pattern, we can terminate the
++ * search early without trying to match them to longer
++ * substrings. This is because a longer match for the
++ * earlier part of the pattern would require the rest of the
++ * pattern to match starting later in the string, and we
++ * have just determined that there is no match for the rest
++ * of the pattern starting from anywhere in the current
++ * string. */
+ return 0; /* no match */
+ break;
+ case '?':
+@@ -166,10 +178,17 @@
+ return 0;
+ }
+
++int stringmatchlen(const char *pattern, int patternLen,
++ const char *string, int stringLen, int nocase) {
++ int skipLongerMatches = 0;
++ return stringmatchlen_impl(pattern,patternLen,string,stringLen,nocase,&skipLongerMatches);
++}
++
+ int stringmatch(const char *pattern, const char *string, int nocase) {
+ return stringmatchlen(pattern,strlen(pattern),string,strlen(string),nocase);
+ }
+
++
+ /* Convert a string representing an amount of memory into the number of
+ * bytes, so for instance memtoll("1Gb") will return 1073741824 that is
+ * (1024*1024*1024).
+
+diff --git a/tests/unit/keyspace.tcl b/tests/unit/keyspace.tcl
+index b173e0efcacc..43690d06b321 100644
+--- a/tests/unit/keyspace.tcl
++++ b/tests/unit/keyspace.tcl
+@@ -493,4 +493,10 @@ foreach {type large} [array get largevalue] {
+ r keys *
+ r keys *
+ } {dlskeriewrioeuwqoirueioqwrueoqwrueqw}
++
++ test {Regression for pattern matching long nested loops} {
++ r flushdb
++ r SET aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 1
++ r KEYS "a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*b"
++ } {}
+ }
diff --git a/CVE-2023-28856.patch b/CVE-2023-28856.patch
new file mode 100644
index 0000000..43ceb81
--- /dev/null
+++ b/CVE-2023-28856.patch
@@ -0,0 +1,49 @@
+From c924ac3fdf8fe544891dc66c88018e259ee4be87 Mon Sep 17 00:00:00 2001
+From: chendianqiang <c.d_q@163.com>
+Date: Sun, 28 Aug 2022 16:33:41 +0800
+Subject: [PATCH] fix hincrbyfloat not to create a key if the new value is
+ invalid (#11149)
+
+Check the validity of the value before performing the create operation,
+prevents new data from being generated even if the request fails to execute.
+
+Co-authored-by: Oran Agra <oran@redislabs.com>
+Co-authored-by: chendianqiang <chendianqiang@meituan.com>
+Co-authored-by: Binbin <binloveplay1314@qq.com>
+(cherry picked from commit bc7fe41e5857a0854d524e2a63a028e9394d2a5c)
+(cherry picked from commit 606a385935363ea46c0df4f40f8a949d85f7a20a)
+(cherry picked from commit 7df23a5f51488ce002411c9d24b38520ad67b764)
+---
+ src/t_hash.c | 4 ++++
+ tests/unit/type/hash.tcl | 5 +++++
+ 2 files changed, 9 insertions(+)
+
+diff --git a/src/t_hash.c b/src/t_hash.c
+index 3cdfdd169abf..13e65502f145 100644
+--- a/src/t_hash.c
++++ b/src/t_hash.c
+@@ -605,6 +605,10 @@ void hincrbyfloatCommand(client *c) {
+ unsigned int vlen;
+
+ if (getLongDoubleFromObjectOrReply(c,c->argv[3],&incr,NULL) != C_OK) return;
++ if (isnan(incr) || isinf(incr)) {
++ addReplyError(c,"value is NaN or Infinity");
++ return;
++ }
+ if ((o = hashTypeLookupWriteOrCreate(c,c->argv[1])) == NULL) return;
+ if (hashTypeGetValue(o,c->argv[2]->ptr,&vstr,&vlen,&ll) == C_OK) {
+ if (vstr) {
+diff --git a/tests/unit/type/hash.tcl b/tests/unit/type/hash.tcl
+index 9f8a21b1ce11..931662989d82 100644
+--- a/tests/unit/type/hash.tcl
++++ b/tests/unit/type/hash.tcl
+@@ -540,4 +540,9 @@ start_server {tags {"hash"}} {
+ assert {[r hincrbyfloat myhash float -0.1] eq {1.9}}
+ }
+ }
++
++ test {HINCRBYFLOAT does not allow NaN or Infinity} {
++ assert_error "*value is NaN or Infinity*" {r hincrbyfloat hfoo field +inf}
++ assert_equal 0 [r exists hfoo]
++ }
+ }
diff --git a/huawei-deps-jemalloc-support-riscv.patch b/huawei-deps-jemalloc-support-riscv.patch
new file mode 100644
index 0000000..2a486b9
--- /dev/null
+++ b/huawei-deps-jemalloc-support-riscv.patch
@@ -0,0 +1,62 @@
+From 1b9b76419cf0b6c2ff73bb0d02c8c04896bdde20 Mon Sep 17 00:00:00 2001
+From: yangyanchao <yangyanchao6@huawei.com>
+Date: Wed, 11 Nov 2020 17:49:37 +0800
+Subject: [PATCH] jemalloc_support_riscv
+
+---
+ deps/jemalloc/config.guess | 3 +++
+ deps/jemalloc/config.sub | 2 ++
+ deps/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in | 3 +++
+ 3 files changed, 8 insertions(+)
+
+diff --git a/deps/jemalloc/config.guess b/deps/jemalloc/config.guess
+index 1f5c50c..e5a8c92 100755
+--- a/deps/jemalloc/config.guess
++++ b/deps/jemalloc/config.guess
+@@ -1001,6 +1001,9 @@ EOF
+ ppcle:Linux:*:*)
+ echo powerpcle-unknown-linux-${LIBC}
+ exit ;;
++ riscv32:Linux:*:* | riscv64:Linux:*:*)
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
++ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
+ exit ;;
+diff --git a/deps/jemalloc/config.sub b/deps/jemalloc/config.sub
+index 0ccff77..76df7ee 100755
+--- a/deps/jemalloc/config.sub
++++ b/deps/jemalloc/config.sub
+@@ -302,6 +302,7 @@ case $basic_machine in
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle \
+ | pyramid \
++ | riscv32 | riscv64 \
+ | rl78 | rx \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+@@ -423,6 +424,7 @@ case $basic_machine in
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+ | pyramid-* \
++ | riscv32-* | riscv64-* \
+ | rl78-* | romp-* | rs6000-* | rx-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+diff --git a/deps/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in b/deps/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in
+index 8536a3e..cfbe169 100644
+--- a/deps/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in
++++ b/deps/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in
+@@ -256,6 +256,9 @@ typedef unsigned szind_t;
+ # ifdef __powerpc__
+ # define LG_QUANTUM 4
+ # endif
++# if defined(__riscv) || defined(__riscv__)
++# define LQ_QUANTUM 4
++# endif
+ # ifdef __s390__
+ # define LG_QUANTUM 4
+ # endif
+--
+1.8.3.1
+
diff --git a/improved-HyperLogLog-cardinality-estimation.patch b/improved-HyperLogLog-cardinality-estimation.patch
new file mode 100644
index 0000000..0a2256b
--- /dev/null
+++ b/improved-HyperLogLog-cardinality-estimation.patch
@@ -0,0 +1,328 @@
+From 1e9a7748716e1cd234893dd858d07ffa77920e41 Mon Sep 17 00:00:00 2001
+From: Otmar Ertl <otmar.ertl@gmail.com>
+Date: Sat, 10 Mar 2018 20:13:21 +0100
+Subject: [PATCH] improved HyperLogLog cardinality estimation
+
+based on method described in https://arxiv.org/abs/1702.01284
+that does not rely on any magic constants
+---
+ src/hyperloglog.c | 230 +++++++++++++++++++++++-----------------------
+ 1 file changed, 117 insertions(+), 113 deletions(-)
+
+diff --git a/src/hyperloglog.c b/src/hyperloglog.c
+index 8ab9d2a30c0..7f5f62445c9 100644
+--- a/src/hyperloglog.c
++++ b/src/hyperloglog.c
+@@ -192,6 +192,7 @@ struct hllhdr {
+ #define HLL_VALID_CACHE(hdr) (((hdr)->card[7] & (1<<7)) == 0)
+
+ #define HLL_P 14 /* The greater is P, the smaller the error. */
++#define HLL_Q (63-HLL_P)
+ #define HLL_REGISTERS (1<<HLL_P) /* With P=14, 16384 registers. */
+ #define HLL_P_MASK (HLL_REGISTERS-1) /* Mask to index register. */
+ #define HLL_BITS 6 /* Enough to count up to 63 leading zeroes. */
+@@ -510,13 +511,9 @@ int hllDenseAdd(uint8_t *registers, unsigned char *ele, size_t elesize) {
+ return hllDenseSet(registers,index,count);
+ }
+
+-/* Compute SUM(2^-reg) in the dense representation.
+- * PE is an array with a pre-computer table of values 2^-reg indexed by reg.
+- * As a side effect the integer pointed by 'ezp' is set to the number
+- * of zero registers. */
+-double hllDenseSum(uint8_t *registers, double *PE, int *ezp) {
+- double E = 0;
+- int j, ez = 0;
++/* Compute the register histogram in the dense representation. */
++void hllDenseRegHisto(uint8_t *registers, int* regHisto) {
++ int j;
+
+ /* Redis default is to use 16384 registers 6 bits each. The code works
+ * with other values by modifying the defines, but for our target value
+@@ -527,47 +524,49 @@ double hllDenseSum(uint8_t *registers, double *PE, int *ezp) {
+ r10, r11, r12, r13, r14, r15;
+ for (j = 0; j < 1024; j++) {
+ /* Handle 16 registers per iteration. */
+- r0 = r[0] & 63; if (r0 == 0) ez++;
+- r1 = (r[0] >> 6 | r[1] << 2) & 63; if (r1 == 0) ez++;
+- r2 = (r[1] >> 4 | r[2] << 4) & 63; if (r2 == 0) ez++;
+- r3 = (r[2] >> 2) & 63; if (r3 == 0) ez++;
+- r4 = r[3] & 63; if (r4 == 0) ez++;
+- r5 = (r[3] >> 6 | r[4] << 2) & 63; if (r5 == 0) ez++;
+- r6 = (r[4] >> 4 | r[5] << 4) & 63; if (r6 == 0) ez++;
+- r7 = (r[5] >> 2) & 63; if (r7 == 0) ez++;
+- r8 = r[6] & 63; if (r8 == 0) ez++;
+- r9 = (r[6] >> 6 | r[7] << 2) & 63; if (r9 == 0) ez++;
+- r10 = (r[7] >> 4 | r[8] << 4) & 63; if (r10 == 0) ez++;
+- r11 = (r[8] >> 2) & 63; if (r11 == 0) ez++;
+- r12 = r[9] & 63; if (r12 == 0) ez++;
+- r13 = (r[9] >> 6 | r[10] << 2) & 63; if (r13 == 0) ez++;
+- r14 = (r[10] >> 4 | r[11] << 4) & 63; if (r14 == 0) ez++;
+- r15 = (r[11] >> 2) & 63; if (r15 == 0) ez++;
+-
+- /* Additional parens will allow the compiler to optimize the
+- * code more with a loss of precision that is not very relevant
+- * here (floating point math is not commutative!). */
+- E += (PE[r0] + PE[r1]) + (PE[r2] + PE[r3]) + (PE[r4] + PE[r5]) +
+- (PE[r6] + PE[r7]) + (PE[r8] + PE[r9]) + (PE[r10] + PE[r11]) +
+- (PE[r12] + PE[r13]) + (PE[r14] + PE[r15]);
++ r0 = r[0] & 63;
++ r1 = (r[0] >> 6 | r[1] << 2) & 63;
++ r2 = (r[1] >> 4 | r[2] << 4) & 63;
++ r3 = (r[2] >> 2) & 63;
++ r4 = r[3] & 63;
++ r5 = (r[3] >> 6 | r[4] << 2) & 63;
++ r6 = (r[4] >> 4 | r[5] << 4) & 63;
++ r7 = (r[5] >> 2) & 63;
++ r8 = r[6] & 63;
++ r9 = (r[6] >> 6 | r[7] << 2) & 63;
++ r10 = (r[7] >> 4 | r[8] << 4) & 63;
++ r11 = (r[8] >> 2) & 63;
++ r12 = r[9] & 63;
++ r13 = (r[9] >> 6 | r[10] << 2) & 63;
++ r14 = (r[10] >> 4 | r[11] << 4) & 63;
++ r15 = (r[11] >> 2) & 63;
++
++ regHisto[r0] += 1;
++ regHisto[r1] += 1;
++ regHisto[r2] += 1;
++ regHisto[r3] += 1;
++ regHisto[r4] += 1;
++ regHisto[r5] += 1;
++ regHisto[r6] += 1;
++ regHisto[r7] += 1;
++ regHisto[r8] += 1;
++ regHisto[r9] += 1;
++ regHisto[r10] += 1;
++ regHisto[r11] += 1;
++ regHisto[r12] += 1;
++ regHisto[r13] += 1;
++ regHisto[r14] += 1;
++ regHisto[r15] += 1;
++
+ r += 12;
+ }
+ } else {
+- for (j = 0; j < HLL_REGISTERS; j++) {
++ for(j = 0; j < HLL_REGISTERS; j++) {
+ unsigned long reg;
+-
+ HLL_DENSE_GET_REGISTER(reg,registers,j);
+- if (reg == 0) {
+- ez++;
+- /* Increment E at the end of the loop. */
+- } else {
+- E += PE[reg]; /* Precomputed 2^(-reg[j]). */
+- }
++ regHisto[reg] += 1;
+ }
+- E += ez; /* Add 2^0 'ez' times. */
+ }
+- *ezp = ez;
+- return E;
+ }
+
+ /* ================== Sparse representation implementation ================= */
+@@ -903,76 +902,96 @@ int hllSparseAdd(robj *o, unsigned char *ele, size_t elesize) {
+ return hllSparseSet(o,index,count);
+ }
+
+-/* Compute SUM(2^-reg) in the sparse representation.
+- * PE is an array with a pre-computer table of values 2^-reg indexed by reg.
+- * As a side effect the integer pointed by 'ezp' is set to the number
+- * of zero registers. */
+-double hllSparseSum(uint8_t *sparse, int sparselen, double *PE, int *ezp, int *invalid) {
+- double E = 0;
+- int ez = 0, idx = 0, runlen, regval;
++/* Compute the register histogram in the sparse representation. */
++void hllSparseRegHisto(uint8_t *sparse, int sparselen, int *invalid, int* regHisto) {
++ int idx = 0, runlen, regval;
+ uint8_t *end = sparse+sparselen, *p = sparse;
+
+ while(p < end) {
+ if (HLL_SPARSE_IS_ZERO(p)) {
+ runlen = HLL_SPARSE_ZERO_LEN(p);
+ idx += runlen;
+- ez += runlen;
+- /* Increment E at the end of the loop. */
++ regHisto[0] += runlen;
+ p++;
+ } else if (HLL_SPARSE_IS_XZERO(p)) {
+ runlen = HLL_SPARSE_XZERO_LEN(p);
+ idx += runlen;
+- ez += runlen;
+- /* Increment E at the end of the loop. */
++ regHisto[0] += runlen;
+ p += 2;
+ } else {
+ runlen = HLL_SPARSE_VAL_LEN(p);
+ regval = HLL_SPARSE_VAL_VALUE(p);
+ idx += runlen;
+- E += PE[regval]*runlen;
++ regHisto[regval] += runlen;
+ p++;
+ }
+ }
+ if (idx != HLL_REGISTERS && invalid) *invalid = 1;
+- E += ez; /* Add 2^0 'ez' times. */
+- *ezp = ez;
+- return E;
+ }
+
+ /* ========================= HyperLogLog Count ==============================
+ * This is the core of the algorithm where the approximated count is computed.
+- * The function uses the lower level hllDenseSum() and hllSparseSum() functions
+- * as helpers to compute the SUM(2^-reg) part of the computation, which is
+- * representation-specific, while all the rest is common. */
+-
+-/* Implements the SUM operation for uint8_t data type which is only used
+- * internally as speedup for PFCOUNT with multiple keys. */
+-double hllRawSum(uint8_t *registers, double *PE, int *ezp) {
+- double E = 0;
+- int j, ez = 0;
++ * The function uses the lower level hllDenseRegHisto() and hllSparseRegHisto()
++ * functions as helpers to compute histogram of register values part of the
++ * computation, which is representation-specific, while all the rest is common. */
++
++/* Implements the register histogram calculation for uint8_t data type
++ * which is only used internally as speedup for PFCOUNT with multiple keys. */
++void hllRawRegHisto(uint8_t *registers, int* regHisto) {
+ uint64_t *word = (uint64_t*) registers;
+ uint8_t *bytes;
++ int j;
+
+ for (j = 0; j < HLL_REGISTERS/8; j++) {
+ if (*word == 0) {
+- ez += 8;
++ regHisto[0] += 8;
+ } else {
+ bytes = (uint8_t*) word;
+- if (bytes[0]) E += PE[bytes[0]]; else ez++;
+- if (bytes[1]) E += PE[bytes[1]]; else ez++;
+- if (bytes[2]) E += PE[bytes[2]]; else ez++;
+- if (bytes[3]) E += PE[bytes[3]]; else ez++;
+- if (bytes[4]) E += PE[bytes[4]]; else ez++;
+- if (bytes[5]) E += PE[bytes[5]]; else ez++;
+- if (bytes[6]) E += PE[bytes[6]]; else ez++;
+- if (bytes[7]) E += PE[bytes[7]]; else ez++;
++ regHisto[bytes[0]] += 1;
++ regHisto[bytes[1]] += 1;
++ regHisto[bytes[2]] += 1;
++ regHisto[bytes[3]] += 1;
++ regHisto[bytes[4]] += 1;
++ regHisto[bytes[5]] += 1;
++ regHisto[bytes[6]] += 1;
++ regHisto[bytes[7]] += 1;
+ }
+ word++;
+ }
+- E += ez; /* 2^(-reg[j]) is 1 when m is 0, add it 'ez' times for every
+- zero register in the HLL. */
+- *ezp = ez;
+- return E;
++}
++
++/* Helper function sigma as defined in
++ * "New cardinality estimation algorithms for HyperLogLog sketches"
++ * Otmar Ertl, arXiv:1702.01284 */
++double hllSigma(double x) {
++ if (x == 1.) return INFINITY;
++ double zPrime;
++ double y = 1;
++ double z = x;
++ do {
++ x *= x;
++ zPrime = z;
++ z += x * y;
++ y += y;
++ } while(zPrime != z);
++ return z;
++}
++
++/* Helper function tau as defined in
++ * "New cardinality estimation algorithms for HyperLogLog sketches"
++ * Otmar Ertl, arXiv:1702.01284 */
++double hllTau(double x) {
++ if (x == 0. || x == 1.) return 0.;
++ double zPrime;
++ double y = 1.0;
++ double z = 1 - x;
++ do {
++ x = sqrt(x);
++ zPrime = z;
++ y *= 0.5;
++ z -= pow(1 - x, 2)*y;
++ } while(zPrime != z);
++ return z / 3;
+ }
+
+ /* Return the approximated cardinality of the set based on the harmonic
+@@ -988,49 +1007,34 @@ double hllRawSum(uint8_t *registers, double *PE, int *ezp) {
+ * keys (no need to work with 6-bit integers encoding). */
+ uint64_t hllCount(struct hllhdr *hdr, int *invalid) {
+ double m = HLL_REGISTERS;
+- double E, alpha = 0.7213/(1+1.079/m);
+- int j, ez; /* Number of registers equal to 0. */
+-
+- /* We precompute 2^(-reg[j]) in a small table in order to
+- * speedup the computation of SUM(2^-register[0..i]). */
+- static int initialized = 0;
+- static double PE[64];
+- if (!initialized) {
+- PE[0] = 1; /* 2^(-reg[j]) is 1 when m is 0. */
+- for (j = 1; j < 64; j++) {
+- /* 2^(-reg[j]) is the same as 1/2^reg[j]. */
+- PE[j] = 1.0/(1ULL << j);
+- }
+- initialized = 1;
+- }
++ double E;
++ int j;
++ double alphaInf = 0.5 / log(2.);
++ int regHisto[HLL_Q+2] = {0};
+
+- /* Compute SUM(2^-register[0..i]). */
++ /* Compute register histogram */
+ if (hdr->encoding == HLL_DENSE) {
+- E = hllDenseSum(hdr->registers,PE,&ez);
++ hllDenseRegHisto(hdr->registers,regHisto);
+ } else if (hdr->encoding == HLL_SPARSE) {
+- E = hllSparseSum(hdr->registers,
+- sdslen((sds)hdr)-HLL_HDR_SIZE,PE,&ez,invalid);
++ hllSparseRegHisto(hdr->registers,
++ sdslen((sds)hdr)-HLL_HDR_SIZE,invalid,regHisto);
+ } else if (hdr->encoding == HLL_RAW) {
+- E = hllRawSum(hdr->registers,PE,&ez);
++ hllRawRegHisto(hdr->registers,regHisto);
+ } else {
+ serverPanic("Unknown HyperLogLog encoding in hllCount()");
+ }
+
+- /* Apply loglog-beta to the raw estimate. See:
+- * "LogLog-Beta and More: A New Algorithm for Cardinality Estimation
+- * Based on LogLog Counting" Jason Qin, Denys Kim, Yumei Tung
+- * arXiv:1612.02284 */
+- double zl = log(ez + 1);
+- double beta = -0.370393911*ez +
+- 0.070471823*zl +
+- 0.17393686*pow(zl,2) +
+- 0.16339839*pow(zl,3) +
+- -0.09237745*pow(zl,4) +
+- 0.03738027*pow(zl,5) +
+- -0.005384159*pow(zl,6) +
+- 0.00042419*pow(zl,7);
+-
+- E = llroundl(alpha*m*(m-ez)*(1/(E+beta)));
++ /* Estimate cardinality form register histogram. See:
++ * "New cardinality estimation algorithms for HyperLogLog sketches"
++ * Otmar Ertl, arXiv:1702.01284 */
++ double z = m * hllTau((m-regHisto[HLL_Q+1])/(double)m);
++ for (j = HLL_Q; j >= 1; --j) {
++ z += regHisto[j];
++ z *= 0.5;
++ }
++ z += m * hllSigma(regHisto[0]/(double)m);
++ E = llroundl(alphaInf*m*m/z);
++
+ return (uint64_t) E;
+ }
+
diff --git a/modify-aarch64-architecture-jemalloc-page-size-from-4k-to-64k.patch b/modify-aarch64-architecture-jemalloc-page-size-from-4k-to-64k.patch
new file mode 100644
index 0000000..bedaaca
--- /dev/null
+++ b/modify-aarch64-architecture-jemalloc-page-size-from-4k-to-64k.patch
@@ -0,0 +1,13 @@
+diff --git a/deps/Makefile b/deps/Makefile
+index e148a33..f1855f3 100644
+--- a/deps/Makefile
++++ b/deps/Makefile
+@@ -77,7 +77,7 @@ JEMALLOC_LDFLAGS= $(LDFLAGS)
+
+ jemalloc: .make-prerequisites
+ @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)
+- cd jemalloc && ./configure --with-lg-quantum=3 --with-jemalloc-prefix=je_ --enable-cc-silence CFLAGS="$(JEMALLOC_CFLAGS)" LDFLAGS="$(JEMALLOC_LDFLAGS)"
++ cd jemalloc && ./configure --with-lg-quantum=3 --with-jemalloc-prefix=je_ --enable-cc-silence CFLAGS="$(JEMALLOC_CFLAGS)" LDFLAGS="$(JEMALLOC_LDFLAGS)" --with-lg-page=16
+ cd jemalloc && $(MAKE) CFLAGS="$(JEMALLOC_CFLAGS)" LDFLAGS="$(JEMALLOC_LDFLAGS)" lib/libjemalloc.a
+
+ .PHONY: jemalloc
diff --git a/redis-sentinel.service b/redis-sentinel.service
new file mode 100644
index 0000000..5e8ae1c
--- /dev/null
+++ b/redis-sentinel.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Redis Sentinel
+After=network.target
+
+[Service]
+ExecStart=/usr/bin/redis-sentinel /etc/redis-sentinel.conf --supervised systemd
+Type=notify
+User=redis
+Group=redis
+RuntimeDirectory=redis
+RuntimeDirectoryMode=0755
+
+[Install]
+WantedBy=multi-user.target
diff --git a/redis.logrotate b/redis.logrotate
new file mode 100644
index 0000000..3a3d185
--- /dev/null
+++ b/redis.logrotate
@@ -0,0 +1,9 @@
+/var/log/redis/*.log {
+ weekly
+ rotate 10
+ copytruncate
+ delaycompress
+ compress
+ notifempty
+ missingok
+}
diff --git a/redis.service b/redis.service
new file mode 100644
index 0000000..e4eff49
--- /dev/null
+++ b/redis.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=Redis persistent key-value database
+After=network.target
+
+[Service]
+ExecStart=/usr/bin/redis-server /etc/redis.conf --supervised systemd
+Type=notify
+User=redis
+Group=redis
+RuntimeDirectory=redis
+RuntimeDirectoryMode=0755
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/redis.spec b/redis.spec
new file mode 100644
index 0000000..fef75c5
--- /dev/null
+++ b/redis.spec
@@ -0,0 +1,181 @@
+Name: redis
+Version: 4.0.14
+Release: 5
+Summary: A persistent key-value database
+License: BSD-3-Clause and MIT
+URL: https://redis.io
+Source0: http://download.redis.io/releases/%{name}-%{version}.tar.gz
+Source1: %{name}.logrotate
+Source2: %{name}-sentinel.service
+Source3: %{name}.service
+
+Patch0001: CVE-2020-14147.patch
+Patch0002: improved-HyperLogLog-cardinality-estimation.patch
+Patch0003: Aesthetic-changes-to-PR.patch
+Patch0004: CVE-2019-10193.patch
+Patch0005: modify-aarch64-architecture-jemalloc-page-size-from-4k-to-64k.patch
+Patch0006: huawei-deps-jemalloc-support-riscv.patch
+Patch0007: CVE-2021-21309.patch
+Patch0008: CVE-2021-3470.patch
+Patch0009: CVE-2021-29478.patch
+Patch0010: CVE-2021-32672.patch
+Patch0011: CVE-2022-36021.patch
+Patch0012: CVE-2023-28856.patch
+
+BuildRequires: systemd gcc
+Requires: /bin/awk
+Requires: logrotate
+Requires(pre): shadow-utils
+Requires(post): systemd
+Requires(preun): systemd
+Requires(postun): systemd
+
+%description
+Redis is an advanced key-value store. It is often referred to as a dattructure server since keys can contain strings, hashes
+,lists, sets anorted sets.
+
+%prep
+%setup
+%patch0001 -p1
+%patch0002 -p1
+%patch0003 -p1
+%patch0004 -p1
+%ifarch aarch64
+%patch0005 -p1
+%endif
+%patch0006 -p1
+%patch0007 -p1
+%patch0008 -p1
+%patch0009 -p1
+%patch0010 -p1
+%patch0011 -p1
+%patch0012 -p1
+%ifarch loongarch64
+%_update_config_guess
+%_update_config_sub
+%endif
+
+sed -i -e 's|^logfile .*$|logfile /var/log/redis/redis.log|g' redis.conf
+sed -i -e '$ alogfile /var/log/redis/sentinel.log' sentinel.conf
+sed -i -e 's|^dir .*$|dir /var/lib/redis|g' redis.conf
+
+%build
+make
+
+%install
+%make_install PREFIX=%{buildroot}%{_prefix}
+install -d %{buildroot}%{_sharedstatedir}/%{name}
+install -d %{buildroot}%{_localstatedir}/log/%{name}
+install -d %{buildroot}%{_localstatedir}/run/%{name}
+install -d %{buildroot}%{_libdir}/%{name}/modules
+install -pDm644 %{SOURCE1} %{buildroot}%{_sysconfdir}/logrotate.d/%{name}
+mkdir -p %{buildroot}%{_unitdir}
+install -pm644 %{SOURCE2} %{buildroot}%{_unitdir}
+install -pm644 %{SOURCE3} %{buildroot}%{_unitdir}
+install -pDm640 %{name}.conf %{buildroot}%{_sysconfdir}/%{name}.conf
+install -pDm640 sentinel.conf %{buildroot}%{_sysconfdir}/%{name}-sentinel.conf
+
+%pre
+getent group %{name} &> /dev/null || \
+groupadd -r %{name} &> /dev/null
+getent passwd %{name} &> /dev/null || \
+useradd -r -g %{name} -d %{_sharedstatedir}/%{name} -s /sbin/nologin \
+-c 'Redis Database Server' %{name} &> /dev/null
+exit 0
+
+%post
+%systemd_post %{name}.service
+%systemd_post %{name}-sentinel.service
+
+%preun
+%systemd_preun %{name}.service
+%systemd_preun %{name}-sentinel.service
+
+%postun
+%systemd_postun_with_restart %{name}.service
+%systemd_postun_with_restart %{name}-sentinel.service
+
+
+%files
+%license COPYING
+%doc BUGS README.md 00-RELEASENOTES MANIFESTO CONTRIBUTING
+%config(noreplace) %{_sysconfdir}/logrotate.d/%{name}
+%attr(0640, redis, root) %config(noreplace) %{_sysconfdir}/%{name}.conf
+%attr(0640, redis, root) %config(noreplace) %{_sysconfdir}/%{name}-sentinel.conf
+%dir %attr(0750, redis, redis) %{_libdir}/%{name}
+%dir %attr(0750, redis, redis) %{_libdir}/%{name}/modules
+%dir %attr(0750, redis, redis) %{_sharedstatedir}/%{name}
+%dir %attr(0750, redis, redis) %{_localstatedir}/log/%{name}
+%{_bindir}/%{name}-*
+%{_unitdir}/%{name}.service
+%{_unitdir}/%{name}-sentinel.service
+
+%changelog
+* Mon May 15 2023 yaoxin <yao_xin001@hoperun.com> - 4.0.14-5
+- Fix CVE-2023-28856
+
+* Mon Mar 27 2023 wushaozheng<wushaozheng@ncti-gba.cn> - 4.0.14-4
+- Fix CVE-2022-36021
+
+* Tue Nov 15 2022 huajingyun<huajingyun@loongson.cn> - 4.0.14-3
+- Update config.guess and config.sub for loongarch
+
+* Tue May 10 2022 chenchen <chen_aka_jan@163.com> - 4.0.14-2
+- License compliance rectification
+
+* Wed Dec 29 2021 zhangjiapeng <zhangjiapeng9@huawei.com> - 4.0.14-1
+- Update to 4.0.14
+
+* Sat Oct 09 2021 yaoxin <yaoxin30@huawei.com> - 4.0.11-18
+- Fix CVE-2021-32672
+
+* Tue Jun 08 2021 wangyue <wangyue92@huawei.com> - 4.0.11-17
+- Fix CVE-2021-29478
+
+* Mon May 31 2021 huanghaitao <huanghaitao8@huawei.com> - 4.0.11-16
+- Completing build dependencies to fix gcc compiler missing error
+
+* Wed Apr 07 2021 wangyue <wangyue92@huawei.com> - 4.0.11-15
+- Fix CVE-2021-3470
+
+* Wed Mar 24 2021 sunguoshuai <sunguoshuai@huawei.com> - 4.0.11-14
+- change patch file in order src.rpm is same in aarch64 and x86_64
+
+* Thu Mar 11 2021 wangxiao <wangxiao65@huawei.com> - 4.0.11-13
+- Fix CVE-2021-21309
+
+* Wed Nov 11 2020 yangyanchao <yangyanchao6@huawei.com> - 4.0.11-12
+- enable dependency package jemalloc of redis to support riscv
+
+* Wed Sep 30 2020 Jiapeng Zhang <zhangjiapeng9@huawei.com> - 4.0.11-11
+- Modify aarch64 architecture jemalloc page size from 4k to 64k
+
+* Mon Sep 21 2020 wangyue <wangyue92@huawei.com> - 4.0.11-10
+- fix CVE-2019-10193
+
+* Mon Jul 20 2020 wangxiao <wangxiao654@huawei.com> - 4.0.11-9
+- fix CVE-2020-14147
+
+* Fri Jun 19 2020 Captain Wei <captain.a.wei@gmail.com> - 4.0.11-8
+- Add some dependency package in building and running phase
+
+* Fri Jun 12 2020 panchenbo <panchenbo@uniontech.com> - 4.0.11-7
+- Type:bugfix
+- ID: NA
+- SUG: restart
+- DESC: Resolve service startup failure whthout no %pre
+
+* Mon Jun 01 2020 huanghaitao <huanghaitao8@huawei.com> - 4.0.11-6
+- Resolve service startup failure
+
+* Tue Mar 17 2020 wangye <wangye54@huawei.com> - 4.0.11-5
+- CVE name fix
+
+* Tue Mar 17 2020 wangye <wangye54@huawei.com> - 4.0.11-4
+- CVE fix
+
+* Wed Jan 15 2020 zhujunhao <zhujunhao5@huawei.com> - 4.0.11-3
+- Modify redis service
+
+* Wed Jan 08 2020 lijin Yang <yanglijin@openeuler.org> - 4.0.11-2
+- Package init
diff --git a/sources b/sources
new file mode 100644
index 0000000..a347a11
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+96ae20ffd68b9daee24b702b754d89f3 redis-4.0.14.tar.gz