Go regexp too slow? I built coregex, a drop-in replacement. An audit found 16 bugs — here's what broke
Description and use
Coregex, a drop‑in replacement for Go's regexp, uncovered 16 bugs after an audit, including incorrect matches, Unicode handling issues, and a DoS vulnerability. Fixes reduced divergence to 0.75% and improved performance on short strings.
Problem
Coregex, a drop-in replacement for Go's regexp, produced incorrect matches, performance regressions, and denial‑of‑service vulnerabilities after a code audit revealed 16 bugs.
Outcome
Coregex now correctly handles complex patterns, Unicode classes, and large inputs, with reduced divergence from the Go stdlib and improved performance on short strings.
Workflow
- Commissioned independent code review and differential fuzz
- Identified 6% divergence and 16 bugs
- Analyzed each bug: branch‑dispatch, case‑insensitive Cyrillic, large‑input Unicode class, empty‑match UTF‑8 slicing, 15‑char DoS
- Implemented fixes: removed branch‑dispatch, used SimpleFold orbit, corrected reverse DFA fallback, fixed empty‑match advancement, removed Sub0 clone loop
- Re‑ran differential fuzz: divergence 0.75%
- Documented remaining issues and tracked them
Evidence
6% of random pattern/input pairs gave wrong answers.
BranchDispatch optimization dispatched by first byte, then verified the match with a simple matcher that couldn't handle real AST shapes.
Non-ASCII runes with case-insensitive flag were compiled as exact uppercase match.
\pL+ on a 50KB file: MatchString returned true, but FindAllStringIndex returned zero or one match instead of thousands.
After an empty match, the position advanced by one byte instead of one rune.
15-character pattern caused >3 GB heap, >15 seconds, OOM kill.
- Record date: 2026-10-09T09:41:02.158Z