From 3688ad7a46708c15469ac593a8aeae531b6a6e4d Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Fri, 16 Oct 2026 19:33:39 +0200 Subject: [PATCH] Reject '+' and other non-hex characters in Color::from_hex Found while testing crates/color/src/lib.rs:184 Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/color/src/lib.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/crates/color/src/lib.rs b/crates/color/src/lib.rs index 742dfb749..6fc854ff0 100644 --- a/crates/color/src/lib.rs +++ b/crates/color/src/lib.rs @@ -181,6 +181,10 @@ impl Color { _ => {} } let h = s.strip_prefix('#').unwrap_or(s); + // `from_str_radix` accepts a leading `+`, so check the digits first. + if !h.chars().all(|c| c.is_ascii_hexdigit()) { + return None; + } let p = |i: usize, n: usize| u8::from_str_radix(h.get(i..i + n)?, 16).ok(); match h.len() { 3 => Some(Color::rgb8(p(0, 1)? * 17, p(1, 1)? * 17, p(2, 1)? * 17)), @@ -412,6 +416,14 @@ mod tests { assert_eq!(Color::from_hex("zz"), None); } + #[test] + fn hex_rejects_sign_characters() { + for bad in ["#+1+2+3", "+f+f+f", "#-1-2-3", "#+12+34+56", "#+f+f+f+f", "#12345+"] { + assert_eq!(Color::from_hex(bad), None, "{bad}"); + } + assert_eq!(Color::from_hex("#123"), Color::from_hex("#112233")); + } + #[test] fn hsb_roundtrip() { for hex in ["#ff0000", "#00ff00", "#0000ff", "#336699", "#ffffff", "#000000", "#c0ffee"] {