Browse Source

Merge pull request #726 from grynca/master

fix unaligned access in murmur hash
Micha Mettke 7 years ago
parent
commit
19c14bb777
2 changed files with 36 additions and 24 deletions
  1. 18 12
      nuklear.h
  2. 18 12
      src/nuklear_util.c

+ 18 - 12
nuklear.h

@@ -7164,23 +7164,29 @@ nk_murmur_hash(const void * key, int len, nk_hash seed)
 {
     /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/
     #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r)))
-    union {const nk_uint *i; const nk_byte *b;} conv = {0};
+
+    nk_uint h1 = seed;
+    nk_uint k1;
     const nk_byte *data = (const nk_byte*)key;
+    const nk_byte *keyptr = data;
+    nk_byte *k1ptr;
+    const int bsize = sizeof(k1);
     const int nblocks = len/4;
-    nk_uint h1 = seed;
+
     const nk_uint c1 = 0xcc9e2d51;
     const nk_uint c2 = 0x1b873593;
     const nk_byte *tail;
-    const nk_uint *blocks;
-    nk_uint k1;
     int i;
 
     /* body */
     if (!key) return 0;
-    conv.b = (data + nblocks*4);
-    blocks = (const nk_uint*)conv.i;
-    for (i = -nblocks; i; ++i) {
-        k1 = blocks[i];
+    for (i = 0; i < nblocks; ++i, keyptr += bsize) {
+        k1ptr = (nk_byte*)&k1;
+        k1ptr[0] = keyptr[0];
+        k1ptr[1] = keyptr[1];
+        k1ptr[2] = keyptr[2];
+        k1ptr[3] = keyptr[3];
+
         k1 *= c1;
         k1 = NK_ROTL(k1,15);
         k1 *= c2;
@@ -7194,15 +7200,15 @@ nk_murmur_hash(const void * key, int len, nk_hash seed)
     tail = (const nk_byte*)(data + nblocks*4);
     k1 = 0;
     switch (len & 3) {
-    case 3: k1 ^= (nk_uint)(tail[2] << 16); /* fallthrough */
-    case 2: k1 ^= (nk_uint)(tail[1] << 8u); /* fallthrough */
-    case 1: k1 ^= tail[0];
+        case 3: k1 ^= (nk_uint)(tail[2] << 16); /* fallthrough */
+        case 2: k1 ^= (nk_uint)(tail[1] << 8u); /* fallthrough */
+        case 1: k1 ^= tail[0];
             k1 *= c1;
             k1 = NK_ROTL(k1,15);
             k1 *= c2;
             h1 ^= k1;
             break;
-    default: break;
+        default: break;
     }
 
     /* finalization */

+ 18 - 12
src/nuklear_util.c

@@ -914,23 +914,29 @@ nk_murmur_hash(const void * key, int len, nk_hash seed)
 {
     /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/
     #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r)))
-    union {const nk_uint *i; const nk_byte *b;} conv = {0};
+
+    nk_uint h1 = seed;
+    nk_uint k1;
     const nk_byte *data = (const nk_byte*)key;
+    const nk_byte *keyptr = data;
+    nk_byte *k1ptr;
+    const int bsize = sizeof(k1);
     const int nblocks = len/4;
-    nk_uint h1 = seed;
+
     const nk_uint c1 = 0xcc9e2d51;
     const nk_uint c2 = 0x1b873593;
     const nk_byte *tail;
-    const nk_uint *blocks;
-    nk_uint k1;
     int i;
 
     /* body */
     if (!key) return 0;
-    conv.b = (data + nblocks*4);
-    blocks = (const nk_uint*)conv.i;
-    for (i = -nblocks; i; ++i) {
-        k1 = blocks[i];
+    for (i = 0; i < nblocks; ++i, keyptr += bsize) {
+        k1ptr = (nk_byte*)&k1;
+        k1ptr[0] = keyptr[0];
+        k1ptr[1] = keyptr[1];
+        k1ptr[2] = keyptr[2];
+        k1ptr[3] = keyptr[3];
+
         k1 *= c1;
         k1 = NK_ROTL(k1,15);
         k1 *= c2;
@@ -944,15 +950,15 @@ nk_murmur_hash(const void * key, int len, nk_hash seed)
     tail = (const nk_byte*)(data + nblocks*4);
     k1 = 0;
     switch (len & 3) {
-    case 3: k1 ^= (nk_uint)(tail[2] << 16); /* fallthrough */
-    case 2: k1 ^= (nk_uint)(tail[1] << 8u); /* fallthrough */
-    case 1: k1 ^= tail[0];
+        case 3: k1 ^= (nk_uint)(tail[2] << 16); /* fallthrough */
+        case 2: k1 ^= (nk_uint)(tail[1] << 8u); /* fallthrough */
+        case 1: k1 ^= tail[0];
             k1 *= c1;
             k1 = NK_ROTL(k1,15);
             k1 *= c2;
             h1 ^= k1;
             break;
-    default: break;
+        default: break;
     }
 
     /* finalization */