Browse Source

lib: hash: murmur3: Account for unaligned 32-bit access

The code was casting a byte array to 32-bit words without accounting for
alignment. On some platforms (e.g. Arm Cortex-M with multiple load/store
instructions) this will fault. Fix it by using the UNALIGED_GET() macro
whenever the array is passed unaligned.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
pull/89054/head
Carles Cufi 2 months ago committed by Benjamin Cabé
parent
commit
7c15b08a7e
  1. 19
      lib/hash/hash_func32_murmur3.c

19
lib/hash/hash_func32_murmur3.c

@ -6,6 +6,8 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <zephyr/toolchain.h>
#include <zephyr/sys/util.h>
static inline uint32_t murmur_32_scramble(uint32_t k) static inline uint32_t murmur_32_scramble(uint32_t k)
{ {
@ -16,6 +18,14 @@ static inline uint32_t murmur_32_scramble(uint32_t k)
return k; return k;
} }
#define _LOOP(_GET) \
for (; n >= sizeof(uint32_t); n -= sizeof(uint32_t), str += sizeof(uint32_t)) { \
k = _GET; \
h ^= murmur_32_scramble(k); \
h = (h << 13) | (h >> 19); \
h = h * 5 + 0xe6546b64; \
}
uint32_t sys_hash32_murmur3(const char *str, size_t n) uint32_t sys_hash32_murmur3(const char *str, size_t n)
{ {
uint32_t k; uint32_t k;
@ -23,11 +33,10 @@ uint32_t sys_hash32_murmur3(const char *str, size_t n)
uint32_t h = 0; uint32_t h = 0;
const size_t len = n; const size_t len = n;
for (; n >= sizeof(uint32_t); n -= sizeof(uint32_t), str += sizeof(uint32_t)) { if (IS_ALIGNED(str, sizeof(uint32_t))) {
k = *(const uint32_t *)str; _LOOP(*(const uint32_t *)str);
h ^= murmur_32_scramble(k); } else {
h = (h << 13) | (h >> 19); _LOOP(UNALIGNED_GET((const uint32_t *)str));
h = h * 5 + 0xe6546b64;
} }
for (k = 0; n != 0; --n, ++str) { for (k = 0; n != 0; --n, ++str) {

Loading…
Cancel
Save