diff options
author | Evan Brown <ezb@google.com> | 2022-10-25 11:07:59 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2022-10-25 11:08:45 -0700 |
commit | 90184f6cdf914e1e88c719cfbccc15f22bfa11dc (patch) | |
tree | c92f2c1874f7614f8f341a428336f68e75f599b2 | |
parent | b3e64c416844c3579f90f4b1cc42d8d137f21b0a (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.cc | 8 | ||||
-rw-r--r-- | absl/container/internal/btree.h | 16 |
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_). |