Skip to content

Commit c0392a6

Browse files
committed
perf/search: keep folded mismatch checks constant-time
Most candidate mismatches occur well before the document boundary, where UTF-8's maximum rune width can prove the remaining span fits without decoding it. Reserve the exact rune walk for boundary-adjacent candidates so corruption remains observable without multiplying query-length work across broad candidate sets. Amp-Thread-ID: https://ampcode.com/threads/T-019fd1ab-1ad4-77f5-9b59-c65232f5b3f1
1 parent 471350d commit c0392a6

1 file changed

Lines changed: 13 additions & 0 deletions

File tree

index/bits.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,19 @@ func caseFoldingEqualsRunes(lower, mixed []byte) (int, bool, bool) {
9494
}
9595

9696
func hasEnoughRunes(mixed, lower []byte) bool {
97+
// A UTF-8 rune occupies at most UTFMax bytes, and lower cannot contain
98+
// more runes than bytes. A sufficiently long mixed suffix therefore proves
99+
// the candidate span fits without walking either slice. In practice this
100+
// keeps ordinary mismatches constant-time and reserves the exact scan below
101+
// for candidates close enough to the document end to be truncated.
102+
if len(mixed)/utf8.UTFMax >= len(lower) {
103+
return true
104+
}
105+
106+
// Compare only rune availability, not values: the caller already knows the
107+
// candidate mismatches. Reaching the end of mixed first means the candidate's
108+
// expected rune span crosses the document boundary, which is a corrupt index
109+
// invariant rather than an ordinary non-match.
97110
for len(lower) > 0 {
98111
if len(mixed) == 0 {
99112
return false

0 commit comments

Comments
 (0)