From a579ca70731691a3b00710650eee746d009cd1a4 Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Sat, 24 Oct 2026 18:27:45 +0200 Subject: [PATCH] Require two hex digits in SVG href percent escapes Found while testing crates/svg/src/import/files.rs:82 (percent_decoded) Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/svg/src/import/files.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/svg/src/import/files.rs b/crates/svg/src/import/files.rs index e4732f8cd..1ee025db8 100644 --- a/crates/svg/src/import/files.rs +++ b/crates/svg/src/import/files.rs @@ -79,7 +79,11 @@ fn percent_decoded(s: &str) -> String { let mut out = Vec::with_capacity(s.len()); let mut rest = s.as_bytes(); while let Some((&b, tail)) = rest.split_first() { - let hex = tail.get(..2).and_then(|h| std::str::from_utf8(h).ok()).and_then(|h| u8::from_str_radix(h, 16).ok()); + let hex = tail + .get(..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()); match hex { Some(v) if b == b'%' => { out.push(v); @@ -304,6 +308,13 @@ fn leave_out(why: &AtomicBool, noted: bool) -> Option { mod tests { use super::*; + #[test] + fn percent_decoding_needs_two_hex_digits() { + assert_eq!(percent_decoded("a%41b"), "aAb"); + assert_eq!(percent_decoded("a%+1b"), "a%+1b"); + assert_eq!(percent_decoded("a%-1b"), "a%-1b"); + } + #[test] fn hrefs_resolve_against_the_folder() { let sep = std::path::MAIN_SEPARATOR;