Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions sdk/src/asset_handlers/bmff_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1537,6 +1537,21 @@ pub(crate) fn read_bmff_c2pa_boxes(reader: &mut dyn CAIRead) -> Result<C2PABmffB

impl CAIReader for BmffIO {
fn read_cai(&self, reader: &mut dyn CAIRead) -> Result<Vec<u8>> {
reader.seek(SeekFrom::Start(4))?;

let mut header = [0u8; 4];
reader.read_exact(&mut header)?;

if header[..4] != *b"ftyp" {
return Err(BmffError::InvalidFileSignature {
reason: format!(
"invalid BMFF structure: expected box type \"ftyp\" at offset 4, found {}",
String::from_utf8_lossy(&header[..4])
),
}
.into());
}

let c2pa_boxes = read_bmff_c2pa_boxes(reader)?;

// is this an update manifest?
Expand Down Expand Up @@ -2271,6 +2286,12 @@ impl RemoteRefEmbed for BmffIO {
}
}

#[derive(Debug, thiserror::Error)]
pub enum BmffError {
#[error("invalid file signature: {reason}")]
InvalidFileSignature { reason: String },
}

#[cfg(test)]
pub mod tests {
#![allow(clippy::expect_used)]
Expand Down
2 changes: 2 additions & 0 deletions sdk/src/asset_handlers/c2pa_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub struct C2paIO {}

impl CAIReader for C2paIO {
fn read_cai(&self, asset_reader: &mut dyn CAIRead) -> Result<Vec<u8>> {
asset_reader.rewind()?;

let mut cai_data = Vec::new();
// read the whole file
asset_reader.read_to_end(&mut cai_data)?;
Expand Down
23 changes: 22 additions & 1 deletion sdk/src/asset_handlers/gif_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -817,11 +817,26 @@ impl Header {
let mut signature = [0u8; 3];
stream.read_exact(&mut signature)?;
if signature != *b"GIF" {
return Err(Error::InvalidAsset("GIF signature invalid".to_owned()));
return Err(GifError::InvalidFileSignature {
reason: format!(
"invalid header signature: expected \"GIF\", found \"{}\"",
String::from_utf8_lossy(&signature)
),
}
.into());
}

let mut version = [0u8; 3];
stream.read_exact(&mut version)?;
if version != *b"87a" && version != *b"89a" {
return Err(GifError::InvalidFileSignature {
reason: format!(
"invalid header version: expected \"89a\" or \"87a\", found \"{}\"",
String::from_utf8_lossy(&version)
),
}
.into());
}

Ok(Header {
// version
Expand Down Expand Up @@ -1140,6 +1155,12 @@ fn gif_chunks(mut encoded_bytes: &[u8]) -> impl Iterator<Item = &[u8]> {
})
}

#[derive(Debug, thiserror::Error)]
pub enum GifError {
#[error("invalid file signature: {reason}")]
InvalidFileSignature { reason: String },
}

#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used)]
Expand Down
19 changes: 17 additions & 2 deletions sdk/src/asset_handlers/jpeg_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,17 @@ impl CAIReader for JpegIO {
asset_reader.rewind()?;
asset_reader.read_to_end(&mut buf).map_err(Error::IoError)?;

let dimg_opt = DynImage::from_bytes(buf.into())
.map_err(|_err| Error::InvalidAsset("Could not parse input JPEG".to_owned()))?;
let dimg_opt = DynImage::from_bytes(buf.into()).map_err(|err| match err {
img_parts::Error::WrongSignature => JpegError::InvalidFileSignature {
reason: format!(
"it may be because the stream does not start with \"{} {}\"",
markers::P,
markers::SOI
),
}
.into(),
_ => Error::InvalidAsset("Could not parse input JPEG".to_owned()),
})?;

if let Some(dimg) = dimg_opt {
match dimg {
Expand Down Expand Up @@ -1138,6 +1147,12 @@ impl ComposedManifestRef for JpegIO {
}
}

#[derive(Debug, thiserror::Error)]
pub enum JpegError {
#[error("invalid file signature: {reason}")]
InvalidFileSignature { reason: String },
}

#[cfg(test)]
pub mod tests {
#![allow(clippy::unwrap_used)]
Expand Down
3 changes: 3 additions & 0 deletions sdk/src/asset_handlers/mp3_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,9 @@ impl AssetPatch for Mp3IO {
}
}

#[derive(Debug, thiserror::Error)]
pub enum Mp3Error {}

#[cfg(test)]
pub mod tests {
#![allow(clippy::expect_used)]
Expand Down
24 changes: 22 additions & 2 deletions sdk/src/asset_handlers/pdf_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ use std::{fs::File, path::Path};
use crate::{
asset_handlers::pdf::{C2paPdf, Pdf},
asset_io::{AssetIO, CAIRead, CAIReader, CAIWriter, ComposedManifestRef, HashObjectPositions},
Error,
Error::{JumbfNotFound, NotImplemented, PdfReadError},
Error::{self, JumbfNotFound, NotImplemented, PdfReadError},
};

static SUPPORTED_TYPES: [&str; 2] = ["pdf", "application/pdf"];
Expand All @@ -28,6 +27,21 @@ pub struct PdfIO {}
impl CAIReader for PdfIO {
fn read_cai(&self, asset_reader: &mut dyn CAIRead) -> crate::Result<Vec<u8>> {
asset_reader.rewind()?;

let mut header = [0u8; 5];
asset_reader.read_exact(&mut header)?;
if header != *b"%PDF-" {
return Err(PdfError::InvalidFileSignature {
reason: format!(
"invalid header signature: expected \"%PDF-\", found {}",
String::from_utf8_lossy(&header)
),
}
.into());
}

asset_reader.rewind()?;

let pdf = Pdf::from_reader(asset_reader).map_err(|e| Error::InvalidAsset(e.to_string()))?;
self.read_manifest_bytes(pdf)
}
Expand Down Expand Up @@ -121,6 +135,12 @@ impl ComposedManifestRef for PdfIO {
}
}

#[derive(Debug, thiserror::Error)]
pub enum PdfError {
#[error("invalid file signature: {reason}")]
InvalidFileSignature { reason: String },
}

#[cfg(test)]
pub mod tests {
#![allow(clippy::panic)]
Expand Down
17 changes: 13 additions & 4 deletions sdk/src/asset_handlers/png_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,12 @@ fn get_png_chunk_positions<R: Read + Seek + ?Sized>(f: &mut R) -> Result<Vec<Png
let mut hdr = [0; 8];

// check PNG signature
f.read_exact(&mut hdr)
.map_err(|_err| Error::InvalidAsset("PNG invalid".to_string()))?;
f.read_exact(&mut hdr)?;
if hdr != PNG_ID {
return Err(Error::InvalidAsset("PNG invalid".to_string()));
return Err(PngError::InvalidFileSignature {
reason: format!("invalid header: expected {:02X?}, got {:02X?}", PNG_ID, hdr),
}
.into());
}

loop {
Expand Down Expand Up @@ -196,6 +198,7 @@ fn read_string(asset_reader: &mut dyn CAIRead, max_read: u32) -> Result<String>

Ok(String::from_utf8_lossy(&s).to_string())
}

pub struct PngIO {}

impl CAIReader for PngIO {
Expand Down Expand Up @@ -782,6 +785,12 @@ impl ComposedManifestRef for PngIO {
}
}

#[derive(Debug, thiserror::Error)]
pub enum PngError {
#[error("invalid file signature: {reason}")]
InvalidFileSignature { reason: String },
}

#[cfg(test)]
#[allow(clippy::panic)]
#[allow(clippy::unwrap_used)]
Expand Down Expand Up @@ -935,7 +944,7 @@ pub mod tests {
let mut output_stream = Cursor::new(output);
assert!(matches!(
png_io.write_cai(&mut stream, &mut output_stream, &[]),
Err(Error::InvalidAsset(_),)
Err(Error::PngError(PngError::InvalidFileSignature { .. }))
));
}

Expand Down
15 changes: 14 additions & 1 deletion sdk/src/asset_handlers/riff_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,14 @@ impl CAIReader for RiffIO {
let top_level_chunks = Chunk::read(&mut chunk_reader, 0)?;

if top_level_chunks.id() != RIFF_ID {
return Err(Error::InvalidAsset("Invalid RIFF format".to_string()));
return Err(RiffError::InvalidFileSignature {
reason: format!(
"invalid header: expected \"{}\", got \"{}\"",
String::from_utf8_lossy(&RIFF_ID.value),
String::from_utf8_lossy(&top_level_chunks.id().value),
),
}
.into());
}

for result in top_level_chunks.iter(&mut chunk_reader) {
Expand Down Expand Up @@ -619,6 +626,12 @@ impl RemoteRefEmbed for RiffIO {
}
}

#[derive(Debug, thiserror::Error)]
pub enum RiffError {
#[error("invalid file signature: {reason}")]
InvalidFileSignature { reason: String },
}

#[cfg(test)]
pub mod tests {
#![allow(clippy::expect_used)]
Expand Down
24 changes: 21 additions & 3 deletions sdk/src/asset_handlers/svg_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,21 @@ fn detect_manifest_location(
let name = String::from_utf8_lossy(e.name().into_inner()).into_owned();
xml_path.push(name);

if xml_path.len() == 2 && xml_path[0] == SVG && xml_path[1] == METADATA {
detected_level = DetectedTagsDepth::Metadata;
insertion_point = xml_reader.buffer_position();
if xml_path.len() == 2 {
if xml_path[0] == SVG {
if xml_path[1] == METADATA {
detected_level = DetectedTagsDepth::Metadata;
insertion_point = xml_reader.buffer_position();
}
} else {
return Err(SvgError::InvalidFileSignature {
reason: format!(
"invalid tag structure: root element must be \"{}\", found \"{}\"",
SVG, xml_path[0]
),
}
.into());
}
}

if xml_path.len() == 3
Expand Down Expand Up @@ -736,6 +748,12 @@ impl RemoteRefEmbed for SvgIO {
}
}

#[derive(Debug, thiserror::Error)]
pub enum SvgError {
#[error("invalid file signature: {reason}")]
InvalidFileSignature { reason: String },
}

#[cfg(test)]
pub mod tests {
#![allow(clippy::expect_used)]
Expand Down
Loading
Loading