Commit 85dc8290 authored by Daniel Cheng's avatar Daniel Cheng Committed by Commit Bot

Make base::HashInts non-deterministic in DCHECK_IS_ON() builds.

Bug: 902789
Change-Id: I7de5133278e3c83517d93fadd9c00103553b7861
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1919809
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarLei Zhang <thestig@chromium.org>
Cr-Commit-Position: refs/heads/master@{#716001}
parent 8d65f296
......@@ -15,14 +15,22 @@ extern "C" uint32_t SuperFastHash(const char* data, int len);
namespace base {
size_t FastHash(base::span<const uint8_t> data) {
namespace {
template <typename T>
T Scramble(T input) {
#if DCHECK_IS_ON()
static const T seed = RandUint64();
return input ^ seed;
#else
return input;
#endif
}
size_t FastHashImpl(base::span<const uint8_t> data) {
// We use the updated CityHash within our namespace (not the deprecated
// version from third_party/smhasher).
#if DCHECK_IS_ON()
static const uint64_t seed = base::RandUint64();
return base::internal::cityhash_v111::CityHash64WithSeed(
reinterpret_cast<const char*>(data.data()), data.size(), seed);
#elif defined(ARCH_CPU_64_BITS)
#if defined(ARCH_CPU_64_BITS)
return base::internal::cityhash_v111::CityHash64(
reinterpret_cast<const char*>(data.data()), data.size());
#else
......@@ -31,36 +39,6 @@ size_t FastHash(base::span<const uint8_t> data) {
#endif
}
uint32_t Hash(const void* data, size_t length) {
// Currently our in-memory hash is the same as the persistent hash. The
// split between in-memory and persistent hash functions is maintained to
// allow the in-memory hash function to be updated in the future.
return PersistentHash(data, length);
}
uint32_t Hash(const std::string& str) {
return PersistentHash(str.data(), str.size());
}
uint32_t Hash(const string16& str) {
return PersistentHash(str.data(), str.size() * sizeof(char16));
}
uint32_t PersistentHash(const void* data, size_t length) {
// This hash function must not change, since it is designed to be persistable
// to disk.
if (length > static_cast<size_t>(std::numeric_limits<int>::max())) {
NOTREACHED();
return 0;
}
return ::SuperFastHash(reinterpret_cast<const char*>(data),
static_cast<int>(length));
}
uint32_t PersistentHash(const std::string& str) {
return PersistentHash(str.data(), str.size());
}
// Implement hashing for pairs of at-most 32 bit integer values.
// When size_t is 32 bits, we turn the 64-bit hash code into 32 bits by using
// multiply-add hashing. This algorithm, as described in
......@@ -70,7 +48,7 @@ uint32_t PersistentHash(const std::string& str) {
// h32(x32, y32) = (h64(x32, y32) * rand_odd64 + rand16 * 2^16) % 2^64 / 2^32
//
// Contact danakj@chromium.org for any questions.
size_t HashInts32(uint32_t value1, uint32_t value2) {
size_t HashInts32Impl(uint32_t value1, uint32_t value2) {
uint64_t value1_64 = value1;
uint64_t hash64 = (value1_64 << 32) | value2;
......@@ -91,7 +69,7 @@ size_t HashInts32(uint32_t value1, uint32_t value2) {
// breaking the two 64-bit inputs into 4 32-bit values:
// http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000
// Then we reduce our result to 32 bits if required, similar to above.
size_t HashInts64(uint64_t value1, uint64_t value2) {
size_t HashInts64Impl(uint64_t value1, uint64_t value2) {
uint32_t short_random1 = 842304669U;
uint32_t short_random2 = 619063811U;
uint32_t short_random3 = 937041849U;
......@@ -121,4 +99,53 @@ size_t HashInts64(uint64_t value1, uint64_t value2) {
return high_bits;
}
} // namespace
size_t FastHash(base::span<const uint8_t> data) {
return Scramble(FastHashImpl(data));
}
uint32_t Hash(const void* data, size_t length) {
// Currently our in-memory hash is the same as the persistent hash. The
// split between in-memory and persistent hash functions is maintained to
// allow the in-memory hash function to be updated in the future.
return PersistentHash(data, length);
}
uint32_t Hash(const std::string& str) {
return PersistentHash(str.data(), str.size());
}
uint32_t Hash(const string16& str) {
return PersistentHash(str.data(), str.size() * sizeof(char16));
}
uint32_t PersistentHash(const void* data, size_t length) {
// This hash function must not change, since it is designed to be persistable
// to disk.
if (length > static_cast<size_t>(std::numeric_limits<int>::max())) {
NOTREACHED();
return 0;
}
return ::SuperFastHash(reinterpret_cast<const char*>(data),
static_cast<int>(length));
}
uint32_t PersistentHash(const std::string& str) {
return PersistentHash(str.data(), str.size());
}
size_t HashInts32(uint32_t value1, uint32_t value2) {
return Scramble(HashInts32Impl(value1, value2));
}
// Implement hashing for pairs of up-to 64-bit integer values.
// We use the compound integer hash method to produce a 64-bit hash code, by
// breaking the two 64-bit inputs into 4 32-bit values:
// http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000
// Then we reduce our result to 32 bits if required, similar to above.
size_t HashInts64(uint64_t value1, uint64_t value2) {
return Scramble(HashInts64Impl(value1, value2));
}
} // namespace base
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment