summaryrefslogtreecommitdiff
path: root/src/intset.c
diff options
context:
space:
mode:
authorOran Agra <oran@redislabs.com>2020-11-02 09:35:37 +0200
committerOran Agra <oran@redislabs.com>2020-12-06 14:54:34 +0200
commit3716950cfc389c0f7ed13fac5bd205173c2d8189 (patch)
tree7e9e73ac7ffda406e85a19c1b365a1a13deab81d /src/intset.c
parent5b44631397787a65327fcab77f7df37862286ed9 (diff)
downloadredis-3716950cfc389c0f7ed13fac5bd205173c2d8189.tar.gz
Sanitize dump payload: validate no duplicate records in hash/zset/intset
If RESTORE passes successfully with full sanitization, we can't affort to crash later on assertion due to duplicate records in a hash when converting it form ziplist to dict. This means that when doing full sanitization, we must make sure there are no duplicate records in any of the collections.
Diffstat (limited to 'src/intset.c')
-rw-r--r--src/intset.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/src/intset.c b/src/intset.c
index 964a41187..54afae875 100644
--- a/src/intset.c
+++ b/src/intset.c
@@ -284,8 +284,11 @@ size_t intsetBlobLen(intset *is) {
return sizeof(intset)+intrev32ifbe(is->length)*intrev32ifbe(is->encoding);
}
-int intsetValidateIntegrity(const unsigned char *p, size_t size) {
- const intset *is = (const intset *)p;
+/* Validate the integrity of the data stracture.
+ * when `deep` is 0, only the integrity of the header is validated.
+ * when `deep` is 1, we make sure there are no duplicate or out of order records. */
+int intsetValidateIntegrity(const unsigned char *p, size_t size, int deep) {
+ intset *is = (intset *)p;
/* check that we can actually read the header. */
if (size < sizeof(*is))
return 0;
@@ -308,6 +311,22 @@ int intsetValidateIntegrity(const unsigned char *p, size_t size) {
if (sizeof(*is) + count*record_size != size)
return 0;
+ /* check that the set is not empty. */
+ if (count==0)
+ return 0;
+
+ if (!deep)
+ return 1;
+
+ /* check that there are no dup or out of order records. */
+ int64_t prev = _intsetGet(is,0);
+ for (uint32_t i=1; i<count; i++) {
+ int64_t cur = _intsetGet(is,i);
+ if (cur <= prev)
+ return 0;
+ prev = cur;
+ }
+
return 1;
}