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
@@ -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],