PR #2120: Fix hash_instantiated_test and hash_test on big-endian Imported from GitHub PR https://github.com/abseil/abseil-cpp/pull/2120 The two tests are failing on big-endian platforms after 63c77e406. The new bit-packing code stores packed bits in the LSB of a uint64_t, then feeds raw bytes via reinterpret_cast. On big-endian, the LSB is at the end of the memory layout, so the partial-word path reads leading zero bytes instead of the actual data, causing hash collisions between distinct inputs. Fix by byte-swapping the word to little-endian layout before feeding it to the combiner. Merge 955225b59105b384641beee9e00c25c07b80ce7e into 3d9e6767fb5483e70fb7262e4e5dd449fae59a66 Merging this change closes #2120 COPYBARA_INTEGRATE_REVIEW=https://github.com/abseil/abseil-cpp/pull/2120 from miladfarca:63c77e406-fix 955225b59105b384641beee9e00c25c07b80ce7e PiperOrigin-RevId: 951057598 Change-Id: I8f16de470641d2cb846806ff887cf955504735fd
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h index f68872f..fa4b53f 100644 --- a/absl/hash/internal/hash.h +++ b/absl/hash/internal/hash.h
@@ -809,6 +809,9 @@ for (size_t j = 0; j < 64; ++j) { word |= static_cast<uint64_t>(vector[i + j]) << j; } + if constexpr (absl::endian::native == absl::endian::big) { + word = absl::byteswap(word); + } hash_state = combiner.add_buffer( std::move(hash_state), reinterpret_cast<const unsigned char*>(&word), sizeof(word)); @@ -821,6 +824,9 @@ for (size_t j = 0; j < rem; ++j) { word |= static_cast<uint64_t>(vector[i + j]) << j; } + if constexpr (absl::endian::native == absl::endian::big) { + word = absl::byteswap(word); + } hash_state = combiner.add_buffer( std::move(hash_state), reinterpret_cast<const unsigned char*>(&word), (rem + 7) / 8); @@ -988,6 +994,9 @@ for (size_t j = 0; j < 64; ++j) { word |= static_cast<uint64_t>(set[i + j]) << j; } + if constexpr (absl::endian::native == absl::endian::big) { + word = absl::byteswap(word); + } hash_state = combiner.add_buffer( std::move(hash_state), reinterpret_cast<const unsigned char*>(&word), sizeof(word)); @@ -1000,6 +1009,9 @@ for (size_t j = 0; j < rem; ++j) { word |= static_cast<uint64_t>(set[i + j]) << j; } + if constexpr (absl::endian::native == absl::endian::big) { + word = absl::byteswap(word); + } hash_state = combiner.add_buffer( std::move(hash_state), reinterpret_cast<const unsigned char*>(&word), (rem + 7) / 8);