From b9e056f779f1c6cbf07a7a11be6f5ee6a4d433b8 Mon Sep 17 00:00:00 2001 From: Protobuf Team Bot Date: Thu, 13 Apr 2023 09:11:55 -0700 Subject: [PATCH] Use builtin multiplication for intentional overflow Clang's unsigned integer overflow sanitizer is flagging BucketNumber as having an overflow. This is intentional behavior, so we should mark it as such. Rather than disabling the sanitizer, this uses __builtin_mul_overflow to indicate the overflow is intentional. PiperOrigin-RevId: 524018233 --- src/google/protobuf/map.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h index 99369d3b54..9a8f711f1f 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.h @@ -655,6 +655,18 @@ struct KeyNode : NodeBase { decltype(auto) key() const { return ReadKey(GetVoidKey()); } }; +// Multiply two numbers where overflow is expected. +template +N MultiplyWithOverflow(N a, N b) { +#if __has_builtin(__builtin_mul_overflow) + N res; + (void)__builtin_mul_overflow(a, b, &res); + return res; +#else + return a * b; +#endif +} + // KeyMapBase is a chaining hash map with the additional feature that some // buckets can be converted to use an ordered container. This ensures O(lg n) // bounds on find, insert, and erase, while avoiding the overheads of ordered @@ -1019,7 +1031,7 @@ class KeyMapBase : public UntypedMapBase { // the hash value. The constant kPhi (suggested by Knuth) is roughly // (sqrt(5) - 1) / 2 * 2^64. constexpr uint64_t kPhi = uint64_t{0x9e3779b97f4a7c15}; - return ((kPhi * h) >> 32) & (num_buckets_ - 1); + return (MultiplyWithOverflow(kPhi, h) >> 32) & (num_buckets_ - 1); } void DestroyTree(Tree* tree) {