Yarr JIT: word-boundary assertions corrupt the non-BMP index advance
/\B/u never consumes a character — but it still advanced the match index.
Component: JSC Yarr regex JIT | 116394d
Yarr is JSC's regex JIT compiler. For Unicode-mode regexes it generates native code that can advance the match index by more than one UTF-16 code unit when the first matched character is a non-BMP character represented as a surrogate pair; firstCharacterAdditionalReadSize records that extra advancement and is added back into m_regs.index at reentry points so subsequent matching resumes at the correct position. Word-boundary assertions (\b/\B) are zero-width — they peek at surrounding characters without consuming input — and the same fast-path optimization used for normal character matching was incorrectly left active while generating this zero-width peek, letting an inconsistent index-advancement value leak into the generated backtrack and reentry code.
The fix disables that optimization while generating word-boundary assertion code via a scoped flag, and adjusts the alternation begin/reentry backtrack path to re-add firstCharacterAdditionalReadSize into m_regs.index and re-check input via checkInput().linkTo(beginOp->m_reentry, ...) instead of jumping unconditionally.
Significance
A corrupted index-advancement value produces a malformed JSString read reachable directly from user-controlled JavaScript via /\B|.../u.exec(str). The commit message describes the observable result as a WebContent crash: the wrong match index is used later in the generated code, and the string materialized from it is built over out-of-range bounds.
Audit directions
This is a canonical JIT index-bookkeeping bug in a public tracker, which makes it a good template for sibling hunting rather than a one-off. Narrow: audit every call site that reads or mutates firstCharacterAdditionalReadSize and m_regs.index around non-consuming terms — any other zero-width construct (lookahead, lookbehind, other assertions) that reuses m_useFirstNonBMPCharacterOptimization without properly scoping it could carry the same class of bug, and the tell in review is an optimization flag consulted inside a code generator for a term that does not consume input. Wider: the same shape recurs anywhere a JIT keeps bookkeeping state whose validity is scoped to one term kind but whose flag is process-wide for the compilation — check the backtrack and reentry paths of every alternation and repetition construct where index restoration is written by hand rather than derived. Widest: fuzz Unicode regexes combining lookarounds and assertions with surrogate pairs and backtracking reentry points; the interesting corpus is inputs where a zero-width term is the first alternative, since that is where the first-character optimization arms and the zero-width term disarms nothing.