From d415da7ae571c3854550564a1764e763cc83c921 Mon Sep 17 00:00:00 2001 From: ellie timoney Date: Wed, 19 May 2021 13:39:34 +1000 Subject: [PATCH] strhash: replace ad-hoc algorithm with seeded djb2 Part of CVE-2021-33582 --- lib/strhash.c | 37 ++++++++++++++++++++++++++----------- lib/strhash.h | 6 +++++- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/lib/strhash.c b/lib/strhash.c index 3457abab27..8f68d13867 100644 --- a/lib/strhash.c +++ b/lib/strhash.c @@ -57,17 +57,32 @@ #include "assert.h" #include "strhash.h" -unsigned strhash(const char *string) +#include "lib/strhash.h" + +/* The well-known djb2 algorithm (e.g. http://www.cse.yorku.ca/~oz/hash.html), + * with the addition of an optional seed to limit predictability. + * + * XXX return type 'unsigned' for back-compat to previous version, but + * XXX ought to be 'uint32_t' + */ +unsigned strhash_seeded_djb2(uint32_t seed, const char *string) { - unsigned ret_val = 0; - int i; + const unsigned char *ustr = (const unsigned char *) string; + unsigned hash = 5381; + int c; + + if (seed) { + /* treat the bytes of the seed as a prefix to the string */ + unsigned i; + for (i = 0; i < sizeof seed; i++) { + c = seed & 0xff; + hash = ((hash << 5) + hash) ^ c; + seed >>= 8; + } + } + + while ((c = *ustr++)) + hash = ((hash << 5) + hash) ^ c; - while (*string) - { - i = (int) *string; - ret_val ^= i; - ret_val <<= 1; - string ++; - } - return ret_val; + return hash; } diff --git a/lib/strhash.h b/lib/strhash.h index 3ecb432a34..dc6f6b759f 100644 --- a/lib/strhash.h +++ b/lib/strhash.h @@ -43,6 +43,7 @@ */ #ifndef _STRHASH_H_ +#include #ifdef HAVE_UNISTD_H #include @@ -57,6 +58,9 @@ #include #include -unsigned strhash(const char *string); +unsigned strhash_seeded_djb2(uint32_t seed, const char *string); + +#define strhash(in) strhash_seeded_djb2((0), (in)) +#define strhash_seeded(sd, in) strhash_seeded_djb2((sd), (in)) #endif /* _STRHASH_H_ */