From caf5f1f6196361abab71d55a33802c387523155e Mon Sep 17 00:00:00 2001 From: iequidoo Date: Sun, 12 Oct 2025 04:40:10 -0300 Subject: [PATCH] fix: Remove Exif with non-fatal errors from images NB: This still doesn't help with detecting Exif in PNGs unfortunately. --- src/blob.rs | 6 +++++- src/blob/blob_tests.rs | 24 +++++++++++++++++++++++- test-data/image/1000x1000-bad-exif.jpg | Bin 0 -> 35027 bytes 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 test-data/image/1000x1000-bad-exif.jpg diff --git a/src/blob.rs b/src/blob.rs index 1c1630d2d..ca47c65a4 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -537,7 +537,11 @@ fn file_hash(src: &Path) -> Result { fn image_metadata(file: &std::fs::File) -> Result<(u64, Option)> { let len = file.metadata()?.len(); let mut bufreader = std::io::BufReader::new(file); - let exif = exif::Reader::new().read_from_container(&mut bufreader).ok(); + let exif = exif::Reader::new() + .continue_on_error(true) + .read_from_container(&mut bufreader) + .or_else(|e| e.distill_partial_result(|_errors| {})) + .ok(); Ok((len, exif)) } diff --git a/src/blob/blob_tests.rs b/src/blob/blob_tests.rs index 68472f867..a63c08602 100644 --- a/src/blob/blob_tests.rs +++ b/src/blob/blob_tests.rs @@ -334,6 +334,28 @@ async fn test_recode_image_2() { assert_correct_rotation(&img_rotated); } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_recode_image_bad_exif() { + // `exiftool` reports for this file "Bad offset for IFD0 XResolution", still Exif must be + // detected and removed. + let bytes = include_bytes!("../../test-data/image/1000x1000-bad-exif.jpg"); + SendImageCheckMediaquality { + viewtype: Viewtype::Image, + media_quality_config: "0", + bytes, + extension: "jpg", + has_exif: true, + original_width: 1000, + original_height: 1000, + compressed_width: 1000, + compressed_height: 1000, + ..Default::default() + } + .test() + .await + .unwrap(); +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_recode_image_balanced_png() { let bytes = include_bytes!("../../test-data/image/screenshot.png"); @@ -418,7 +440,7 @@ async fn test_recode_image_balanced_png() { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_sticker_with_exif() { - let bytes = include_bytes!("../../test-data/image/logo.png"); + let bytes = include_bytes!("../../test-data/image/logo-exif.png"); SendImageCheckMediaquality { viewtype: Viewtype::Sticker, bytes, diff --git a/test-data/image/1000x1000-bad-exif.jpg b/test-data/image/1000x1000-bad-exif.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e39d6bf40d661742f18464416ec34eadb6806a27 GIT binary patch literal 35027 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 literal 0 HcmV?d00001