Color Lookup: a malformed or second .3dl shaper row is refused

Review by @bommerts on #9170: a shaper row with a token that isn't a number
(0 341 junk 682 1023) had the token dropped, which can turn a bent shaper
into an even ramp and lose it, and a second shaper row was ignored. Every
token of a numeric line must parse, and only one shaper row ahead of the
table is read. New test: three_dl_malformed_shaper_rows_are_refused (both
files loaded without the fix).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hector VillarrealandClaude Opus 5.5 committed 2026-10-24 15:28:37 -06:00
1 parent 97cf5d81d2
commit 999a2c7be1
1 file changed
+19 -3
+19 -3
View File
@@ -189,11 +189,16 @@ pub fn parse_3dl(text: &str) -> Result<LutFile, LutError> {
if line.is_empty() || line.starts_with(|c: char| c.is_ascii_alphabetic()) {
continue;
}
let v: Vec<f64> = line.split_whitespace().filter_map(|s| s.parse().ok()).collect();
// Every token is a number: a malformed one is refused rather than dropped, which could
// turn a shaper into an even ramp and lose it silently.
let v: Vec<f64> = line.split_whitespace().map(str::parse).collect::<Result<_, _>>().map_err(|_| LutError(format!("bad line `{line}`")))?;
if v.len() == 3 {
rows.push([v[0], v[1], v[2]]);
} else if v.len() > 3 && shaper.is_none() && rows.is_empty() {
// The input shaper: one row of values ahead of the table.
} else if v.len() > 3 {
// The input shaper: one row of values ahead of the table, and only one.
if shaper.is_some() || !rows.is_empty() {
return err(format!("a second shaper row `{line}`"));
}
shaper = Some(v);
}
}
@@ -505,6 +510,17 @@ mod tests {
}
}
/// #9170 review (bommerts): a shaper row with a token that isn't a number, or a second
/// shaper row, is refused rather than silently dropped.
#[test]
fn three_dl_malformed_shaper_rows_are_refused() {
let table = identity_3dl(&[0, 1, 2, 3], 4);
let body = table.split_once('\n').unwrap().1;
assert!(parse_3dl(&format!("0 341 junk 682 1023\n{body}")).is_err(), "a junk token");
assert!(parse_3dl(&format!("0 114 455 1023\n0 114 455 1023\n{body}")).is_err(), "two shaper rows");
assert!(parse_3dl(&format!("0 114 455 1023\n{body}")).is_ok());
}
#[test]
fn cube_title_with_hash_round_trips() {
let l = LutFile::from_fn("Look #3", 2, |c| c);