summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Evan Brown <ezb@google.com>2022-10-25 11:07:59 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2022-10-25 11:08:45 -0700
commit90184f6cdf914e1e88c719cfbccc15f22bfa11dc (patch)
treec92f2c1874f7614f8f341a428336f68e75f599b2
parentb3e64c416844c3579f90f4b1cc42d8d137f21b0a (diff)
Improve b-tree error messages when dereferencing invalid iterators.
- Check for invalid generation before checking for other types of invalid iterators. - Check specifically for dereferencing end() iterators. PiperOrigin-RevId: 483725646 Change-Id: Ibca19c48b1b242384683580145be8fb9ae707bc8
-rw-r--r--absl/container/btree_test.cc8
-rw-r--r--absl/container/internal/btree.h16
2 files changed, 22 insertions, 2 deletions
diff --git a/absl/container/btree_test.cc b/absl/container/btree_test.cc
index 6a5351fe..e6d4e360 100644
--- a/absl/container/btree_test.cc
+++ b/absl/container/btree_test.cc
@@ -3340,6 +3340,14 @@ TEST(Btree, IteratorSubtraction) {
}
}
+#ifndef NDEBUG
+TEST(Btree, DereferencingEndIterator) {
+ absl::btree_set<int> set;
+ for (int i = 0; i < 1000; ++i) set.insert(i);
+ EXPECT_DEATH(*set.end(), R"regex(Dereferencing end\(\) iterator)regex");
+}
+#endif
+
} // namespace
} // namespace container_internal
ABSL_NAMESPACE_END
diff --git a/absl/container/internal/btree.h b/absl/container/internal/btree.h
index 5000d1c3..2e21dc66 100644
--- a/absl/container/internal/btree.h
+++ b/absl/container/internal/btree.h
@@ -1098,9 +1098,12 @@ class btree_iterator {
// Accessors for the key/value the iterator is pointing at.
reference operator*() const {
ABSL_HARDENING_ASSERT(node_ != nullptr);
- ABSL_HARDENING_ASSERT(node_->start() <= position_);
- ABSL_HARDENING_ASSERT(node_->finish() > position_);
assert_valid_generation();
+ ABSL_HARDENING_ASSERT(position_ >= node_->start());
+ if (position_ >= node_->finish()) {
+ ABSL_HARDENING_ASSERT(!IsEndIterator() && "Dereferencing end() iterator");
+ ABSL_HARDENING_ASSERT(position_ < node_->finish());
+ }
return node_->value(static_cast<field_type>(position_));
}
pointer operator->() const { return &operator*(); }
@@ -1158,6 +1161,15 @@ class btree_iterator {
#endif
}
+ bool IsEndIterator() const {
+ if (position_ != node_->finish()) return false;
+ // Navigate to the rightmost node.
+ node_type *node = node_;
+ while (!node->is_root()) node = node->parent();
+ while (node->is_internal()) node = node->child(node->finish());
+ return node == node_;
+ }
+
// Returns n such that n calls to ++other yields *this.
// Precondition: n exists && (this->node_ != other.node_ ||
// !this->node_->is_leaf() || this->position_ != other.position_).