diff --git a/crates/engine/src/cmd/place/rtf.rs b/crates/engine/src/cmd/place/rtf.rs index b28797061..5af951952 100644 --- a/crates/engine/src/cmd/place/rtf.rs +++ b/crates/engine/src/cmd/place/rtf.rs @@ -108,7 +108,12 @@ pub(super) fn import(bytes: &[u8], cmd: &str) -> Result { match next { b'*' => starred = true, b'\'' => { - if let Some(v) = bytes.get(i..i + 2).and_then(|h| std::str::from_utf8(h).ok()).and_then(|h| u8::from_str_radix(h, 16).ok()) { + if let Some(v) = bytes + .get(i..i + 2) + .filter(|h| h.iter().all(u8::is_ascii_hexdigit)) + .and_then(|h| std::str::from_utf8(h).ok()) + .and_then(|h| u8::from_str_radix(h, 16).ok()) + { i += 2; r.byte(v); } @@ -650,6 +655,13 @@ mod tests { assert_eq!(text_of(&mac), "é•", "Mac Roman"); } + #[test] + fn hex_escapes_need_two_hex_digits() { + assert_eq!(text_of(&read(r"{\rtf1\ansi A\'+1B}")), "A+1B"); + assert_eq!(text_of(&read(r"{\rtf1\ansi A\'-1B}")), "A-1B"); + assert_eq!(text_of(&read(r"{\rtf1\ansi A\'g0B}")), "Ag0B"); + } + #[test] fn upr_groups_read_their_unicode_text() { let s = read(concat!(r"{\rtf1 a{\upr{\f0 b?}{\*\ud{\f0 c\u", "945", r"?}}}d}"));