aboutsummaryrefslogtreecommitdiff
path: root/absl/container/internal/raw_hash_set.h
diff options
context:
space:
mode:
authorEvan Brown <ezb@google.com>2023-10-30 09:58:13 -0700
committerCopybara-Service <copybara-worker@google.com>2023-10-30 09:59:17 -0700
commitdc3ef2950e7ce08b53ead824cc81b3287e2b74ac (patch)
treef19cce04f786a98d91cbc43306c3ba9042c4c6f3 /absl/container/internal/raw_hash_set.h
parente7d9317bf5d65d98d9fa4bbbc9750613fc4cdf8a (diff)
downloadabseil-dc3ef2950e7ce08b53ead824cc81b3287e2b74ac.tar.gz
abseil-dc3ef2950e7ce08b53ead824cc81b3287e2b74ac.tar.bz2
abseil-dc3ef2950e7ce08b53ead824cc81b3287e2b74ac.zip
Roll forward: Add sanitizer mode checks that element constructors/destructors don't make reentrant calls to raw_hash_set member functions.
PiperOrigin-RevId: 577877803 Change-Id: I254c589b00cadec6ff95dfd60a8a38ab303c1af5
Diffstat (limited to 'absl/container/internal/raw_hash_set.h')
-rw-r--r--absl/container/internal/raw_hash_set.h39
1 files changed, 27 insertions, 12 deletions
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index a8fd80ca..67964f54 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -2143,7 +2143,7 @@ class raw_hash_set {
alignas(slot_type) unsigned char raw[sizeof(slot_type)];
slot_type* slot = reinterpret_cast<slot_type*>(&raw);
- PolicyTraits::construct(&alloc_ref(), slot, std::forward<Args>(args)...);
+ construct(slot, std::forward<Args>(args)...);
const auto& elem = PolicyTraits::element(slot);
return PolicyTraits::apply(InsertSlot<true>{*this, std::move(*slot)}, elem);
}
@@ -2248,7 +2248,7 @@ class raw_hash_set {
// a better match if non-const iterator is passed as an argument.
void erase(iterator it) {
AssertIsFull(it.ctrl_, it.generation(), it.generation_ptr(), "erase()");
- PolicyTraits::destroy(&alloc_ref(), it.slot_);
+ destroy(it.slot_);
erase_meta_only(it);
}
@@ -2541,10 +2541,9 @@ class raw_hash_set {
std::pair<iterator, bool> operator()(const K& key, Args&&...) && {
auto res = s.find_or_prepare_insert(key);
if (res.second) {
- PolicyTraits::transfer(&s.alloc_ref(), s.slot_array() + res.first,
- &slot);
+ s.transfer(s.slot_array() + res.first, &slot);
} else if (do_destroy) {
- PolicyTraits::destroy(&s.alloc_ref(), &slot);
+ s.destroy(&slot);
}
return {s.iterator_at(res.first), res.second};
}
@@ -2553,13 +2552,31 @@ class raw_hash_set {
slot_type&& slot;
};
+ // Helpers to enable sanitizer mode validation to protect against reentrant
+ // calls during element constructor/destructor.
+ template <typename... Args>
+ inline void construct(slot_type* slot, Args&&... args) {
+ RunWithReentrancyGuard(*this, alloc_ref(), [&] {
+ PolicyTraits::construct(&alloc_ref(), slot, std::forward<Args>(args)...);
+ });
+ }
+ inline void destroy(slot_type* slot) {
+ RunWithReentrancyGuard(*this, alloc_ref(),
+ [&] { PolicyTraits::destroy(&alloc_ref(), slot); });
+ }
+ inline void transfer(slot_type* to, slot_type* from) {
+ RunWithReentrancyGuard(*this, alloc_ref(), [&] {
+ PolicyTraits::transfer(&alloc_ref(), to, from);
+ });
+ }
+
inline void destroy_slots() {
const size_t cap = capacity();
const ctrl_t* ctrl = control();
slot_type* slot = slot_array();
for (size_t i = 0; i != cap; ++i) {
if (IsFull(ctrl[i])) {
- PolicyTraits::destroy(&alloc_ref(), slot + i);
+ destroy(slot + i);
}
}
}
@@ -2622,7 +2639,7 @@ class raw_hash_set {
size_t new_i = target.offset;
total_probe_length += target.probe_length;
SetCtrl(common(), new_i, H2(hash), sizeof(slot_type));
- PolicyTraits::transfer(&alloc_ref(), new_slots + new_i, old_slots + i);
+ transfer(new_slots + new_i, old_slots + i);
}
}
if (old_capacity) {
@@ -2725,7 +2742,7 @@ class raw_hash_set {
reserve(size);
for (iterator it = that.begin(); it != that.end(); ++it) {
insert(std::move(PolicyTraits::element(it.slot_)));
- PolicyTraits::destroy(&that.alloc_ref(), it.slot_);
+ that.destroy(it.slot_);
}
that.dealloc();
that.common() = CommonFields{};
@@ -2816,8 +2833,7 @@ class raw_hash_set {
// POSTCONDITION: *m.iterator_at(i) == value_type(forward<Args>(args)...).
template <class... Args>
void emplace_at(size_t i, Args&&... args) {
- PolicyTraits::construct(&alloc_ref(), slot_array() + i,
- std::forward<Args>(args)...);
+ construct(slot_array() + i, std::forward<Args>(args)...);
assert(PolicyTraits::apply(FindElement{*this}, *iterator_at(i)) ==
iterator_at(i) &&
@@ -2883,8 +2899,7 @@ class raw_hash_set {
}
static void transfer_slot_fn(void* set, void* dst, void* src) {
auto* h = static_cast<raw_hash_set*>(set);
- PolicyTraits::transfer(&h->alloc_ref(), static_cast<slot_type*>(dst),
- static_cast<slot_type*>(src));
+ h->transfer(static_cast<slot_type*>(dst), static_cast<slot_type*>(src));
}
// Note: dealloc_fn will only be used if we have a non-standard allocator.
static void dealloc_fn(CommonFields& common, const PolicyFunctions&) {