From: Dmitry Volyntsev Date: Thu, 17 Sep 2026 21:51:00 +0000 (-0700) Subject: Avoid undefined shifts in MurmurHash2 X-Git-Tag: 1.0.2~37 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=d05bcb9bd58897578c2f2a7c384add9d87fbc623;p=njs.git Avoid undefined shifts in MurmurHash2 Previously, input bytes were promoted to signed int before being shifted into a hash word. A byte with its high bit set could make the 24-bit shift undefined. The fix is to cast input bytes to uint32_t before shifting. This preserves the hash result and avoids undefined behavior under UBSan. --- diff --git a/src/njs_murmur_hash.c b/src/njs_murmur_hash.c index f5ee0079..5256ff80 100644 --- a/src/njs_murmur_hash.c +++ b/src/njs_murmur_hash.c @@ -19,10 +19,10 @@ njs_murmur_hash2(const void *data, size_t len) h = 0 ^ (uint32_t) len; while (len >= 4) { - k = p[0]; - k |= p[1] << 8; - k |= p[2] << 16; - k |= p[3] << 24; + k = (uint32_t) p[0]; + k |= (uint32_t) p[1] << 8; + k |= (uint32_t) p[2] << 16; + k |= (uint32_t) p[3] << 24; k *= m; k ^= k >> 24; @@ -37,10 +37,10 @@ njs_murmur_hash2(const void *data, size_t len) switch (len) { case 3: - h ^= p[2] << 16; + h ^= (uint32_t) p[2] << 16; /* Fall through. */ case 2: - h ^= p[1] << 8; + h ^= (uint32_t) p[1] << 8; /* Fall through. */ case 1: h ^= p[0]; @@ -66,10 +66,10 @@ njs_murmur_hash2_uint32(const void *data) p = data; - k = p[0]; - k |= p[1] << 8; - k |= p[2] << 16; - k |= p[3] << 24; + k = (uint32_t) p[0]; + k |= (uint32_t) p[1] << 8; + k |= (uint32_t) p[2] << 16; + k |= (uint32_t) p[3] << 24; k *= m; k ^= k >> 24;