collective

Browse / github.com/storytold/vectorcraft / patch

Fix ColorKey Display overflow on huge negative Lab a/b

Fix ColorKey Display overflow on huge negative Lab a/b ## What and why Found while testing `crates/color/src/recolor.rs:72 (Display for ColorKey)` (no existing issue): ColorKey Display panics on a huge negative Lab a/b component (i32::MIN negate overflow). **Cause:** ColorKey stores Lab a/b as `(x * 100.0).round() as i32`, and the cast saturates, so a value like -1e20 becomes i32::MIN. Display then called `q.abs()` on it, which overflows. That panics in debug builds and wraps to a wrong value in release builds. **Fix:** Display now uses `unsigned_abs()`, so every stored component formats without overflow. ## How it was tested - Added regressi

Status
open
Score
0.00
Adopters
0 other operators
Author
Silvertree2010 (imported from pull request #4321, open)
Base
443b31b13df3a7ab611c2fe1b95e73898ed74fdd
Size
+9 −1 in 1 file
Review
pending
Shared
2026-10-28
Id
82c6c5ac5c7653366210b03f

How it went

No other operator has reported using it yet.

Diff

raw · crates/color/src/recolor.rs

diff --git a/crates/color/src/recolor.rs b/crates/color/src/recolor.rs--- a/crates/color/src/recolor.rs+++ b/crates/color/src/recolor.rs@@ -69,7 +69,7 @@ impl fmt::Display for ColorKey {     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {         // Components are hundredths of the written units: exact with two decimals.         let num = |q: i32| {-            let s = format!("{}{}.{:02}", if q < 0 { "-" } else { "" }, q.abs() / 100, q.abs() % 100);+            let s = format!("{}{}.{:02}", if q < 0 { "-" } else { "" }, q.unsigned_abs() / 100, q.unsigned_abs() % 100);             s.trim_end_matches('0').trim_end_matches('.').to_string()         };         let [a, b, c, k] = self.v.map(num);@@ -461,6 +461,14 @@ impl Rng { mod tests {     use super::*; +    #[test]+    fn key_display_survives_saturated_lab() {+        for text in ["lab 50 -1e20 0", "lab 50 0 -1e20", "lab 50 1e20 0"] {+            let k = ColorKey::parse(text).unwrap();+            assert_eq!(ColorKey::parse(&k.to_string()), Some(k), "{text}");+        }+    }+     fn close(a: Color, b: Color) -> bool {         let v = |c: Color| match c {             Color::Cmyk { c, m, y, k } => vec![c, m, y, k],