Skip to content

Commit 924f770

Browse files
carlescufirlubos
authored andcommitted
[nrf fromtree] 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 <[email protected]> (cherry picked from commit 7c15b08)
1 parent 9a1e1dc commit 924f770

File tree

1 file changed

+14
-5
lines changed

1 file changed

+14
-5
lines changed

lib/hash/hash_func32_murmur3.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
#include <stddef.h>
88
#include <stdint.h>
9+
#include <zephyr/toolchain.h>
10+
#include <zephyr/sys/util.h>
911

1012
static inline uint32_t murmur_32_scramble(uint32_t k)
1113
{
@@ -16,18 +18,25 @@ static inline uint32_t murmur_32_scramble(uint32_t k)
1618
return k;
1719
}
1820

21+
#define _LOOP(_GET) \
22+
for (; n >= sizeof(uint32_t); n -= sizeof(uint32_t), str += sizeof(uint32_t)) { \
23+
k = _GET; \
24+
h ^= murmur_32_scramble(k); \
25+
h = (h << 13) | (h >> 19); \
26+
h = h * 5 + 0xe6546b64; \
27+
}
28+
1929
uint32_t sys_hash32_murmur3(const char *str, size_t n)
2030
{
2131
uint32_t k;
2232
/* seed of 0 */
2333
uint32_t h = 0;
2434
const size_t len = n;
2535

26-
for (; n >= sizeof(uint32_t); n -= sizeof(uint32_t), str += sizeof(uint32_t)) {
27-
k = *(const uint32_t *)str;
28-
h ^= murmur_32_scramble(k);
29-
h = (h << 13) | (h >> 19);
30-
h = h * 5 + 0xe6546b64;
36+
if (IS_ALIGNED(str, sizeof(uint32_t))) {
37+
_LOOP(*(const uint32_t *)str);
38+
} else {
39+
_LOOP(UNALIGNED_GET((const uint32_t *)str));
3140
}
3241

3342
for (k = 0; n != 0; --n, ++str) {

0 commit comments

Comments
 (0)