From d6a595f070aeac84a34e383da4142dc81680057e Mon Sep 17 00:00:00 2001 From: Benjamin Barenblat Date: Mon, 8 Feb 2021 13:55:30 -0500 Subject: Fix endianness issues in absl/random --- debian/changelog | 2 +- debian/patches/endian-random.diff | 244 ++++++++++++++++++++++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 246 insertions(+), 1 deletion(-) create mode 100644 debian/patches/endian-random.diff diff --git a/debian/changelog b/debian/changelog index 664d5007..caa82188 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,7 @@ abseil (0~20200923.3-1) UNRELEASED; urgency=medium * New upstream release. - * Correct endianness issues in hash functions. + * Correct endianness issues in hash functions and RNG. -- Benjamin Barenblat Thu, 04 Feb 2021 12:08:46 -0500 diff --git a/debian/patches/endian-random.diff b/debian/patches/endian-random.diff new file mode 100644 index 00000000..244f36df --- /dev/null +++ b/debian/patches/endian-random.diff @@ -0,0 +1,244 @@ +From: Benjamin Barenblat +Subject: Remove endian-sensitivity from Abseil's RNG +Forwarded: yes + +Ensure that the Abseil random number generator produces identical output +on both big- and little-endian platforms by byte-swapping appropriately +on big-endian systems. + +--- a/absl/base/BUILD.bazel ++++ b/absl/base/BUILD.bazel +@@ -479,6 +479,7 @@ + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ ++ ":base", + ":config", + ":core_headers", + ], +--- a/absl/base/CMakeLists.txt ++++ b/absl/base/CMakeLists.txt +@@ -418,6 +418,7 @@ + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS ++ absl::base + absl::config + absl::core_headers + PUBLIC +--- a/absl/base/internal/endian.h ++++ b/absl/base/internal/endian.h +@@ -26,6 +26,7 @@ + #endif + + #include ++#include "absl/base/casts.h" + #include "absl/base/config.h" + #include "absl/base/internal/unaligned_access.h" + #include "absl/base/port.h" +@@ -173,6 +174,36 @@ + + #endif /* ENDIAN */ + ++inline uint8_t FromHost(uint8_t x) { return x; } ++inline uint16_t FromHost(uint16_t x) { return FromHost16(x); } ++inline uint32_t FromHost(uint32_t x) { return FromHost32(x); } ++inline uint64_t FromHost(uint64_t x) { return FromHost64(x); } ++inline uint8_t ToHost(uint8_t x) { return x; } ++inline uint16_t ToHost(uint16_t x) { return ToHost16(x); } ++inline uint32_t ToHost(uint32_t x) { return ToHost32(x); } ++inline uint64_t ToHost(uint64_t x) { return ToHost64(x); } ++ ++inline int8_t FromHost(int8_t x) { return x; } ++inline int16_t FromHost(int16_t x) { ++ return bit_cast(FromHost16(bit_cast(x))); ++} ++inline int32_t FromHost(int32_t x) { ++ return bit_cast(FromHost32(bit_cast(x))); ++} ++inline int64_t FromHost(int64_t x) { ++ return bit_cast(FromHost64(bit_cast(x))); ++} ++inline int8_t ToHost(int8_t x) { return x; } ++inline int16_t ToHost(int16_t x) { ++ return bit_cast(ToHost16(bit_cast(x))); ++} ++inline int32_t ToHost(int32_t x) { ++ return bit_cast(ToHost32(bit_cast(x))); ++} ++inline int64_t ToHost(int64_t x) { ++ return bit_cast(ToHost64(bit_cast(x))); ++} ++ + // Functions to do unaligned loads and stores in little-endian order. + inline uint16_t Load16(const void *p) { + return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p)); +@@ -233,6 +264,36 @@ + + #endif /* ENDIAN */ + ++inline uint8_t FromHost(uint8_t x) { return x; } ++inline uint16_t FromHost(uint16_t x) { return FromHost16(x); } ++inline uint32_t FromHost(uint32_t x) { return FromHost32(x); } ++inline uint64_t FromHost(uint64_t x) { return FromHost64(x); } ++inline uint8_t ToHost(uint8_t x) { return x; } ++inline uint16_t ToHost(uint16_t x) { return ToHost16(x); } ++inline uint32_t ToHost(uint32_t x) { return ToHost32(x); } ++inline uint64_t ToHost(uint64_t x) { return ToHost64(x); } ++ ++inline int8_t FromHost(int8_t x) { return x; } ++inline int16_t FromHost(int16_t x) { ++ return bit_cast(FromHost16(bit_cast(x))); ++} ++inline int32_t FromHost(int32_t x) { ++ return bit_cast(FromHost32(bit_cast(x))); ++} ++inline int64_t FromHost(int64_t x) { ++ return bit_cast(FromHost64(bit_cast(x))); ++} ++inline int8_t ToHost(int8_t x) { return x; } ++inline int16_t ToHost(int16_t x) { ++ return bit_cast(ToHost16(bit_cast(x))); ++} ++inline int32_t ToHost(int32_t x) { ++ return bit_cast(ToHost32(bit_cast(x))); ++} ++inline int64_t ToHost(int64_t x) { ++ return bit_cast(ToHost64(bit_cast(x))); ++} ++ + // Functions to do unaligned loads and stores in big-endian order. + inline uint16_t Load16(const void *p) { + return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p)); +--- a/absl/random/CMakeLists.txt ++++ b/absl/random/CMakeLists.txt +@@ -611,6 +611,7 @@ + ${ABSL_DEFAULT_LINKOPTS} + DEPS + absl::config ++ absl::endian + TESTONLY + ) + +@@ -758,6 +759,7 @@ + LINKOPTS + ${ABSL_DEFAULT_LINKOPTS} + DEPS ++ absl::endian + absl::random_internal_iostream_state_saver + absl::random_internal_randen + absl::raw_logging_internal +@@ -1119,6 +1121,7 @@ + LINKOPTS + ${ABSL_DEFAULT_LINKOPTS} + DEPS ++ absl::endian + absl::random_internal_randen_slow + gtest_main + ) +--- a/absl/random/internal/BUILD.bazel ++++ b/absl/random/internal/BUILD.bazel +@@ -124,7 +124,10 @@ + ], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, +- deps = ["//absl/base:config"], ++ deps = [ ++ "//absl/base:config", ++ "//absl/base:endian", ++ ], + ) + + cc_library( +@@ -241,6 +244,7 @@ + deps = [ + ":iostream_state_saver", + ":randen", ++ "//absl/base:endian", + "//absl/meta:type_traits", + ], + ) +@@ -606,6 +610,7 @@ + ":platform", + ":randen_slow", + "@com_google_googletest//:gtest_main", ++ "//absl/base:endian", + ], + ) + +--- a/absl/random/internal/explicit_seed_seq.h ++++ b/absl/random/internal/explicit_seed_seq.h +@@ -23,6 +23,7 @@ + #include + + #include "absl/base/config.h" ++#include "absl/base/internal/endian.h" + + namespace absl { + ABSL_NAMESPACE_BEGIN +@@ -73,7 +74,7 @@ + template + void generate(OutIterator begin, OutIterator end) { + for (size_t index = 0; begin != end; begin++) { +- *begin = state_.empty() ? 0 : state_[index++]; ++ *begin = state_.empty() ? 0 : little_endian::FromHost32(state_[index++]); + if (index >= state_.size()) { + index = 0; + } +--- a/absl/random/internal/randen_engine.h ++++ b/absl/random/internal/randen_engine.h +@@ -23,6 +23,7 @@ + #include + #include + ++#include "absl/base/internal/endian.h" + #include "absl/meta/type_traits.h" + #include "absl/random/internal/iostream_state_saver.h" + #include "absl/random/internal/randen.h" +@@ -76,7 +77,7 @@ + impl_.Generate(state_); + } + +- return state_[next_++]; ++ return little_endian::ToHost(state_[next_++]); + } + + template +@@ -181,7 +182,8 @@ + // In the case that `elem` is `uint8_t`, it must be cast to something + // larger so that it prints as an integer rather than a character. For + // simplicity, apply the cast all circumstances. +- os << static_cast(elem) << os.fill(); ++ os << static_cast(little_endian::FromHost(elem)) ++ << os.fill(); + } + os << engine.next_; + return os; +@@ -200,7 +202,7 @@ + // necessary to read a wider type and then cast it to uint8_t. + numeric_type value; + is >> value; +- elem = static_cast(value); ++ elem = little_endian::ToHost(static_cast(value)); + } + is >> next; + if (is.fail()) { +--- a/absl/random/internal/randen_slow_test.cc ++++ b/absl/random/internal/randen_slow_test.cc +@@ -17,6 +17,7 @@ + #include + + #include "gtest/gtest.h" ++#include "absl/base/internal/endian.h" + #include "absl/random/internal/randen_traits.h" + + namespace { +@@ -56,7 +57,7 @@ + + uint64_t* id = d.state; + for (const auto& elem : kGolden) { +- EXPECT_EQ(elem, *id++); ++ EXPECT_EQ(absl::little_endian::FromHost64(elem), *id++); + } + } + diff --git a/debian/patches/series b/debian/patches/series index 33ae234a..6330dc6c 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -5,3 +5,4 @@ latomic.diff cpu-frequency.diff nan-narrowing.diff endian-hash.diff +endian-random.diff -- cgit v1.2.3