Merge PR #2083: Reject signed hex digits in #rrggbb colour parsing

This commit is contained in:
Brandon Thomas committed 2026-10-18 09:18:16 -04:00
commit 9bf08f6ce6
3 files changed
+18 -4

No files matched your search

+11 -2
View File
@@ -180,8 +180,8 @@ pub struct Rgb8(pub u8, pub u8, pub u8);
impl Rgb8 {
pub fn from_hex(s: &str) -> Option<Rgb8> {
let s = s.trim_start_matches('#');
if s.len() != 6 {
let s = s.strip_prefix('#').unwrap_or(s);
if s.len() != 6 || !s.bytes().all(|b| b.is_ascii_hexdigit()) {
return None;
}
let v = u32::from_str_radix(s, 16).ok()?;
@@ -196,6 +196,15 @@ impl Rgb8 {
mod tests {
use super::*;
#[test]
fn rgb8_from_hex_rejects_signs_and_extra_hashes() {
assert_eq!(Rgb8::from_hex("#0f0f0f"), Some(Rgb8(15, 15, 15)));
assert_eq!(Rgb8::from_hex("ff8000"), Some(Rgb8(255, 128, 0)));
for bad in ["+12345", "#+12345", "#+f+f+f", "-12345", "##123456", "#12345", ""] {
assert_eq!(Rgb8::from_hex(bad), None, "{bad}");
}
}
#[test]
fn srgb_matrix_matches_standard() {
let m = SRGB.to_xyz();
+3 -1
View File
@@ -115,7 +115,7 @@ fn color(v: &Value) -> std::result::Result<Option<[u8; 3]>, String> {
Value::String(s) if s.is_empty() || s.eq_ignore_ascii_case("none") => Ok(None),
Value::String(s) => {
let h = s.strip_prefix('#').unwrap_or(s);
if h.len() != 6 || !h.is_ascii() {
if h.len() != 6 || !h.bytes().all(|b| b.is_ascii_hexdigit()) {
return Err(bad());
}
let byte = |i: usize| h.get(i..i + 2).and_then(|x| u8::from_str_radix(x, 16).ok()).ok_or_else(bad);
@@ -747,6 +747,8 @@ mod tests {
json!({"repeat": 1}),
json!({"fadeColor": "#12345"}),
json!({"fadeColor": "#ééé"}),
json!({"fadeColor": "#+f+f+f"}),
json!({"fadeColor": "-12345"}),
json!({"fadeColor": [300, 0, 0]}),
json!({"fadeColor": [1, 2]}),
json!({"speed": 2}),
+4 -1
View File
@@ -293,7 +293,7 @@ pub fn parse_color(v: &Value) -> Option<[u8; 3]> {
match v {
Value::String(s) => {
let h = s.trim().strip_prefix('#').unwrap_or(s.trim());
if h.len() != 6 || !h.is_ascii() {
if h.len() != 6 || !h.bytes().all(|b| b.is_ascii_hexdigit()) {
return None;
}
let byte = |i: usize| h.get(i..i + 2).and_then(|x| u8::from_str_radix(x, 16).ok());
@@ -356,6 +356,9 @@ mod tests {
json!({"zoomToFill": 1}),
json!({"strokeColor": "#12345"}),
json!({"strokeColor": "#ééééé"}),
json!({"strokeColor": "#+f+f+f"}),
json!({"backdropColor": "+12345"}),
json!({"washColor": "#-00000"}),
json!({"washColor": [256, 0, 0]}),
json!({"washColor": [-1, 0, 0]}),
json!({"backdropColor": [1, 2]}),