Blame SOURCES/cyrus-imapd-CVE-2021-33582.patch

d3a111
diff --git a/imap/http_dav.c b/imap/http_dav.c
d3a111
index d5f7c114a2..abc6da42ca 100644
d3a111
--- a/imap/http_dav.c
d3a111
+++ b/imap/http_dav.c
d3a111
@@ -6108,7 +6108,7 @@ EXPORTED int meth_propfind(struct transaction_t *txn, void *params)
d3a111
     xmlDocPtr indoc = NULL, outdoc = NULL;
d3a111
     xmlNodePtr root, cur = NULL, props = NULL;
d3a111
     xmlNsPtr ns[NUM_NAMESPACE];
d3a111
-    struct hash_table ns_table = { 0, NULL, NULL };
d3a111
+    struct hash_table ns_table = HASH_TABLE_INITIALIZER;
d3a111
     struct propfind_ctx fctx;
d3a111
 
d3a111
     memset(&fctx, 0, sizeof(struct propfind_ctx));
d3a111
@@ -8083,7 +8083,7 @@ int meth_report(struct transaction_t *txn, void *params)
d3a111
     xmlNodePtr inroot = NULL, outroot = NULL, cur, prop = NULL, props = NULL;
d3a111
     const struct report_type_t *report = NULL;
d3a111
     xmlNsPtr ns[NUM_NAMESPACE];
d3a111
-    struct hash_table ns_table = { 0, NULL, NULL };
d3a111
+    struct hash_table ns_table = HASH_TABLE_INITIALIZER;
d3a111
     struct propfind_ctx fctx;
d3a111
 
d3a111
     memset(&fctx, 0, sizeof(struct propfind_ctx));
d3a111
diff --git a/imap/jmap_mail.c b/imap/jmap_mail.c
d3a111
index 7f2d9cb563..84845d273b 100644
d3a111
--- a/imap/jmap_mail.c
d3a111
+++ b/imap/jmap_mail.c
d3a111
@@ -4334,7 +4334,7 @@ static void _email_querychanges_collapsed(jmap_req_t *req,
d3a111
     memset(&touched_ids, 0, sizeof(hash_table));
d3a111
     construct_hash_table(&touched_ids, mdcount + 1, 0);
d3a111
 
d3a111
-    hashu64_table touched_cids = HASH_TABLE_INITIALIZER;
d3a111
+    hashu64_table touched_cids = HASHU64_TABLE_INITIALIZER;
d3a111
     memset(&touched_cids, 0, sizeof(hashu64_table));
d3a111
     construct_hashu64_table(&touched_cids, mdcount + 1, 0);
d3a111
 
d3a111
diff --git a/lib/hash.c b/lib/hash.c
d3a111
index 639b6997e6..593f1bf968 100644
d3a111
--- a/lib/hash.c
d3a111
+++ b/lib/hash.c
d3a111
@@ -43,10 +43,11 @@ EXPORTED hash_table *construct_hash_table(hash_table *table, size_t size, int us
d3a111
       assert(table);
d3a111
       assert(size);
d3a111
 
d3a111
-      table->size  = size;
d3a111
+      table->size = size;
d3a111
+      table->seed = rand(); /* might be zero, that's okay */
d3a111
 
d3a111
       /* Allocate the table -- different for using memory pools and not */
d3a111
-      if(use_mpool) {
d3a111
+      if (use_mpool) {
d3a111
           /* Allocate an initial memory pool for 32 byte keys + the hash table
d3a111
            * + the buckets themselves */
d3a111
           table->pool =
d3a111
@@ -72,7 +73,7 @@ EXPORTED hash_table *construct_hash_table(hash_table *table, size_t size, int us
d3a111
 
d3a111
 EXPORTED void *hash_insert(const char *key, void *data, hash_table *table)
d3a111
 {
d3a111
-      unsigned val = strhash(key) % table->size;
d3a111
+      unsigned val = strhash_seeded(table->seed, key) % table->size;
d3a111
       bucket *ptr, *newptr;
d3a111
       bucket **prev;
d3a111
 
d3a111
@@ -159,7 +160,7 @@ EXPORTED void *hash_lookup(const char *key, hash_table *table)
d3a111
       if (!table->size)
d3a111
           return NULL;
d3a111
 
d3a111
-      val = strhash(key) % table->size;
d3a111
+      val = strhash_seeded(table->seed, key) % table->size;
d3a111
 
d3a111
       if (!(table->table)[val])
d3a111
             return NULL;
d3a111
@@ -183,7 +184,7 @@ EXPORTED void *hash_lookup(const char *key, hash_table *table)
d3a111
  * since it will leak memory until you get rid of the entire hash table */
d3a111
 EXPORTED void *hash_del(const char *key, hash_table *table)
d3a111
 {
d3a111
-      unsigned val = strhash(key) % table->size;
d3a111
+      unsigned val = strhash_seeded(table->seed, key) % table->size;
d3a111
       bucket *ptr, *last = NULL;
d3a111
 
d3a111
       if (!(table->table)[val])
d3a111
diff --git a/lib/hash.h b/lib/hash.h
d3a111
index e49037d614..e476de77da 100644
d3a111
--- a/lib/hash.h
d3a111
+++ b/lib/hash.h
d3a111
@@ -3,10 +3,11 @@
d3a111
 #define HASH__H
d3a111
 
d3a111
 #include <stddef.h>           /* For size_t     */
d3a111
+#include <stdint.h>
d3a111
 #include "mpool.h"
d3a111
 #include "strarray.h"
d3a111
 
d3a111
-#define HASH_TABLE_INITIALIZER {0, NULL, NULL}
d3a111
+#define HASH_TABLE_INITIALIZER {0, 0, NULL, NULL}
d3a111
 
d3a111
 /*
d3a111
 ** A hash table consists of an array of these buckets.  Each bucket
d3a111
@@ -32,6 +33,7 @@ typedef struct bucket {
d3a111
 
d3a111
 typedef struct hash_table {
d3a111
     size_t size;
d3a111
+    uint32_t seed;
d3a111
     bucket **table;
d3a111
     struct mpool *pool;
d3a111
 } hash_table;
d3a111
diff --git a/lib/strhash.c b/lib/strhash.c
d3a111
index d7c1741d2a..1b3251db73 100644
d3a111
--- a/lib/strhash.c
d3a111
+++ b/lib/strhash.c
d3a111
@@ -42,17 +42,32 @@
d3a111
 
d3a111
 #include "config.h"
d3a111
 
d3a111
-EXPORTED unsigned strhash(const char *string)
d3a111
+#include "lib/strhash.h"
d3a111
+
d3a111
+/* The well-known djb2 algorithm (e.g. http://www.cse.yorku.ca/~oz/hash.html),
d3a111
+ * with the addition of an optional seed to limit predictability.
d3a111
+ *
d3a111
+ * XXX return type 'unsigned' for back-compat to previous version, but
d3a111
+ * XXX ought to be 'uint32_t'
d3a111
+ */
d3a111
+EXPORTED unsigned strhash_seeded_djb2(uint32_t seed, const char *string)
d3a111
 {
d3a111
-      unsigned ret_val = 0;
d3a111
-      int i;
d3a111
+    const unsigned char *ustr = (const unsigned char *) string;
d3a111
+    unsigned hash = 5381;
d3a111
+    int c;
d3a111
 
d3a111
-      while (*string)
d3a111
-      {
d3a111
-            i = (int) *string;
d3a111
-            ret_val ^= i;
d3a111
-            ret_val <<= 1;
d3a111
-            string ++;
d3a111
-      }
d3a111
-      return ret_val;
d3a111
+    if (seed) {
d3a111
+        /* treat the bytes of the seed as a prefix to the string */
d3a111
+        unsigned i;
d3a111
+        for (i = 0; i < sizeof seed; i++) {
d3a111
+            c = seed & 0xff;
d3a111
+            hash = ((hash << 5) + hash) ^ c;
d3a111
+            seed >>= 8;
d3a111
+        }
d3a111
+    }
d3a111
+
d3a111
+    while ((c = *ustr++))
d3a111
+        hash = ((hash << 5) + hash) ^ c;
d3a111
+
d3a111
+    return hash;
d3a111
 }
d3a111
diff --git a/lib/strhash.h b/lib/strhash.h
d3a111
index 34533fdffa..27339bb288 100644
d3a111
--- a/lib/strhash.h
d3a111
+++ b/lib/strhash.h
d3a111
@@ -41,7 +41,11 @@
d3a111
  */
d3a111
 
d3a111
 #ifndef _STRHASH_H_
d3a111
+#include <stdint.h>
d3a111
 
d3a111
-unsigned strhash(const char *string);
d3a111
+unsigned strhash_seeded_djb2(uint32_t seed, const char *string);
d3a111
+
d3a111
+#define strhash(in)             strhash_seeded_djb2((0),  (in))
d3a111
+#define strhash_seeded(sd, in)  strhash_seeded_djb2((sd), (in))
d3a111
 
d3a111
 #endif /* _STRHASH_H_ */