aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Camillo Lugaresi <camillol@google.com>2017-11-17 14:21:13 -0800
committerGravatar Camillo Lugaresi <camillol@google.com>2017-11-28 10:30:53 -0800
commit962722cbc02c5b1e00baaaad3ddeebd95bc3906d (patch)
tree302836e74fe021f494e3ccce87e4f915db020363 /src/core
parent1972e5ce741dab2ffe671e0dfde00288005f19f4 (diff)
Fix alignment issue in gpr_murmur_hash3
This function cast a void* to a uint32_t*. This is invalid, since a uint32_t* must be 32-bit-aligned, while the input key clearly isn't. Even though the function later uses memcpy to access the memory, by that point the compiler is allowed to assume that the pointer is aligned, and so it can output code that does an unaligned memory access. In practice, this resulted in a crash on some devices when this code is compiled with optimizations for 32-bit ARM with the Android NDK r14.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/lib/support/murmur_hash.cc19
1 files changed, 8 insertions, 11 deletions
diff --git a/src/core/lib/support/murmur_hash.cc b/src/core/lib/support/murmur_hash.cc
index 4e08579a1d..2f0e71a53c 100644
--- a/src/core/lib/support/murmur_hash.cc
+++ b/src/core/lib/support/murmur_hash.cc
@@ -30,22 +30,19 @@
(h) ^= (h) >> 16;
uint32_t gpr_murmur_hash3(const void* key, size_t len, uint32_t seed) {
- const uint8_t* data = (const uint8_t*)key;
- const size_t nblocks = len / 4;
- int i;
-
uint32_t h1 = seed;
uint32_t k1;
const uint32_t c1 = 0xcc9e2d51;
const uint32_t c2 = 0x1b873593;
- const uint32_t* blocks = ((const uint32_t*)key) + nblocks;
- const uint8_t* tail = (const uint8_t*)(data + nblocks * 4);
+ const uint8_t* keyptr = (const uint8_t*)key;
+ const size_t bsize = sizeof(k1);
+ const size_t nblocks = len / bsize;
/* body */
- for (i = -(int)nblocks; i; i++) {
- memcpy(&k1, blocks + i, sizeof(uint32_t));
+ for (size_t i = 0; i < nblocks; i++, keyptr += bsize) {
+ memcpy(&k1, keyptr, bsize);
k1 *= c1;
k1 = ROTL32(k1, 15);
@@ -61,13 +58,13 @@ uint32_t gpr_murmur_hash3(const void* key, size_t len, uint32_t seed) {
/* tail */
switch (len & 3) {
case 3:
- k1 ^= ((uint32_t)tail[2]) << 16;
+ k1 ^= ((uint32_t)keyptr[2]) << 16;
/* fallthrough */
case 2:
- k1 ^= ((uint32_t)tail[1]) << 8;
+ k1 ^= ((uint32_t)keyptr[1]) << 8;
/* fallthrough */
case 1:
- k1 ^= tail[0];
+ k1 ^= keyptr[0];
k1 *= c1;
k1 = ROTL32(k1, 15);
k1 *= c2;