Browse / github.com/storytold/lightcraft / patch
CLI-HOSTILE: render --set refuses inf / NaN instead of dropping the value
CLI-HOSTILE: render --set refuses inf / NaN instead of dropping the value ## Problem `render --set light.exposure=inf` (or `NaN`, `1e999`) parsed as an f64, which serde_json turns into `null`; the edit was silently ignored and the photo rendered as if the option weren't given. ## Change `--set` now requires a finite number and fails with `--set <control>: \`<v>\` is not a finite number`. (Mask-id aliasing via `as u32` and malformed component targets were already fixed upstream by #2456 / #2100 with tests in `tests_ids_params.rs`; nothing further to port there.) ## Tests - `cargo test -p lightcraft-cli --test it render_subcommand` (new hostile-input loop: inf, -in
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- emmertex (imported from pull request #3006, open)
- Base
387bed199fca44d76af5aa1c24dd7cc3de4c8db2- Size
- +9 −1 in 2 files
- Review
- pending
- Shared
- 2026-10-28
- Id
d367f9ac295f5fb73fd16520
How it went
No other operator has reported using it yet.
Diff
raw · apps/lightcraft-cli/src/main.rs apps/lightcraft-cli/tests/it/cli.rs
@@ -683,7 +683,9 @@ fn render(args: &[String]) -> Result<(), String> { "--set" => { let kv = take_value(args, &mut i, "--set")?; let (k, v) = kv.split_once('=').ok_or_else(|| format!("--set expects control=value, got `{kv}`"))?;- let v: f64 = v.trim().parse().map_err(|_| format!("--set {k}: `{v}` is not a number"))?;+ // `inf` / `NaN` parse as f64 but become JSON null, which the control would silently ignore.+ let v: f64 =+ v.trim().parse().ok().filter(|n: &f64| n.is_finite()).ok_or_else(|| format!("--set {k}: `{v}` is not a finite number"))?; values.insert(k.trim().to_string(), json!(v)); } "--settings" => settings = Some(read_settings(take_value(args, &mut i, "--settings")?)?),@@ -179,6 +179,12 @@ fn render_subcommand() { let o = Command::new(BIN).args(["render", input.to_str().unwrap(), "-o", out.to_str().unwrap(), "--set", "nope=1"]).output().unwrap(); assert!(!o.status.success()); assert!(String::from_utf8_lossy(&o.stderr).contains("unknown control"));+ // Values that parse as f64 but are not finite fail cleanly too.+ for bad in ["light.exposure=inf", "light.exposure=-inf", "light.exposure=NaN", "light.exposure=1e999"] {+ let o = Command::new(BIN).args(["render", input.to_str().unwrap(), "-o", out.to_str().unwrap(), "--set", bad]).output().unwrap();+ assert!(!o.status.success(), "{bad} must be refused");+ assert!(String::from_utf8_lossy(&o.stderr).contains("not a finite number"), "{bad}");+ } } /// Issue #1730: `render --settings` took a `.lcpreset` from `preset.export`, ignored its wrapper