From f991d0f0d07488a48e2e6b5ce812c24ae1f8421e Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Wed, 4 Nov 2026 01:12:07 +0000 Subject: [PATCH] address review: match full PNG and GIF signatures --- crates/lottie/src/export.rs | 6 +++--- crates/lottie/src/tests.rs | 13 ++++++++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/crates/lottie/src/export.rs b/crates/lottie/src/export.rs index 0bd7c3161..88dcf4ed4 100644 --- a/crates/lottie/src/export.rs +++ b/crates/lottie/src/export.rs @@ -146,12 +146,12 @@ fn hex(c: [f32; 3]) -> String { } /// The image type `bytes` hold, by their signature; `None` for anything else. -fn image_mime(bytes: &[u8]) -> Option<&'static str> { - if bytes.starts_with(b"\x89PNG") { +pub(crate) fn image_mime(bytes: &[u8]) -> Option<&'static str> { + if bytes.starts_with(b"\x89PNG\r\n\x1a\n") { Some("image/png") } else if bytes.starts_with(&[0xff, 0xd8, 0xff]) { Some("image/jpeg") - } else if bytes.starts_with(b"GIF8") { + } else if bytes.starts_with(b"GIF87a") || bytes.starts_with(b"GIF89a") { Some("image/gif") } else if bytes.starts_with(b"RIFF") && bytes.get(8..12) == Some(b"WEBP") { Some("image/webp") diff --git a/crates/lottie/src/tests.rs b/crates/lottie/src/tests.rs index 40b7df048..664001769 100644 --- a/crates/lottie/src/tests.rs +++ b/crates/lottie/src/tests.rs @@ -672,7 +672,7 @@ fn effects_expressions_and_warnings() { #[test] fn images_embed_as_base64_and_come_back() { let (mut p, cid) = setup(); - let png: Vec = vec![0x89, b'P', b'N', b'G', 1, 2, 3, 4, 5]; + let png: Vec = vec![0x89, b'P', b'N', b'G', 0x0d, 0x0a, 0x1a, 0x0a, 1, 2, 3, 4, 5]; let fid = p.add_item( "pic.png", Label::Lavender, @@ -722,6 +722,17 @@ fn images_embed_as_base64_and_come_back() { assert!(f.path.starts_with("/tmp/image_") && f.path.ends_with(".png"), "{}", f.path); } +#[test] +fn image_signatures_are_matched_in_full() { + use crate::export::image_mime; + assert_eq!(image_mime(b"\x89PNG\r\n\x1a\n\0"), Some("image/png")); + assert_eq!(image_mime(b"GIF89a\0"), Some("image/gif")); + assert_eq!(image_mime(b"GIF87a\0"), Some("image/gif")); + // Near matches (a prefix of the signature, or text that starts with it) are not images. + assert_eq!(image_mime(b"\x89PNG\x01\x02\x03\x04"), None); + assert_eq!(image_mime(b"GIF8 is a text file"), None); +} + #[test] fn dotlottie_archive_roundtrip() { let (mut p, cid) = setup();