From b84d9a8cfff6f7b10e7f15a8c2138b289f8fb1c7 Mon Sep 17 00:00:00 2001 From: Clyde C Brown Date: Thu, 22 Oct 2026 15:40:49 -0600 Subject: [PATCH] #2625: view.maskOverlayColor refuses signed hex digits parse_rgb checked only the length, and u8::from_str_radix accepts a leading '+', so "#+f+f+f" set the overlay to #0f0f0f. Require six hex digits, as 80e439f6 does for the other #rrggbb parsers. Co-Authored-By: Claude Opus 5.5 --- crates/ui-egui/src/menus.rs | 2 +- crates/ui-egui/src/tests_masking.rs | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/crates/ui-egui/src/menus.rs b/crates/ui-egui/src/menus.rs index 04d43e0d3..747cfbccb 100644 --- a/crates/ui-egui/src/menus.rs +++ b/crates/ui-egui/src/menus.rs @@ -340,7 +340,7 @@ fn import_into_album(app: &mut LightcraftApp, p: &Value, r: Result Option<[u8; 3]> { if let Some(s) = v.as_str() { let h = s.strip_prefix('#').unwrap_or(s); - if h.len() != 6 { + if h.len() != 6 || !h.bytes().all(|b| b.is_ascii_hexdigit()) { return None; } let c = |i: usize| u8::from_str_radix(h.get(i..i + 2)?, 16).ok(); diff --git a/crates/ui-egui/src/tests_masking.rs b/crates/ui-egui/src/tests_masking.rs index a1e5846e4..4e2fa5c20 100644 --- a/crates/ui-egui/src/tests_masking.rs +++ b/crates/ui-egui/src/tests_masking.rs @@ -295,6 +295,21 @@ fn radial_body_drag_keeps_resize_and_rotation_handles() { } } +#[test] +fn mask_overlay_color_refuses_anything_but_six_hex_digits() { + let mut h = detail("panel.masking"); + exec(&mut h, "view.maskOverlayColor", json!({"color": "#2870f0"})); + for bad in ["#+f+f+f", "+12345", "#-0-0-0", "##ffffff"] { + let r = h.request("engine.execute", json!({"command": "view.maskOverlayColor", "params": {"color": bad}}), T); + assert_eq!(r["ok"], false, "{bad:?} is not a colour: {r}"); + assert_eq!(h.app.ui.mask_overlay_color, [0x28, 0x70, 0xf0], "{bad:?} leaves the overlay colour alone"); + } + exec(&mut h, "view.maskOverlayColor", json!({"color": "e63228"})); + assert_eq!(h.app.ui.mask_overlay_color, [0xe6, 0x32, 0x28]); + exec(&mut h, "view.maskOverlayColor", json!({"color": [10, 20, 30]})); + assert_eq!(h.app.ui.mask_overlay_color, [10, 20, 30]); +} + #[test] fn mask_overlay_keys_and_pins() { use lightcraft_pipeline::{MaskView, Overlay};