Skip to content

Commit

Permalink
kv/kvserver/spanset: fix read of invalid iterator's UnsafeKey
Browse files Browse the repository at this point in the history
Previously, the spanset.MVCCIterator implementation would retrieve the
contained iterator's UsafeKey() on an invalid iterator in Next, NextKey and
Prev. This retrieval was harmless because it always checked the validity of the
iterator before using it, but recent assertions in test builds prevent this
usage.

Release note: None
  • Loading branch information
jbowens committed Feb 23, 2023
1 parent cfb711f commit 05f7c76
Showing 1 changed file with 23 additions and 3 deletions.
26 changes: 23 additions & 3 deletions pkg/kv/kvserver/spanset/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,21 +103,37 @@ func (i *MVCCIterator) SeekLT(key storage.MVCCKey) {
// Next is part of the storage.MVCCIterator interface.
func (i *MVCCIterator) Next() {
i.i.Next()
i.checkAllowed(roachpb.Span{Key: i.UnsafeKey().Key}, false)
i.checkAllowedCurrPosForward(false)
}

// Prev is part of the storage.MVCCIterator interface.
func (i *MVCCIterator) Prev() {
i.i.Prev()
i.checkAllowed(roachpb.Span{Key: i.UnsafeKey().Key}, false)
i.checkAllowedCurrPosForward(false)
}

// NextKey is part of the storage.MVCCIterator interface.
func (i *MVCCIterator) NextKey() {
i.i.NextKey()
i.checkAllowed(roachpb.Span{Key: i.UnsafeKey().Key}, false)
i.checkAllowedCurrPosForward(false)
}

// checkAllowedCurrPosForward checks the span starting at the current iterator
// position, if the current iterator position is valid.
func (i *MVCCIterator) checkAllowedCurrPosForward(errIfDisallowed bool) {
i.invalid = false
i.err = nil
if ok, _ := i.i.Valid(); !ok {
// If the iterator is invalid after the operation, there's nothing to
// check. We allow uses of iterators to exceed the declared span bounds
// as long as the iterator itself is configured with proper boundaries.
return
}
i.checkAllowedValidPos(roachpb.Span{Key: i.UnsafeKey().Key}, errIfDisallowed)
}

// checkAllowed checks the provided span if the current iterator position is
// valid.
func (i *MVCCIterator) checkAllowed(span roachpb.Span, errIfDisallowed bool) {
i.invalid = false
i.err = nil
Expand All @@ -127,6 +143,10 @@ func (i *MVCCIterator) checkAllowed(span roachpb.Span, errIfDisallowed bool) {
// as long as the iterator itself is configured with proper boundaries.
return
}
i.checkAllowedValidPos(span, errIfDisallowed)
}

func (i *MVCCIterator) checkAllowedValidPos(span roachpb.Span, errIfDisallowed bool) {
var err error
if i.spansOnly {
err = i.spans.CheckAllowed(SpanReadOnly, span)
Expand Down

0 comments on commit 05f7c76

Please sign in to comment.