Description
truncate_summary in src/annotate/converters/mod.rs panics on doc-comment summaries that contain multi-byte UTF-8 characters (e.g. box-drawing characters like ─, U+2500, 3 bytes in UTF-8) when the byte offset used for truncation (max_len) lands in the middle of one of those characters.
Repro
Running acp annotate over a JS file containing a comment block like:
// ─── Config ─────────────────────────────────────────────────────────────────
produces:
thread '<unnamed>' panicked at src/annotate/converters/mod.rs:281:34:
end byte index 100 is not a char boundary; it is inside '─' (bytes 98..101) of `─── Config ─────────────────────────────────────────────────────────────────`
Root cause
fn truncate_summary(summary: &str, max_len: usize) -> String {
let trimmed = summary.trim();
if trimmed.len() <= max_len {
trimmed.to_string()
} else {
// Find the last space before max_len to avoid cutting words
let truncate_at = trimmed[..max_len].rfind(' ').unwrap_or(max_len);
format!("{}...", &trimmed[..truncate_at])
}
}
trimmed[..max_len] slices by raw byte offset with no check that max_len falls on a UTF-8 char boundary. Any input where a multi-byte character straddles byte max_len (currently called with max_len = 100) panics instead of truncating.
Fix
I have a fix ready (back off max_len to the nearest preceding is_char_boundary before slicing) plus a regression test, and will open a PR shortly.
Description
truncate_summaryinsrc/annotate/converters/mod.rspanics on doc-comment summaries that contain multi-byte UTF-8 characters (e.g. box-drawing characters like─, U+2500, 3 bytes in UTF-8) when the byte offset used for truncation (max_len) lands in the middle of one of those characters.Repro
Running
acp annotateover a JS file containing a comment block like:produces:
Root cause
trimmed[..max_len]slices by raw byte offset with no check thatmax_lenfalls on a UTF-8 char boundary. Any input where a multi-byte character straddles bytemax_len(currently called withmax_len = 100) panics instead of truncating.Fix
I have a fix ready (back off
max_lento the nearest precedingis_char_boundarybefore slicing) plus a regression test, and will open a PR shortly.