diff --git a/MODULE.bazel b/MODULE.bazel index 9d60905a302..86b62dc5a7a 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -16,7 +16,7 @@ module( name = "abseil-cpp", - version = "20240116.2", + version = "20240116.3", compatibility_level = 1, ) diff --git a/absl/base/config.h b/absl/base/config.h index 3933a3dbe29..0f4e855ce3c 100644 --- a/absl/base/config.h +++ b/absl/base/config.h @@ -118,7 +118,7 @@ // LTS releases can be obtained from // https://github.com/abseil/abseil-cpp/releases. #define ABSL_LTS_RELEASE_VERSION 20240116 -#define ABSL_LTS_RELEASE_PATCH_LEVEL 2 +#define ABSL_LTS_RELEASE_PATCH_LEVEL 3 // Helper macro to convert a CPP variable to a string literal. #define ABSL_INTERNAL_DO_TOKEN_STR(x) #x diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index 3518bc34040..5f7d0d7f0d8 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h @@ -1184,6 +1184,12 @@ inline size_t NormalizeCapacity(size_t n) { return n ? ~size_t{} >> countl_zero(n) : 1; } +template +size_t MaxValidCapacity() { + return NormalizeCapacity((std::numeric_limits::max)() / 4 / + kSlotSize); +} + // General notes on capacity/growth methods below: // - We use 7/8th as maximum load factor. For 16-wide groups, that gives an // average of two empty slots per group. @@ -2093,6 +2099,8 @@ class raw_hash_set { const allocator_type& alloc = allocator_type()) : settings_(CommonFields{}, hash, eq, alloc) { if (bucket_count) { + ABSL_RAW_CHECK(bucket_count <= MaxValidCapacity(), + "Hash table size overflow"); resize(NormalizeCapacity(bucket_count)); } } @@ -2286,7 +2294,9 @@ class raw_hash_set { bool empty() const { return !size(); } size_t size() const { return common().size(); } size_t capacity() const { return common().capacity(); } - size_t max_size() const { return (std::numeric_limits::max)(); } + size_t max_size() const { + return CapacityToGrowth(MaxValidCapacity()); + } ABSL_ATTRIBUTE_REINITIALIZES void clear() { // Iterating over this container is O(bucket_count()). When bucket_count() @@ -2624,6 +2634,8 @@ class raw_hash_set { auto m = NormalizeCapacity(n | GrowthToLowerboundCapacity(size())); // n == 0 unconditionally rehashes as per the standard. if (n == 0 || m > capacity()) { + ABSL_RAW_CHECK(m <= MaxValidCapacity(), + "Hash table size overflow"); resize(m); // This is after resize, to ensure that we have completed the allocation @@ -2634,6 +2646,7 @@ class raw_hash_set { void reserve(size_t n) { if (n > size() + growth_left()) { + ABSL_RAW_CHECK(n <= max_size(), "Hash table size overflow"); size_t m = GrowthToLowerboundCapacity(n); resize(NormalizeCapacity(m)); diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index f9797f565f4..1f579bf2f1e 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc @@ -2678,6 +2678,14 @@ TEST(Table, CountedHash) { } } +TEST(Table, MaxSizeOverflow) { + size_t overflow = (std::numeric_limits::max)(); + EXPECT_DEATH_IF_SUPPORTED(IntTable t(overflow), "Hash table size overflow"); + IntTable t; + EXPECT_DEATH_IF_SUPPORTED(t.reserve(overflow), "Hash table size overflow"); + EXPECT_DEATH_IF_SUPPORTED(t.rehash(overflow), "Hash table size overflow"); +} + } // namespace } // namespace container_internal ABSL_NAMESPACE_END