Skip to content

Commit ce70686

Browse files
committed
fix(context): avoid UTF-8 panic when probing .md suffix
Check the last three bytes on the UTF-8 byte slice before slicing the str, so stems like xπ•Œ (without .md) do not use a misaligned str index. Adds regression tests for multibyte stems with and without .md.
1 parent a2d81e1 commit ce70686

1 file changed

Lines changed: 22 additions & 5 deletions

File tree

β€Žsrc/context.rsβ€Ž

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,17 @@ pub fn normalize_context_cli_name(name: &str) -> String {
5858
.and_then(|n| n.to_str())
5959
.unwrap_or(trimmed);
6060
const MD_SUFFIX: &str = ".md";
61-
if basename.len() >= MD_SUFFIX.len() {
62-
let start = basename.len() - MD_SUFFIX.len();
63-
let suffix = &basename[start..];
64-
if suffix.eq_ignore_ascii_case(MD_SUFFIX) {
65-
return basename[..start].to_string();
61+
let md_len = MD_SUFFIX.len();
62+
let bytes = basename.as_bytes();
63+
if bytes.len() >= md_len {
64+
let i = bytes.len() - md_len;
65+
// Inspect bytes only: avoid slicing `str` at `i` until we know the last `md_len` bytes are
66+
// ASCII `.md` (so `i` is a UTF-8 char boundary β€” e.g. `xπ•Œ` must not index `basename[2..]`).
67+
if bytes[i] == b'.'
68+
&& bytes[i + 1].eq_ignore_ascii_case(&b'm')
69+
&& bytes[i + 2].eq_ignore_ascii_case(&b'd')
70+
{
71+
return basename[..i].to_string();
6672
}
6773
}
6874
basename.to_string()
@@ -374,4 +380,15 @@ mod tests {
374380
fn normalize_strips_md_one_char_stem() {
375381
assert_eq!(normalize_context_cli_name("a.md"), "a");
376382
}
383+
384+
#[test]
385+
fn normalize_does_not_panic_multibyte_stem_without_md() {
386+
// 1 ASCII byte + 4-byte UTF-8; byte index 2 is inside the codepoint β€” must not slice there.
387+
assert_eq!(normalize_context_cli_name("xπ•Œ"), "xπ•Œ");
388+
}
389+
390+
#[test]
391+
fn normalize_strips_md_after_multibyte_char() {
392+
assert_eq!(normalize_context_cli_name("xπ•Œ.md"), "xπ•Œ");
393+
}
377394
}

0 commit comments

Comments
Β (0)