Problem
With styling disabled, AutoStream still walks every record through anstyle-parse's VT state machine, roughly doubling per-record cost even for builds emitting no styling.
Target::Stderr → /dev/null, 161-byte records, 500k iterations, release + LTO, 8 interleaved rounds:
|
ns/record |
with color |
596 |
without color |
302 |
Turning off just auto-color doesn't avoid it — WriteStyle::Auto then collapses to Never (src/writer/mod.rs:134), making the parse unconditional. Only dropping color entirely removes the parser.
However dropping color also removes sanitization, as the two share a code path, so untrusted input then reaches the reader's terminal verbatim:
Note: deactivating the build-time feature color is not a mitigation as that
removes all ANSI escape code stripping from env_logger.
Neither configuration avoids both. The coupling isn't required though: without color there is no styling emitted, so nothing needs parsing, only payload bytes need neutralizing.
Proposal
Escape C0 and DEL as \xNN when color is off, sparing \n and \t.
- 319 ns/record measured, so sanitizing costs ~17 ns over the unsafe build today
color path untouched, no behavior change for anyone using it
- differs from the strip it replaces in both directions:
- stricter on
\r, VT and FF, which anstream passes through
- more permissive on raw C1 and stray continuation bytes, which
anstream drops (matching it there needs full UTF-8 validation — ~20 lines, free for ASCII records, ~+40 ns/record for records with legitimate non-ASCII)
Problem
With styling disabled,
AutoStreamstill walks every record throughanstyle-parse's VT state machine, roughly doubling per-record cost even for builds emitting no styling.Target::Stderr→/dev/null, 161-byte records, 500k iterations, release + LTO, 8 interleaved rounds:colorcolorTurning off just
auto-colordoesn't avoid it —WriteStyle::Autothen collapses toNever(src/writer/mod.rs:134), making the parse unconditional. Only droppingcolorentirely removes the parser.However dropping
coloralso removes sanitization, as the two share a code path, so untrusted input then reaches the reader's terminal verbatim:Neither configuration avoids both. The coupling isn't required though: without
colorthere is no styling emitted, so nothing needs parsing, only payload bytes need neutralizing.Proposal
Escape C0 and DEL as
\xNNwhencoloris off, sparing\nand\t.colorpath untouched, no behavior change for anyone using it\r, VT and FF, whichanstreampasses throughanstreamdrops (matching it there needs full UTF-8 validation — ~20 lines, free for ASCII records, ~+40 ns/record for records with legitimate non-ASCII)