From b142814bbdc42482eff628ce8f677e8a2c3e4e06 Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Sun, 8 Nov 2026 17:59:59 +0000 Subject: [PATCH] Reject a plus sign in type.insert unicode hex digits Found while testing crates/engine/src/cmd/typemenu.rs:614 (unicode_char) Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/engine/src/cmd/typemenu.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/crates/engine/src/cmd/typemenu.rs b/crates/engine/src/cmd/typemenu.rs index 83dfd925d..872ceee4b 100644 --- a/crates/engine/src/cmd/typemenu.rs +++ b/crates/engine/src/cmd/typemenu.rs @@ -611,6 +611,9 @@ pub(crate) fn alt_code_char(code: u64) -> Option { fn unicode_char(u: &str) -> Option { let u = u.trim(); let hex = u.strip_prefix("U+").or_else(|| u.strip_prefix("u+")).or_else(|| u.strip_prefix("0x")).unwrap_or(u); + if hex.is_empty() || !hex.bytes().all(|b| b.is_ascii_hexdigit()) { + return None; + } char::from_u32(u32::from_str_radix(hex, 16).ok()?).filter(|c| !c.is_control() || *c == '\t') } @@ -843,3 +846,18 @@ fn paste_plain(s: &mut Session, p: &Value) -> Result { } r } + +#[cfg(test)] +mod tests { + use super::unicode_char; + + #[test] + fn unicode_char_rejects_sign_in_hex_digits() { + assert_eq!(unicode_char("+B0"), None); + assert_eq!(unicode_char("U++B0"), None); + assert_eq!(unicode_char("U+"), None); + assert_eq!(unicode_char("00B0"), Some('°')); + assert_eq!(unicode_char("U+00B0"), Some('°')); + assert_eq!(unicode_char("0x00B0"), Some('°')); + } +}