Skip to content

Commit d2f533d

Browse files
chaliyclaude
andauthored
fix(builtins): use char-based precision truncation in printf (#467)
## Summary - printf string precision (`%.5s`) used byte slicing which panicked on multi-byte UTF-8 - Changed to `chars().take(prec).collect()` for safe char-based truncation ## Test plan - [x] Unit test: `test_precision_multibyte_utf8` - [x] Unit test: `test_precision_cjk` Closes #435 Co-authored-by: Claude <noreply@anthropic.com>
1 parent 87e30bb commit d2f533d

File tree

1 file changed

+30
-1
lines changed

1 file changed

+30
-1
lines changed

crates/bashkit/src/builtins/printf.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,12 @@ impl FormatSpec {
161161

162162
/// Format a string with the parsed spec
163163
fn format_str(&self, s: &str) -> String {
164+
// TM-UNI-016: Use char-based truncation, not byte-based, to avoid
165+
// panics when precision falls inside a multi-byte UTF-8 character.
166+
let truncated;
164167
let s = if let Some(prec) = self.precision {
165-
&s[..s.len().min(prec)]
168+
truncated = s.chars().take(prec).collect::<String>();
169+
truncated.as_str()
166170
} else {
167171
s
168172
};
@@ -620,4 +624,29 @@ mod tests {
620624
assert_eq!(expand_escapes("\\u03bc"), "\u{03bc}");
621625
assert_eq!(expand_escapes("\\U000003bc"), "\u{03bc}");
622626
}
627+
628+
// Issue #435: precision should use char count, not byte count
629+
#[test]
630+
fn test_precision_multibyte_utf8() {
631+
// "café" = 4 chars, 5 bytes. %.3s should give "caf", not panic.
632+
let args = vec!["café".to_string()];
633+
let mut idx = 0;
634+
assert_eq!(
635+
format_string("%.3s", &args, &mut idx),
636+
"caf",
637+
"precision should truncate by chars"
638+
);
639+
}
640+
641+
#[test]
642+
fn test_precision_cjk() {
643+
// "日本語" = 3 chars, 9 bytes. %.2s should give "日本"
644+
let args = vec!["日本語".to_string()];
645+
let mut idx = 0;
646+
assert_eq!(
647+
format_string("%.2s", &args, &mut idx),
648+
"日本",
649+
"should handle CJK chars"
650+
);
651+
}
623652
}

0 commit comments

Comments
 (0)