Color Lookup: a .3dl shaper starting with NaN or inf isn't a header

CodeRabbit finding on #9170 ("Reject shaper rows that begin with NaN or
inf"): lines starting with a letter were skipped as headers, so a shaper
beginning with NaN or inf was dropped before the non-finite check and the
table loaded alone. A header is now a line whose first word isn't a number
(3DMESH, Mesh 4 12); NaN and inf parse as numbers, so such a shaper is
read and refused. New test: three_dl_shaper_starting_non_finite_is_refused
(the 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-30 12:58:56 -06:00
1 parent 068791475e
commit 909ded33f8
1 file changed
+14 -3
+14 -3
View File
@@ -246,9 +246,9 @@ pub fn parse_3dl(text: &str) -> Result<LutFile, LutError> {
if line.is_empty() {
continue;
}
// Headers: `Mesh 4 12` and the like start with a letter; the `3DMESH` preamble with a digit.
let preamble = line.split_whitespace().next().is_some_and(|t| t.eq_ignore_ascii_case("3DMESH"));
if preamble || line.starts_with(|c: char| c.is_ascii_alphabetic()) {
// A header (`3DMESH`, `Mesh 4 12`…) starts with a word that isn't a number. `NaN` and
// `inf` are numbers: a row starting with one is a shaper or table row, read strictly.
if line.split_whitespace().next().is_none_or(|t| t.parse::<f64>().is_err()) {
header = true;
// The only header keyword that carries data. A malformed or out-of-range `Mesh`
// line is ignored, as every text line always was.
@@ -671,6 +671,17 @@ mod tests {
}
}
/// #9170 review: a shaper row that starts with `NaN` or `inf` is a shaper, not a header, so
/// it reaches the non-finite refusal instead of being skipped.
#[test]
fn three_dl_shaper_starting_non_finite_is_refused() {
let body = identity_3dl(&[0, 1, 2, 3], 4);
let body = body.split_once('\n').unwrap().1;
for shaper in ["NaN 341 682 1023", "inf 341 682 1023", "-inf 341 682 1023"] {
assert!(parse_3dl(&format!("{shaper}\n{body}")).is_err(), "{shaper}");
}
}
#[test]
fn cube_title_with_hash_round_trips() {
let l = LutFile::from_fn("Look #3", 2, |c| c);