02cf0f7d75
Sanitizing user-authored response fields ran multiple allocating passes over every string regardless of content: FilterInvisibleCharacters converted the whole input to []rune and back, FilterCodeFenceMetadata split and rejoined every line, and bluemonday ran unconditionally. On comment- and issue-heavy responses this dominated conversion CPU and allocation. Three changes, none of which alter output or widen what the policy allows: - FilterInvisibleCharacters scans first and copies only from the first filtered rune, skipping ASCII runs without decoding them. Invalid UTF-8 is still re-encoded to U+FFFD, matching the []rune round trip it replaces. - FilterCodeFenceMetadata walks lines in place and returns the input when no line changes. - FilterHTMLTags skips bluemonday for input that is provably a fixed point of the policy: printable ASCII, TAB and LF, with none of the five characters html.EscapeString rewrites. Sanitize also skips the second invisible/code-fence pass when HTML normalization returned its input unchanged, since both filters are fixed points there. Equivalence is pinned by a verbatim copy of the previous pipeline: the new code is diffed against it over a corpus of ~22k deterministic cases plus two fuzz targets, and the fast path is checked byte by byte against the live bluemonday policy. Benchmarks (Intel Ultra 9 185H, n=6): Sanitize/TitleASCII 5.35µs -> 114ns 1 -100% allocs Sanitize/Comment1KiB 45.3µs -> 1.27µs 1 -100% allocs Sanitize/Body64KiB 2.47ms -> 85.9µs 1 -100% allocs 30 issues x 2KiB body 3.00ms -> 88.6µs 1.55MiB -> 1.9KiB 100 comments x 1KiB 5.04ms -> 169µs 2.19MiB -> 6.3KiB Content that genuinely needs rewriting still pays for it, and non-ASCII text still goes through bluemonday by design. Fixes #3117 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>