vello_common: harden gradient LUT against invalid stop positions#1311
vello_common: harden gradient LUT against invalid stop positions#1311waywardmonkeys wants to merge 1 commit intolinebender:mainfrom
Conversation
- Sanitize gradient stop positions with `sanitize_stop_position` to clamp NaNs, infinities, and out-of- range values into [0, 1]. - Use sanitized positions in `determine_lut_size` and LUT ramp construction to ensure indices are finite, monotonic, and within bounds. - Keep the 4-wide write in `GradientLut::new` bounded by `lut_size` so very small LUTs cannot trigger end- index panics. - Add targeted tests to verify sanitization behavior and ensure `GradientLut` handles infinite and out-of-range stop offsets without panicking.
f291f5b to
44cc593
Compare
|
This should fix against the panic mentioned by @nicoburns in a comment in #1302. Some notes / questions:
|
| fn sanitize_stop_position(pos: f32) -> f32 { | ||
| if pos.is_nan() { | ||
| 0.0 | ||
| } else if pos.is_infinite() { | ||
| if pos.is_sign_negative() { 0.0 } else { 1.0 } | ||
| } else { | ||
| pos.clamp(0.0, 1.0) | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
The following is a branchless way to do this.
| fn sanitize_stop_position(pos: f32) -> f32 { | |
| if pos.is_nan() { | |
| 0.0 | |
| } else if pos.is_infinite() { | |
| if pos.is_sign_negative() { 0.0 } else { 1.0 } | |
| } else { | |
| pos.clamp(0.0, 1.0) | |
| } | |
| } | |
| #[inline] | |
| fn sanitize_stop_position(pos: f32) -> f32 { | |
| pos.max(0.).min(1.) | |
| } |
f32:{max,min} don't propagate NaNs (so the NaN gets turned in to 0., if pos.max(0.) is first).
LaurenzV
left a comment
There was a problem hiding this comment.
We already have a method that aims to validate the gradient before even encoding it:
So I feel like it might be better to just add this additional case here? Not much point in trying to fix a gradient that is fundamentally broken. 😄
|
I'm actually surprised this doesn't already work, because we already are checking that each stop is between 0 and 1... |
|
I will figure out why and fix it! |
|
(I already know why, just have to drive home) |
sanitize_stop_positionto clamp NaNs, infinities, and out-of- range values into [0, 1].determine_lut_sizeand LUT ramp construction to ensure indices are finite, monotonic, and within bounds.GradientLut::newbounded bylut_sizeso very small LUTs cannot trigger end- index panics.GradientLuthandles infinite and out-of-range stop offsets without panicking.