aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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_).