From f2b86aaffbaef0563a89e1f187e3e5bbef4c2d25 Mon Sep 17 00:00:00 2001 From: Ben Clayton Date: Tue, 13 Dec 2022 14:46:02 +0000 Subject: [PATCH] tint: Add hash randomization Enable this in Kororo builds to ensure that output isn't dependent on hash values. Change-Id: Ib538385b53bebf5260186b14cea396dac15caf6c Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/113980 Kokoro: Kokoro Reviewed-by: Antonio Maiorano Commit-Queue: Ben Clayton --- CMakeLists.txt | 10 ++++++++++ infra/kokoro/linux/docker.sh | 1 + infra/kokoro/windows/build.bat | 15 ++++++++++++++- src/tint/sem/struct_test.cc | 11 ----------- src/tint/type/array_test.cc | 10 ---------- src/tint/type/atomic_test.cc | 2 -- src/tint/type/depth_texture_test.cc | 2 -- src/tint/type/matrix_test.cc | 6 ------ src/tint/type/multisampled_texture_test.cc | 4 ---- src/tint/type/pointer_test.cc | 6 ------ src/tint/type/reference_test.cc | 8 -------- src/tint/type/sampled_texture_test.cc | 4 ---- src/tint/type/sampler_test.cc | 2 -- src/tint/type/storage_texture_test.cc | 9 --------- src/tint/type/struct_test.cc | 9 --------- src/tint/type/vector_test.cc | 4 ---- src/tint/utils/enum_set_test.cc | 1 - src/tint/utils/hash.h | 20 ++++++++++++++++++-- src/tint/utils/hash_test.cc | 11 ----------- src/tint/utils/hashmap_test.cc | 6 ------ 20 files changed, 43 insertions(+), 98 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 27d70f2457..1f27535d47 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -171,6 +171,7 @@ option_if_not_defined(TINT_BUILD_REMOTE_COMPILE "Build the remote-compile tool f option_if_not_defined(TINT_ENABLE_BREAK_IN_DEBUGGER "Enable tint::debugger::Break()" OFF) option_if_not_defined(TINT_CHECK_CHROMIUM_STYLE "Check for [chromium-style] issues during build" OFF) option_if_not_defined(TINT_SYMBOL_STORE_DEBUG_NAME "Enable storing of name in tint::ast::Symbol to help debugging the AST" OFF) +option_if_not_defined(TINT_RANDOMIZE_HASHES "Randomize the hash seed value to detect non-deterministic output" OFF) # Recommended setting for compability with future abseil releases. set(ABSL_PROPAGATE_CXX_STD ON) @@ -598,6 +599,15 @@ function(tint_default_compile_options TARGET) ) endif() endif() + + if (TINT_RANDOMIZE_HASHES) + if(NOT DEFINED TINT_HASH_SEED) + string(RANDOM LENGTH 16 ALPHABET "0123456789abcdef" seed) + set(TINT_HASH_SEED "0x${seed}" CACHE STRING "Tint hash seed value") + message("Using TINT_HASH_SEED: ${TINT_HASH_SEED}") + endif() + target_compile_definitions(${TARGET} PUBLIC "-DTINT_HASH_SEED=${TINT_HASH_SEED}") + endif() endfunction() ################################################################################ diff --git a/infra/kokoro/linux/docker.sh b/infra/kokoro/linux/docker.sh index f1145e3e37..3f92aac2bf 100755 --- a/infra/kokoro/linux/docker.sh +++ b/infra/kokoro/linux/docker.sh @@ -129,6 +129,7 @@ if [ "$BUILD_SYSTEM" == "cmake" ]; then COMMON_CMAKE_FLAGS+=" -DTINT_BUILD_MSL_WRITER=1" COMMON_CMAKE_FLAGS+=" -DTINT_BUILD_SPV_WRITER=1" COMMON_CMAKE_FLAGS+=" -DTINT_BUILD_WGSL_WRITER=1" + COMMON_CMAKE_FLAGS+=" -DTINT_RANDOMIZE_HASHES=1" if [ "$BUILD_TOOLCHAIN" == "clang" ]; then using clang-10.0.0 diff --git a/infra/kokoro/windows/build.bat b/infra/kokoro/windows/build.bat index 9a355c9716..eac0a71776 100644 --- a/infra/kokoro/windows/build.bat +++ b/infra/kokoro/windows/build.bat @@ -109,7 +109,20 @@ call :status "Configuring build system" @echo on mkdir %BUILD_DIR% cd /d %BUILD_DIR% -set COMMON_CMAKE_FLAGS=-DTINT_BUILD_DOCS=O -DTINT_BUILD_BENCHMARKS=1 -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DTINT_BUILD_BENCHMARKS=1 -DTINT_BUILD_SPV_READER=1 -DTINT_BUILD_WGSL_READER=1 -DTINT_BUILD_GLSL_WRITER=1 -DTINT_BUILD_HLSL_WRITER=1 -DTINT_BUILD_MSL_WRITER=1 -DTINT_BUILD_SPV_WRITER=1 -DTINT_BUILD_WGSL_WRITER=1 +set COMMON_CMAKE_FLAGS= ^ + -DTINT_BUILD_DOCS=O ^ + -DTINT_BUILD_BENCHMARKS=1 ^ + -DCMAKE_BUILD_TYPE=%BUILD_TYPE% ^ + -DTINT_BUILD_BENCHMARKS=1 ^ + -DTINT_BUILD_SPV_READER=1 ^ + -DTINT_BUILD_WGSL_READER=1 ^ + -DTINT_BUILD_GLSL_WRITER=1 ^ + -DTINT_BUILD_HLSL_WRITER=1 ^ + -DTINT_BUILD_MSL_WRITER=1 ^ + -DTINT_BUILD_SPV_WRITER=1 ^ + -DTINT_BUILD_WGSL_WRITER=1 ^ + -DTINT_RANDOMIZE_HASHES=1 + @echo off call :status "Building dawn" diff --git a/src/tint/sem/struct_test.cc b/src/tint/sem/struct_test.cc index 8d16c2daa7..b009d55f43 100644 --- a/src/tint/sem/struct_test.cc +++ b/src/tint/sem/struct_test.cc @@ -34,17 +34,6 @@ TEST_F(SemStructTest, Creation) { EXPECT_EQ(s->SizeNoPadding(), 16u); } -TEST_F(SemStructTest, Hash) { - auto* a_impl = create(Sym("a"), utils::Empty, utils::Empty); - auto* a = create(a_impl, a_impl->source, a_impl->name, utils::Empty, - 4u /* align */, 4u /* size */, 4u /* size_no_padding */); - auto* b_impl = create(Sym("b"), utils::Empty, utils::Empty); - auto* b = create(b_impl, b_impl->source, b_impl->name, utils::Empty, - 4u /* align */, 4u /* size */, 4u /* size_no_padding */); - - EXPECT_NE(a->Hash(), b->Hash()); -} - TEST_F(SemStructTest, Equals) { auto* a_impl = create(Sym("a"), utils::Empty, utils::Empty); auto* a = create(a_impl, a_impl->source, a_impl->name, utils::Empty, diff --git a/src/tint/type/array_test.cc b/src/tint/type/array_test.cc index 367aa4ba7a..cd4d5f137a 100644 --- a/src/tint/type/array_test.cc +++ b/src/tint/type/array_test.cc @@ -74,18 +74,8 @@ TEST_F(ArrayTest, CreateRuntimeArray) { TEST_F(ArrayTest, Hash) { auto* a = create(create(), create(2u), 4u, 8u, 32u, 16u); auto* b = create(create(), create(2u), 4u, 8u, 32u, 16u); - auto* c = create(create(), create(3u), 4u, 8u, 32u, 16u); - auto* d = create(create(), create(2u), 5u, 8u, 32u, 16u); - auto* e = create(create(), create(2u), 4u, 9u, 32u, 16u); - auto* f = create(create(), create(2u), 4u, 8u, 33u, 16u); - auto* g = create(create(), create(2u), 4u, 8u, 33u, 17u); EXPECT_EQ(a->Hash(), b->Hash()); - EXPECT_NE(a->Hash(), c->Hash()); - EXPECT_NE(a->Hash(), d->Hash()); - EXPECT_NE(a->Hash(), e->Hash()); - EXPECT_NE(a->Hash(), f->Hash()); - EXPECT_NE(a->Hash(), g->Hash()); } TEST_F(ArrayTest, Equals) { diff --git a/src/tint/type/atomic_test.cc b/src/tint/type/atomic_test.cc index b67e118e6d..740ce791b0 100644 --- a/src/tint/type/atomic_test.cc +++ b/src/tint/type/atomic_test.cc @@ -33,9 +33,7 @@ TEST_F(AtomicTest, Creation) { TEST_F(AtomicTest, Hash) { auto* a = create(create()); auto* b = create(create()); - auto* c = create(create()); EXPECT_EQ(a->Hash(), b->Hash()); - EXPECT_NE(a->Hash(), c->Hash()); } TEST_F(AtomicTest, Equals) { diff --git a/src/tint/type/depth_texture_test.cc b/src/tint/type/depth_texture_test.cc index b729dc8a4b..3b73af46c6 100644 --- a/src/tint/type/depth_texture_test.cc +++ b/src/tint/type/depth_texture_test.cc @@ -36,10 +36,8 @@ TEST_F(DepthTextureTest, Creation) { TEST_F(DepthTextureTest, Hash) { auto* a = create(ast::TextureDimension::k2d); auto* b = create(ast::TextureDimension::k2d); - auto* c = create(ast::TextureDimension::k2dArray); EXPECT_EQ(a->Hash(), b->Hash()); - EXPECT_NE(a->Hash(), c->Hash()); } TEST_F(DepthTextureTest, Equals) { diff --git a/src/tint/type/matrix_test.cc b/src/tint/type/matrix_test.cc index aff69249a6..7d88c6a1f2 100644 --- a/src/tint/type/matrix_test.cc +++ b/src/tint/type/matrix_test.cc @@ -40,14 +40,8 @@ TEST_F(MatrixTest, Creation) { TEST_F(MatrixTest, Hash) { auto* a = create(create(create(), 3u), 4u); auto* b = create(create(create(), 3u), 4u); - auto* c = create(create(create(), 3u), 4u); - auto* d = create(create(create(), 2u), 4u); - auto* e = create(create(create(), 3u), 2u); EXPECT_EQ(a->Hash(), b->Hash()); - EXPECT_NE(a->Hash(), c->Hash()); - EXPECT_NE(a->Hash(), d->Hash()); - EXPECT_NE(a->Hash(), e->Hash()); } TEST_F(MatrixTest, Equals) { diff --git a/src/tint/type/multisampled_texture_test.cc b/src/tint/type/multisampled_texture_test.cc index cf3d28afe2..8eac7c636a 100644 --- a/src/tint/type/multisampled_texture_test.cc +++ b/src/tint/type/multisampled_texture_test.cc @@ -38,11 +38,7 @@ TEST_F(MultisampledTextureTest, Creation) { TEST_F(MultisampledTextureTest, Hash) { auto* a = create(ast::TextureDimension::k2d, create()); auto* b = create(ast::TextureDimension::k2d, create()); - auto* c = create(ast::TextureDimension::k3d, create()); - auto* d = create(ast::TextureDimension::k2d, create()); EXPECT_EQ(a->Hash(), b->Hash()); - EXPECT_NE(a->Hash(), c->Hash()); - EXPECT_NE(a->Hash(), d->Hash()); } TEST_F(MultisampledTextureTest, Equals) { diff --git a/src/tint/type/pointer_test.cc b/src/tint/type/pointer_test.cc index 4f8033f046..ab51f7c02d 100644 --- a/src/tint/type/pointer_test.cc +++ b/src/tint/type/pointer_test.cc @@ -40,14 +40,8 @@ TEST_F(PointerTest, Creation) { TEST_F(PointerTest, Hash) { auto* a = create(create(), ast::AddressSpace::kStorage, ast::Access::kReadWrite); auto* b = create(create(), ast::AddressSpace::kStorage, ast::Access::kReadWrite); - auto* c = create(create(), ast::AddressSpace::kStorage, ast::Access::kReadWrite); - auto* d = create(create(), ast::AddressSpace::kPrivate, ast::Access::kReadWrite); - auto* e = create(create(), ast::AddressSpace::kStorage, ast::Access::kRead); EXPECT_EQ(a->Hash(), b->Hash()); - EXPECT_NE(a->Hash(), c->Hash()); - EXPECT_NE(a->Hash(), d->Hash()); - EXPECT_NE(a->Hash(), e->Hash()); } TEST_F(PointerTest, Equals) { diff --git a/src/tint/type/reference_test.cc b/src/tint/type/reference_test.cc index 3d50997bbb..094770e37b 100644 --- a/src/tint/type/reference_test.cc +++ b/src/tint/type/reference_test.cc @@ -46,16 +46,8 @@ TEST_F(ReferenceTest, Hash) { create(create(), ast::AddressSpace::kStorage, ast::Access::kReadWrite); auto* b = create(create(), ast::AddressSpace::kStorage, ast::Access::kReadWrite); - auto* c = - create(create(), ast::AddressSpace::kStorage, ast::Access::kReadWrite); - auto* d = - create(create(), ast::AddressSpace::kPrivate, ast::Access::kReadWrite); - auto* e = create(create(), ast::AddressSpace::kStorage, ast::Access::kRead); EXPECT_EQ(a->Hash(), b->Hash()); - EXPECT_NE(a->Hash(), c->Hash()); - EXPECT_NE(a->Hash(), d->Hash()); - EXPECT_NE(a->Hash(), e->Hash()); } TEST_F(ReferenceTest, Equals) { diff --git a/src/tint/type/sampled_texture_test.cc b/src/tint/type/sampled_texture_test.cc index ab0c74d421..f9cb5be900 100644 --- a/src/tint/type/sampled_texture_test.cc +++ b/src/tint/type/sampled_texture_test.cc @@ -41,12 +41,8 @@ TEST_F(SampledTextureTest, Creation) { TEST_F(SampledTextureTest, Hash) { auto* a = create(ast::TextureDimension::kCube, create()); auto* b = create(ast::TextureDimension::kCube, create()); - auto* c = create(ast::TextureDimension::k2d, create()); - auto* d = create(ast::TextureDimension::kCube, create()); EXPECT_EQ(a->Hash(), b->Hash()); - EXPECT_NE(a->Hash(), c->Hash()); - EXPECT_NE(a->Hash(), d->Hash()); } TEST_F(SampledTextureTest, Equals) { diff --git a/src/tint/type/sampler_test.cc b/src/tint/type/sampler_test.cc index 65a23707f5..ba30541b12 100644 --- a/src/tint/type/sampler_test.cc +++ b/src/tint/type/sampler_test.cc @@ -39,10 +39,8 @@ TEST_F(SamplerTest, Creation) { TEST_F(SamplerTest, Hash) { auto* a = create(ast::SamplerKind::kSampler); auto* b = create(ast::SamplerKind::kSampler); - auto* c = create(ast::SamplerKind::kComparisonSampler); EXPECT_EQ(a->Hash(), b->Hash()); - EXPECT_NE(a->Hash(), c->Hash()); } TEST_F(SamplerTest, Equals) { diff --git a/src/tint/type/storage_texture_test.cc b/src/tint/type/storage_texture_test.cc index b375207799..0c86d890d6 100644 --- a/src/tint/type/storage_texture_test.cc +++ b/src/tint/type/storage_texture_test.cc @@ -55,17 +55,8 @@ TEST_F(StorageTextureTest, Hash) { ast::Access::kReadWrite); auto* b = Create(ast::TextureDimension::kCube, ast::TexelFormat::kRgba32Float, ast::Access::kReadWrite); - auto* c = - Create(ast::TextureDimension::k2d, ast::TexelFormat::kRgba32Float, ast::Access::kReadWrite); - auto* d = - Create(ast::TextureDimension::kCube, ast::TexelFormat::kR32Float, ast::Access::kReadWrite); - auto* e = - Create(ast::TextureDimension::kCube, ast::TexelFormat::kRgba32Float, ast::Access::kRead); EXPECT_EQ(a->Hash(), b->Hash()); - EXPECT_NE(a->Hash(), c->Hash()); - EXPECT_NE(a->Hash(), d->Hash()); - EXPECT_NE(a->Hash(), e->Hash()); } TEST_F(StorageTextureTest, Equals) { diff --git a/src/tint/type/struct_test.cc b/src/tint/type/struct_test.cc index ae9a249594..8bacfca9f2 100644 --- a/src/tint/type/struct_test.cc +++ b/src/tint/type/struct_test.cc @@ -31,15 +31,6 @@ TEST_F(TypeStructTest, Creation) { EXPECT_EQ(s->SizeNoPadding(), 16u); } -TEST_F(TypeStructTest, Hash) { - auto* a = create(Source{}, Sym("a"), utils::Empty, 4u /* align */, 4u /* size */, - 4u /* size_no_padding */); - auto* b = create(Source{}, Sym("b"), utils::Empty, 4u /* align */, 4u /* size */, - 4u /* size_no_padding */); - - EXPECT_NE(a->Hash(), b->Hash()); -} - TEST_F(TypeStructTest, Equals) { auto* a = create(Source{}, Sym("a"), utils::Empty, 4u /* align */, 4u /* size */, 4u /* size_no_padding */); diff --git a/src/tint/type/vector_test.cc b/src/tint/type/vector_test.cc index aed294ab3d..65d7b1b420 100644 --- a/src/tint/type/vector_test.cc +++ b/src/tint/type/vector_test.cc @@ -37,12 +37,8 @@ TEST_F(VectorTest, Creation) { TEST_F(VectorTest, Hash) { auto* a = create(create(), 2u); auto* b = create(create(), 2u); - auto* c = create(create(), 2u); - auto* d = create(create(), 3u); EXPECT_EQ(a->Hash(), b->Hash()); - EXPECT_NE(a->Hash(), c->Hash()); - EXPECT_NE(a->Hash(), d->Hash()); } TEST_F(VectorTest, Equals) { diff --git a/src/tint/utils/enum_set_test.cc b/src/tint/utils/enum_set_test.cc index e4696500dc..4cdeb63440 100644 --- a/src/tint/utils/enum_set_test.cc +++ b/src/tint/utils/enum_set_test.cc @@ -192,7 +192,6 @@ TEST(EnumSetTest, InequalityEnum) { TEST(EnumSetTest, Hash) { auto hash = [&](EnumSet s) { return std::hash>()(s); }; EXPECT_EQ(hash(EnumSet(E::A, E::B)), hash(EnumSet(E::A, E::B))); - EXPECT_NE(hash(EnumSet(E::A, E::B)), hash(EnumSet(E::A, E::C))); } TEST(EnumSetTest, Value) { diff --git a/src/tint/utils/hash.h b/src/tint/utils/hash.h index 89cf0f052d..196861b5e4 100644 --- a/src/tint/utils/hash.h +++ b/src/tint/utils/hash.h @@ -23,6 +23,7 @@ #include #include +#include "src/tint/utils/crc32.h" #include "src/tint/utils/vector.h" namespace tint::utils { @@ -37,14 +38,26 @@ struct HashCombineOffset {}; template <> struct HashCombineOffset<4> { /// @returns the seed bias value for HashCombine() - static constexpr inline uint32_t value() { return 0x7f4a7c16; } + static constexpr inline uint32_t value() { + constexpr uint32_t base = 0x7f4a7c16; +#ifdef TINT_HASH_SEED + return base ^ static_cast(TINT_HASH_SEED); +#endif + return base; + } }; /// Specialization of HashCombineOffset for size_t == 8. template <> struct HashCombineOffset<8> { /// @returns the seed bias value for HashCombine() - static constexpr inline uint64_t value() { return 0x9e3779b97f4a7c16; } + static constexpr inline uint64_t value() { + constexpr uint64_t base = 0x9e3779b97f4a7c16; +#ifdef TINT_HASH_SEED + return base ^ static_cast(TINT_HASH_SEED); +#endif + return base; + } }; } // namespace detail @@ -76,6 +89,9 @@ struct Hasher { /// @returns a hash of the pointer size_t operator()(T* ptr) const { auto hash = std::hash()(ptr); +#ifdef TINT_HASH_SEED + hash ^= static_cast(TINT_HASH_SEED); +#endif return hash ^ (hash >> 4); } }; diff --git a/src/tint/utils/hash_test.cc b/src/tint/utils/hash_test.cc index 6ce6820630..cdceab445e 100644 --- a/src/tint/utils/hash_test.cc +++ b/src/tint/utils/hash_test.cc @@ -26,28 +26,19 @@ namespace { TEST(HashTests, Basic) { EXPECT_EQ(Hash(123), Hash(123)); - EXPECT_NE(Hash(123), Hash(321)); EXPECT_EQ(Hash(123, 456), Hash(123, 456)); - EXPECT_NE(Hash(123, 456), Hash(456, 123)); - EXPECT_NE(Hash(123, 456), Hash(123)); EXPECT_EQ(Hash(123, 456, false), Hash(123, 456, false)); - EXPECT_NE(Hash(123, 456, false), Hash(123, 456)); EXPECT_EQ(Hash(std::string("hello")), Hash(std::string("hello"))); - EXPECT_NE(Hash(std::string("hello")), Hash(std::string("world"))); } TEST(HashTests, StdVector) { EXPECT_EQ(Hash(std::vector({})), Hash(std::vector({}))); EXPECT_EQ(Hash(std::vector({1, 2, 3})), Hash(std::vector({1, 2, 3}))); - EXPECT_NE(Hash(std::vector({1, 2, 3})), Hash(std::vector({1, 2, 4}))); - EXPECT_NE(Hash(std::vector({1, 2, 3})), Hash(std::vector({1, 2, 3, 4}))); } TEST(HashTests, TintVector) { EXPECT_EQ(Hash(Vector({})), Hash(Vector({}))); EXPECT_EQ(Hash(Vector({1, 2, 3})), Hash(Vector({1, 2, 3}))); - EXPECT_NE(Hash(Vector({1, 2, 3})), Hash(Vector({1, 2, 4}))); - EXPECT_NE(Hash(Vector({1, 2, 3})), Hash(Vector({1, 2, 3, 4}))); EXPECT_EQ(Hash(Vector({1, 2, 3})), Hash(Vector({1, 2, 3}))); EXPECT_EQ(Hash(Vector({1, 2, 3})), Hash(Vector({1, 2, 3}))); } @@ -55,8 +46,6 @@ TEST(HashTests, TintVector) { TEST(HashTests, Tuple) { EXPECT_EQ(Hash(std::make_tuple(1)), Hash(std::make_tuple(1))); EXPECT_EQ(Hash(std::make_tuple(1, 2, 3)), Hash(std::make_tuple(1, 2, 3))); - EXPECT_NE(Hash(std::make_tuple(1, 2, 3)), Hash(std::make_tuple(1, 2, 4))); - EXPECT_NE(Hash(std::make_tuple(1, 2, 3)), Hash(std::make_tuple(1, 2, 3, 4))); } TEST(HashTests, UnorderedKeyWrapper) { diff --git a/src/tint/utils/hashmap_test.cc b/src/tint/utils/hashmap_test.cc index 5e97aef0f1..6d993e2fa5 100644 --- a/src/tint/utils/hashmap_test.cc +++ b/src/tint/utils/hashmap_test.cc @@ -388,11 +388,8 @@ TEST(Hashmap, HashSameSize) { Hashmap b; EXPECT_EQ(Hash(a), Hash(b)); a.Add(1, "one"); - EXPECT_NE(Hash(a), Hash(b)); b.Add(2, "two"); - EXPECT_NE(Hash(a), Hash(b)); a.Add(2, "two"); - EXPECT_NE(Hash(a), Hash(b)); b.Add(1, "one"); EXPECT_EQ(Hash(a), Hash(b)); } @@ -402,11 +399,8 @@ TEST(Hashmap, HashDifferentSize) { Hashmap b; EXPECT_EQ(Hash(a), Hash(b)); a.Add(1, "one"); - EXPECT_NE(Hash(a), Hash(b)); b.Add(2, "two"); - EXPECT_NE(Hash(a), Hash(b)); a.Add(2, "two"); - EXPECT_NE(Hash(a), Hash(b)); b.Add(1, "one"); EXPECT_EQ(Hash(a), Hash(b)); }