UB Sanitizer report:

lib/hash.h:219:17: runtime error: load of misaligned address
0x7ffc164a88b4 for type 'const uint64_t', which requires 8 byte
alignment

    #0 in hash_words_inline lib/hash.h:219
    #1 in hash_words lib/hash.h:297
    [...]

Signed-off-by: Mike Pattrick <[email protected]>
---
 lib/hash.h | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 66 insertions(+), 3 deletions(-)

diff --git a/lib/hash.h b/lib/hash.h
index 60a39a40b..ca468c52c 100644
--- a/lib/hash.h
+++ b/lib/hash.h
@@ -187,6 +187,16 @@ static inline uint32_t hash_finish(uint64_t hash, uint64_t 
final)
     return hash ^ (uint32_t)hash >> 16; /* Increase entropy in LSBs. */
 }
 
+static inline uint32_t
+hash_finish32(uint64_t hash, uint32_t final, uint32_t semifinal)
+{
+    /* The finishing multiplier 0x805204f3 has been experimentally
+     * derived to pass the testsuite hash tests. */
+    hash = _mm_crc32_u32(hash, semifinal);
+    hash = _mm_crc32_u32(hash, final) * 0x805204f3;
+    return hash ^ ((uint32_t) hash >> 16); /* Increase entropy in LSBs. */
+}
+
 /* Returns the hash of the 'n' 32-bit words at 'p_', starting from 'basis'.
  * We access 'p_' as a uint64_t pointer, which is fine for __SSE_4_2__.
  *
@@ -232,6 +242,55 @@ hash_words_inline(const uint32_t p_[], size_t n_words, 
uint32_t basis)
     return hash_finish(hash1, hash2 << 32 | hash3);
 }
 
+static inline uint32_t
+hash_words_32aligned(const uint32_t p_[], size_t n_words, uint32_t basis)
+{
+    const uint32_t *p = (const void *) p_;
+    uint32_t hash1 = basis;
+    uint32_t hash2 = 0;
+    uint32_t hash3 = n_words;
+    const uint32_t *endp = (const uint32_t *) p + n_words;
+    const uint32_t *limit = p + n_words - 6;
+
+    while (p <= limit) {
+        hash1 = _mm_crc32_u32(hash1, p[0]);
+        hash1 = _mm_crc32_u32(hash1, p[1]);
+        hash2 = _mm_crc32_u32(hash2, p[2]);
+        hash2 = _mm_crc32_u32(hash2, p[3]);
+        hash3 = _mm_crc32_u32(hash3, p[4]);
+        hash3 = _mm_crc32_u32(hash3, p[5]);
+        p += 6;
+    }
+    switch (endp - (const uint32_t *) p) {
+    case 1:
+        hash1 = _mm_crc32_u32(hash1, p[0]);
+        break;
+    case 2:
+        hash1 = _mm_crc32_u32(hash1, p[0]);
+        hash1 = _mm_crc32_u32(hash1, p[1]);
+        break;
+    case 3:
+        hash1 = _mm_crc32_u32(hash1, p[0]);
+        hash1 = _mm_crc32_u32(hash1, p[1]);
+        hash2 = _mm_crc32_u32(hash2, p[2]);
+        break;
+    case 4:
+        hash1 = _mm_crc32_u32(hash1, p[0]);
+        hash1 = _mm_crc32_u32(hash1, p[1]);
+        hash2 = _mm_crc32_u32(hash2, p[2]);
+        hash2 = _mm_crc32_u32(hash2, p[3]);
+        break;
+    case 5:
+        hash1 = _mm_crc32_u32(hash1, p[0]);
+        hash1 = _mm_crc32_u32(hash1, p[1]);
+        hash2 = _mm_crc32_u32(hash2, p[2]);
+        hash2 = _mm_crc32_u32(hash2, p[3]);
+        hash3 = _mm_crc32_u32(hash3, p[4]);
+        break;
+    }
+    return hash_finish32(hash1, hash2, hash3);
+}
+
 /* A simpler version for 64-bit data.
  * 'n_words' is the count of 64-bit words, basis is 64 bits. */
 static inline uint32_t
@@ -293,10 +352,14 @@ uint32_t hash_words64__(const uint64_t *p, size_t 
n_words, uint32_t basis);
 static inline uint32_t
 hash_words(const uint32_t *p, size_t n_words, uint32_t basis)
 {
-    if (__builtin_constant_p(n_words)) {
-        return hash_words_inline(p, n_words, basis);
+    if (OVS_LIKELY(((intptr_t) p & ((sizeof(uint64_t)) - 1)) == 0)) {
+        if (__builtin_constant_p(n_words)) {
+            return hash_words_inline(p, n_words, basis);
+        } else {
+            return hash_words__(p, n_words, basis);
+        }
     } else {
-        return hash_words__(p, n_words, basis);
+        return hash_words_32aligned(p, n_words, basis);
     }
 }
 
-- 
2.31.1

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to