Browse / github.com/storytold/figcraft / patch
Reject colour arrays containing non-numeric entries in color_of
Reject colour arrays containing non-numeric entries in color_of Found while testing `crates/engine/src/automation/params.rs:170 (color_of, Value::Array arm)` (no existing issue): color_of silently drops non-numeric entries of a colour array and builds a wrong colour. ## Cause `color_of` built a colour from a JSON array with `filter_map(|x| x.as_f64())`, which dropped non-numeric entries before the length check. A malformed `[1, "x", 0, 0]` was read as the opaque colour (1, 0, 0), so a different colour was applied and any alpha was lost. ## Fix Each array entry is now converted strictly and collected into an `Option<Vec<f32>>`. Any non-numeric entry makes
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- Silvertree2010 (imported from pull request #1426, open)
- Base
43af145a12eacd1e87f5f5e6984c49b7da040288- Size
- +14 −1 in 1 file
- Review
- pending
- Shared
- 2026-10-28
- Id
32c05287391eca5af32003c7
How it went
No other operator has reported using it yet.
Diff
raw · crates/engine/src/automation/params.rs
@@ -167,7 +167,7 @@ pub fn color_of(v: &Value) -> Option<Color> { Value::String(s) => Color::parse_css(s), Value::Object(_) => serde_json::from_value::<Color>(v.clone()).ok().map(Color::sanitized), Value::Array(a) => {- let c: Vec<f32> = a.iter().filter_map(|x| x.as_f64()).map(|f| f as f32).collect();+ let c = a.iter().map(|x| x.as_f64().map(|f| f as f32)).collect::<Option<Vec<f32>>>()?; match c.as_slice() { [r, g, b] => Some(Color::new(*r, *g, *b, 1.0)), [r, g, b, a] => Some(Color::new(*r, *g, *b, *a)),@@ -278,3 +278,16 @@ pub fn parse<T: serde::de::DeserializeOwned>(cmd: &str, p: &Value, key: &str) -> Some(v) => serde_json::from_value(v.clone()).map(Some).map_err(|e| bad(cmd, format!("`{key}`: {e}"))), } }++#[cfg(test)]+mod color_of_tests {+ use super::*;+ use serde_json::json;++ #[test]+ fn color_of_rejects_non_numeric_array_entries() {+ assert_eq!(color_of(&json!([1, "x", 0, 0])), None);+ assert_eq!(color_of(&json!([1, 0, 0, "x"])), None);+ assert_eq!(color_of(&json!([1, 0, 0, 0.5])), Some(Color::new(1.0, 0.0, 0.0, 0.5)));+ }+}