diff --git a/MODULE.bazel b/MODULE.bazel index 75285b6191b..59ae492d8f7 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -16,7 +16,7 @@ module( name = "abseil-cpp", - version = "20240722.0", + version = "20240722.1", compatibility_level = 1, ) diff --git a/absl/base/config.h b/absl/base/config.h index 0b22167ef5f..46e6fbcb9b2 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 20240722 -#define ABSL_LTS_RELEASE_PATCH_LEVEL 0 +#define ABSL_LTS_RELEASE_PATCH_LEVEL 1 // 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 d4fe8f5c21b..7934b88c3eb 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h @@ -1208,6 +1208,9 @@ class RawHashSetLayout { // Given the capacity of a table, computes the total size of the backing // array. size_t alloc_size(size_t slot_size) const { + ABSL_HARDENING_ASSERT( + slot_size <= + ((std::numeric_limits::max)() - slot_offset_) / capacity_); return slot_offset_ + capacity_ * slot_size; } @@ -1500,6 +1503,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. @@ -2614,6 +2623,8 @@ class raw_hash_set { : settings_(CommonFields::CreateDefault(), hash, eq, alloc) { if (bucket_count > (SooEnabled() ? SooCapacity() : 0)) { + ABSL_RAW_CHECK(bucket_count <= MaxValidCapacity(), + "Hash table size overflow"); resize(NormalizeCapacity(bucket_count)); } } @@ -2871,7 +2882,9 @@ class raw_hash_set { ABSL_ASSUME(!kEnabled || cap >= kCapacity); return cap; } - 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() @@ -3260,6 +3273,8 @@ class raw_hash_set { auto m = NormalizeCapacity(n | GrowthToLowerboundCapacity(size())); // n == 0 unconditionally rehashes as per the standard. if (n == 0 || m > cap) { + ABSL_RAW_CHECK(m <= MaxValidCapacity(), + "Hash table size overflow"); resize(m); // This is after resize, to ensure that we have completed the allocation @@ -3272,6 +3287,7 @@ class raw_hash_set { const size_t max_size_before_growth = is_soo() ? SooCapacity() : size() + growth_left(); if (n > max_size_before_growth) { + 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 f1257d4b850..1604afef01c 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc @@ -3594,6 +3594,14 @@ TEST(Iterator, InconsistentHashEqFunctorsValidation) { "hash/eq functors are inconsistent."); } +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