Skip to content

Commit 8b528fa

Browse files
authored
fix: add anchoredFirstBytes check to state-reusing BoundedBacktracker (#111)
findIndicesBoundedBacktrackerAtWithState was missing the O(1) early rejection check that exists in findIndicesBoundedBacktracker. For pattern ^/.*[\w-]+\.php on 6MB input not starting with '/': - Before: 377ms (full PikeVM scan) - After: 40µs (O(1) rejection) 9000x improvement for non-matching anchored patterns. Fixes #107
1 parent f0f527d commit 8b528fa

File tree

2 files changed

+20
-0
lines changed

2 files changed

+20
-0
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414

1515
---
1616

17+
## [0.11.9] - 2026-02-02
18+
19+
### Fixed
20+
- **Missing first-byte prefilter in FindAll state-reusing path** (Issue #107)
21+
- `findIndicesBoundedBacktrackerAtWithState` was missing `anchoredFirstBytes` check
22+
- Pattern `^/.*[\w-]+\.php` (without `$`) took 377ms instead of 40µs on 6MB input
23+
- Added O(1) early rejection for anchored patterns not starting with required byte
24+
- Fix: **377ms → 40µs** (9000x improvement for non-matching anchored patterns)
25+
26+
---
27+
1728
## [0.11.8] - 2026-02-01
1829

1930
### Fixed

meta/find_indices.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,15 @@ func (e *Engine) findIndicesBoundedBacktrackerAtWithState(haystack []byte, at in
915915
if e.boundedBacktracker == nil {
916916
return e.findIndicesNFAAtWithState(haystack, at, state)
917917
}
918+
919+
// O(1) early rejection for anchored patterns using first-byte prefilter.
920+
// For pattern ^/.*\.php, reject inputs not starting with "/" immediately.
921+
if at == 0 && e.anchoredFirstBytes != nil && len(haystack) > 0 {
922+
if !e.anchoredFirstBytes.Contains(haystack[0]) {
923+
return -1, -1, false
924+
}
925+
}
926+
918927
atomic.AddUint64(&e.stats.NFASearches, 1)
919928

920929
// Slice to remaining portion for more efficient BoundedBacktracker usage.

0 commit comments

Comments
 (0)