summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOran Agra <oran@redislabs.com>2021-10-04 12:09:25 +0300
committerGitHub <noreply@github.com>2021-10-04 12:09:25 +0300
commit7cb89a5a1cc8ee0b003a36b2eba42573c09c45f9 (patch)
treef230718f561386a8e5698aae3e298cf942265dfe
parent24cc0b984d4ed5045c6ff125b0e619b6ce5ea9c6 (diff)
downloadredis-7cb89a5a1cc8ee0b003a36b2eba42573c09c45f9.tar.gz
Fix Integer overflow issue with intsets (CVE-2021-32687) (#9586)
The vulnerability involves changing the default set-max-intset-entries configuration parameter to a very large value and constructing specially crafted commands to manipulate sets
-rw-r--r--src/intset.c3
-rw-r--r--src/rdb.c4
-rw-r--r--src/t_set.c5
3 files changed, 9 insertions, 3 deletions
diff --git a/src/intset.c b/src/intset.c
index 4a9214864..0e8365b46 100644
--- a/src/intset.c
+++ b/src/intset.c
@@ -104,7 +104,8 @@ intset *intsetNew(void) {
/* Resize the intset */
static intset *intsetResize(intset *is, uint32_t len) {
- uint32_t size = len*intrev32ifbe(is->encoding);
+ uint64_t size = (uint64_t)len*intrev32ifbe(is->encoding);
+ assert(size <= SIZE_MAX - sizeof(intset));
is = zrealloc(is,sizeof(intset)+size);
return is;
}
diff --git a/src/rdb.c b/src/rdb.c
index 555bc2ecb..c2f56d80c 100644
--- a/src/rdb.c
+++ b/src/rdb.c
@@ -1690,7 +1690,9 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, sds key, int dbid, int *error) {
if (len == 0) goto emptykey;
/* Use a regular set when there are too many entries. */
- if (len > server.set_max_intset_entries) {
+ size_t max_entries = server.set_max_intset_entries;
+ if (max_entries >= 1<<30) max_entries = 1<<30;
+ if (len > max_entries) {
o = createSetObject();
/* It's faster to expand the dict to the right size asap in order
* to avoid rehashing */
diff --git a/src/t_set.c b/src/t_set.c
index 383d0c692..3823f1cbb 100644
--- a/src/t_set.c
+++ b/src/t_set.c
@@ -66,7 +66,10 @@ int setTypeAdd(robj *subject, sds value) {
if (success) {
/* Convert to regular set when the intset contains
* too many entries. */
- if (intsetLen(subject->ptr) > server.set_max_intset_entries)
+ size_t max_entries = server.set_max_intset_entries;
+ /* limit to 1G entries due to intset internals. */
+ if (max_entries >= 1<<30) max_entries = 1<<30;
+ if (intsetLen(subject->ptr) > max_entries)
setTypeConvert(subject,OBJ_ENCODING_HT);
return 1;
}