Skip to content

Commit

Permalink
Use builtin multiplication for intentional overflow
Browse files Browse the repository at this point in the history
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
  • Loading branch information
protobuf-github-bot authored and copybara-github committed Apr 13, 2023
1 parent 31f649f commit b9e056f
Showing 1 changed file with 13 additions and 1 deletion.
14 changes: 13 additions & 1 deletion src/google/protobuf/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,18 @@ struct KeyNode : NodeBase {
decltype(auto) key() const { return ReadKey<Key>(GetVoidKey()); }
};

// Multiply two numbers where overflow is expected.
template <typename N>
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
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit b9e056f

Please sign in to comment.