Commit 17c1a5e8 by Evan Brown Committed by Copybara-Service

Add validation against use of destroyed hash tables.

PiperOrigin-RevId: 663373500
Change-Id: I6b2014f8cc4244e1599c907197cfaadb6739f72b
parent b2665cee
......@@ -540,8 +540,8 @@ ABSL_DLL extern const ctrl_t kEmptyGroup[32];
// classes of bugs.
enum InvalidCapacity : size_t {
kAboveMaxValidCapacity = ~size_t{} - 100,
// Used for reentrancy assertions.
kInvalidReentrance,
kReentrance,
kDestroyed,
};
// Returns a pointer to a control byte group that can be used by empty tables.
......@@ -1462,7 +1462,7 @@ class CommonFields : public CommonFieldsGenerationInfo {
return;
#endif
const size_t cap = capacity();
set_capacity(kInvalidReentrance);
set_capacity(InvalidCapacity::kReentrance);
f();
set_capacity(cap);
}
......@@ -2858,7 +2858,12 @@ class raw_hash_set {
typename AllocTraits::propagate_on_container_move_assignment());
}
~raw_hash_set() { destructor_impl(); }
~raw_hash_set() {
destructor_impl();
#ifndef NDEBUG
common().set_capacity(InvalidCapacity::kDestroyed);
#endif
}
iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (ABSL_PREDICT_FALSE(empty())) return end();
......@@ -3875,11 +3880,13 @@ class raw_hash_set {
}
// Asserts that the capacity is not a sentinel invalid value.
// TODO(b/296061262): also add asserts for moved-from and destroyed states.
// TODO(b/296061262): also add asserts for moved-from state.
void AssertNotDebugCapacity() const {
assert(capacity() != kInvalidReentrance &&
assert(capacity() != InvalidCapacity::kReentrance &&
"reentrant container access during element construction/destruction "
"is not allowed.");
assert(capacity() != InvalidCapacity::kDestroyed &&
"use of destroyed hash table.");
}
// Asserts that hash and equal functors provided by the user are consistent,
......
......@@ -3661,6 +3661,19 @@ TEST(Table, ReentrantCallsFail) {
#endif
}
TEST(Table, DestroyedCallsFail) {
#ifdef NDEBUG
GTEST_SKIP() << "Destroyed checks only enabled in debug mode.";
#else
absl::optional<IntTable> t;
t.emplace({1});
IntTable* t_ptr = &*t;
EXPECT_TRUE(t_ptr->contains(1));
t.reset();
EXPECT_DEATH_IF_SUPPORTED(t_ptr->contains(1), "");
#endif
}
} // namespace
} // namespace container_internal
ABSL_NAMESPACE_END
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment