[libcxx] r294391 - Prevent UBSAN from generating unsigned overflow diagnostics in the hashing internals
Eric Fiselier via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 7 16:10:10 PST 2017
Author: ericwf
Date: Tue Feb 7 18:10:10 2017
New Revision: 294391
URL: http://llvm.org/viewvc/llvm-project?rev=294391&view=rev
Log:
Prevent UBSAN from generating unsigned overflow diagnostics in the hashing internals
Added:
libcxx/trunk/test/libcxx/utilities/function.objects/unord.hash/
libcxx/trunk/test/libcxx/utilities/function.objects/unord.hash/murmur2_or_cityhash_ubsan_unsigned_overflow_ignored.pass.cpp
Modified:
libcxx/trunk/include/utility
libcxx/trunk/test/support/test_macros.h
Modified: libcxx/trunk/include/utility
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?rev=294391&r1=294390&r2=294391&view=diff
==============================================================================
--- libcxx/trunk/include/utility (original)
+++ libcxx/trunk/include/utility Tue Feb 7 18:10:10 2017
@@ -959,13 +959,14 @@ struct __murmur2_or_cityhash;
template <class _Size>
struct __murmur2_or_cityhash<_Size, 32>
{
- _Size operator()(const void* __key, _Size __len);
+ inline _Size operator()(const void* __key, _Size __len)
+ _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK;
};
// murmur2
template <class _Size>
_Size
-__murmur2_or_cityhash<_Size, 32>::operator()(const void* __key, _Size __len) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
+__murmur2_or_cityhash<_Size, 32>::operator()(const void* __key, _Size __len)
{
const _Size __m = 0x5bd1e995;
const _Size __r = 24;
@@ -999,7 +1000,7 @@ __murmur2_or_cityhash<_Size, 32>::operat
template <class _Size>
struct __murmur2_or_cityhash<_Size, 64>
{
- _Size operator()(const void* __key, _Size __len);
+ inline _Size operator()(const void* __key, _Size __len) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK;
private:
// Some primes between 2^63 and 2^64.
@@ -1020,7 +1021,9 @@ struct __murmur2_or_cityhash<_Size, 64>
return __val ^ (__val >> 47);
}
- static _Size __hash_len_16(_Size __u, _Size __v) {
+ static _Size __hash_len_16(_Size __u, _Size __v)
+ _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
+ {
const _Size __mul = 0x9ddfea08eb382d69ULL;
_Size __a = (__u ^ __v) * __mul;
__a ^= (__a >> 47);
@@ -1030,7 +1033,9 @@ struct __murmur2_or_cityhash<_Size, 64>
return __b;
}
- static _Size __hash_len_0_to_16(const char* __s, _Size __len) {
+ static _Size __hash_len_0_to_16(const char* __s, _Size __len)
+ _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
+ {
if (__len > 8) {
const _Size __a = __loadword<_Size>(__s);
const _Size __b = __loadword<_Size>(__s + __len - 8);
@@ -1053,7 +1058,9 @@ struct __murmur2_or_cityhash<_Size, 64>
return __k2;
}
- static _Size __hash_len_17_to_32(const char *__s, _Size __len) {
+ static _Size __hash_len_17_to_32(const char *__s, _Size __len)
+ _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
+ {
const _Size __a = __loadword<_Size>(__s) * __k1;
const _Size __b = __loadword<_Size>(__s + 8);
const _Size __c = __loadword<_Size>(__s + __len - 8) * __k2;
@@ -1065,7 +1072,9 @@ struct __murmur2_or_cityhash<_Size, 64>
// Return a 16-byte hash for 48 bytes. Quick and dirty.
// Callers do best to use "random-looking" values for a and b.
static pair<_Size, _Size> __weak_hash_len_32_with_seeds(
- _Size __w, _Size __x, _Size __y, _Size __z, _Size __a, _Size __b) {
+ _Size __w, _Size __x, _Size __y, _Size __z, _Size __a, _Size __b)
+ _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
+ {
__a += __w;
__b = __rotate(__b + __a + __z, 21);
const _Size __c = __a;
@@ -1077,7 +1086,9 @@ struct __murmur2_or_cityhash<_Size, 64>
// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
static pair<_Size, _Size> __weak_hash_len_32_with_seeds(
- const char* __s, _Size __a, _Size __b) {
+ const char* __s, _Size __a, _Size __b)
+ _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
+ {
return __weak_hash_len_32_with_seeds(__loadword<_Size>(__s),
__loadword<_Size>(__s + 8),
__loadword<_Size>(__s + 16),
@@ -1087,7 +1098,9 @@ struct __murmur2_or_cityhash<_Size, 64>
}
// Return an 8-byte hash for 33 to 64 bytes.
- static _Size __hash_len_33_to_64(const char *__s, size_t __len) {
+ static _Size __hash_len_33_to_64(const char *__s, size_t __len)
+ _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
+ {
_Size __z = __loadword<_Size>(__s + 24);
_Size __a = __loadword<_Size>(__s) +
(__len + __loadword<_Size>(__s + __len - 16)) * __k0;
@@ -1115,7 +1128,7 @@ struct __murmur2_or_cityhash<_Size, 64>
// cityhash64
template <class _Size>
_Size
-__murmur2_or_cityhash<_Size, 64>::operator()(const void* __key, _Size __len) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
+__murmur2_or_cityhash<_Size, 64>::operator()(const void* __key, _Size __len)
{
const char* __s = static_cast<const char*>(__key);
if (__len <= 32) {
Added: libcxx/trunk/test/libcxx/utilities/function.objects/unord.hash/murmur2_or_cityhash_ubsan_unsigned_overflow_ignored.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/utilities/function.objects/unord.hash/murmur2_or_cityhash_ubsan_unsigned_overflow_ignored.pass.cpp?rev=294391&view=auto
==============================================================================
--- libcxx/trunk/test/libcxx/utilities/function.objects/unord.hash/murmur2_or_cityhash_ubsan_unsigned_overflow_ignored.pass.cpp (added)
+++ libcxx/trunk/test/libcxx/utilities/function.objects/unord.hash/murmur2_or_cityhash_ubsan_unsigned_overflow_ignored.pass.cpp Tue Feb 7 18:10:10 2017
@@ -0,0 +1,41 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Test that UBSAN doesn't generate unsigned integer overflow diagnostics
+// from within the hashing internals.
+
+#include <utility>
+#include <cstdint>
+#include <limits>
+#include <string>
+
+#include "test_macros.h"
+
+typedef std::__murmur2_or_cityhash<uint32_t> Hash32;
+typedef std::__murmur2_or_cityhash<uint64_t> Hash64;
+
+void test(const void* key, int len) {
+ for (int i=1; i <= len; ++i) {
+ Hash32 h1;
+ Hash64 h2;
+ DoNotOptimize(h1(key, i));
+ DoNotOptimize(h2(key, i));
+ }
+}
+
+int main() {
+ const std::string TestCases[] = {
+ "abcdaoeuaoeclaoeoaeuaoeuaousaotehu]+}sthoasuthaoesutahoesutaohesutaoeusaoetuhasoetuhaoseutaoseuthaoesutaohes"
+ "00000000000000000000000000000000000000000000000000000000000000000000000",
+ "1237546895+54+4554985416849484213464984765465464654564565645645646546456546546"
+ };
+ const size_t NumCases = sizeof(TestCases)/sizeof(TestCases[0]);
+ for (size_t i=0; i < NumCases; ++i)
+ test(TestCases[i].data(), TestCases[i].length());
+}
Modified: libcxx/trunk/test/support/test_macros.h
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/support/test_macros.h?rev=294391&r1=294390&r2=294391&view=diff
==============================================================================
--- libcxx/trunk/test/support/test_macros.h (original)
+++ libcxx/trunk/test/support/test_macros.h Tue Feb 7 18:10:10 2017
@@ -182,6 +182,18 @@ struct is_same<T, T> { enum {value = 1};
#endif
#endif
+#if defined(__GNUC__) || defined(__clang__)
+template <class Tp>
+inline void DoNotOptimize(Tp const& value) {
+ asm volatile("" : : "g"(value) : "memory");
+}
+#else
+template <class Tp>
+inline void DoNotOptimize(Tp const&) {
+ // FIXME: Do something here...
+}
+#endif
+
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
More information about the cfe-commits
mailing list