From 58c24883c7a1ae98b0829c4fc9af4b7a326b78c6 Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Tue, 3 Nov 2026 01:14:15 +0100 Subject: [PATCH 1/2] Reject png/jpeg targets in file.save instead of writing zip bytes Found while testing crates/engine/src/cmd/file.rs:489 (save, with save_bytes at :341-349 and format_for_path at :440) Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/engine/src/cmd/file.rs | 1 + crates/engine/src/tests.rs | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/crates/engine/src/cmd/file.rs b/crates/engine/src/cmd/file.rs index 0d52e6358..53009f51f 100644 --- a/crates/engine/src/cmd/file.rs +++ b/crates/engine/src/cmd/file.rs @@ -345,6 +345,7 @@ pub fn save_bytes(doc: &Presentation, format: &str) -> Result> { "rtf" => Ok(deckcraft_format::rtf::slides_to_rtf(doc).into_bytes()), "pdf" => deckcraft_pdf::export(doc, &Default::default()).map_err(|e| EngineError::Other(e.to_string())), "gif" => gif_bytes(doc, &Value::Null), + "png" | "jpeg" => Err(EngineError::Other("saving a presentation as a single image isn't supported; use file.export".into())), _ => deckcraft_format::save(doc).map_err(|e| EngineError::Other(e.to_string())), } } diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index 68de13418..12b13e680 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -6458,3 +6458,19 @@ fn master_body_placeholder_format_keeps_per_level_formatting() { assert_eq!((level(&s, 0).run.size, level(&s, 1).run.size), (Some(28.0), Some(24.0))); assert_eq!(shown(&s), vec![Some(28.0), Some(24.0)]); } + +#[test] +fn save_to_image_path_is_an_error_not_zip_bytes() { + let dir = std::env::temp_dir().join(format!("deckcraft-save-img-{}", std::process::id())); + std::fs::create_dir_all(&dir).unwrap(); + for (cmd, name) in [("file.save", "a.png"), ("file.saveAs", "a.jpg"), ("file.save", "a.jpeg")] { + let mut s = Session::new(); + sample::open_sample(&mut s).unwrap(); + let path = dir.join(name).to_string_lossy().to_string(); + let before = s.doc().unwrap().path.clone(); + assert!(s.execute(cmd, &json!({"path": path})).is_err(), "{cmd} {name} should fail"); + assert!(!std::path::Path::new(&path).exists(), "{name} must not be written"); + assert_eq!(s.doc().unwrap().path, before); + } + let _ = std::fs::remove_dir_all(&dir); +} From fb3b857f53d3d8e371d0b06cc073d8751f7b6091 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Mon, 2 Nov 2026 23:07:29 -0500 Subject: [PATCH 2/2] file.save: an explicit jpg format is refused too Co-Authored-By: Claude Opus 5.5 --- crates/engine/src/cmd/file.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/engine/src/cmd/file.rs b/crates/engine/src/cmd/file.rs index 53009f51f..06ed36e3c 100644 --- a/crates/engine/src/cmd/file.rs +++ b/crates/engine/src/cmd/file.rs @@ -345,7 +345,7 @@ pub fn save_bytes(doc: &Presentation, format: &str) -> Result> { "rtf" => Ok(deckcraft_format::rtf::slides_to_rtf(doc).into_bytes()), "pdf" => deckcraft_pdf::export(doc, &Default::default()).map_err(|e| EngineError::Other(e.to_string())), "gif" => gif_bytes(doc, &Value::Null), - "png" | "jpeg" => Err(EngineError::Other("saving a presentation as a single image isn't supported; use file.export".into())), + "png" | "jpeg" | "jpg" => Err(EngineError::Other("saving a presentation as a single image isn't supported; use file.export".into())), _ => deckcraft_format::save(doc).map_err(|e| EngineError::Other(e.to_string())), } }