Skip to content

Commit

Permalink
sparse: Allow parsing files with unknown fields
Browse files Browse the repository at this point in the history
The official AOSP implementation does, so we should too. This allows
unpacking Samsung's sparse images, which have an extra 4 bytes in both
the file header and chunk headers.

Signed-off-by: Andrew Gunnerson <[email protected]>
  • Loading branch information
chenxiaolong committed Nov 12, 2024
1 parent 37b15a2 commit c0e6526
Showing 1 changed file with 22 additions and 5 deletions.
27 changes: 22 additions & 5 deletions avbroot/src/format/sparse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ use thiserror::Error;
use zerocopy::{byteorder::little_endian, FromZeros, IntoBytes};
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};

use crate::stream::ReadDiscardExt;

/// Magic value for [`RawHeader::magic`].
const HEADER_MAGIC: u32 = 0xed26ff3a;

Expand Down Expand Up @@ -108,15 +110,17 @@ impl RawHeader {
)));
}

if self.file_hdr_sz.get() != mem::size_of::<RawHeader>() as u16 {
if self.file_hdr_sz.get() < mem::size_of::<RawHeader>() as u16 {
return Err(Error::Header(format!(
"Invalid file header size: {}",
"Invalid file header size: {} < {}",
self.file_hdr_sz.get(),
mem::size_of::<RawHeader>(),
)));
} else if self.chunk_hdr_sz.get() != mem::size_of::<RawChunk>() as u16 {
} else if self.chunk_hdr_sz.get() < mem::size_of::<RawChunk>() as u16 {
return Err(Error::Header(format!(
"Invalid chunk header size: {}",
"Invalid chunk header size: {} < {}",
self.chunk_hdr_sz.get(),
mem::size_of::<RawChunk>(),
)));
}

Expand All @@ -129,6 +133,14 @@ impl RawHeader {

Ok(())
}

fn excess_raw_header_bytes(&self) -> u16 {
self.file_hdr_sz.get() - mem::size_of::<RawHeader>() as u16
}

fn excess_raw_chunk_bytes(&self) -> u16 {
self.chunk_hdr_sz.get() - mem::size_of::<RawChunk>() as u16
}
}

/// Raw on-disk layout for the chunk header.
Expand Down Expand Up @@ -180,7 +192,7 @@ impl RawChunk {
};

data_size
.checked_add(mem::size_of::<Self>() as u32)
.checked_add(header.chunk_hdr_sz.into())
.ok_or_else(|| Error::Chunk(index, format!("Data size too large: {data_size}")))
}

Expand Down Expand Up @@ -662,6 +674,8 @@ impl<R: Read> SparseReader<R> {

header.validate()?;

inner.read_discard(header.excess_raw_header_bytes().into())?;

Ok(Self {
inner,
seek: None,
Expand Down Expand Up @@ -724,6 +738,9 @@ impl<R: Read> SparseReader<R> {

raw_chunk.validate(self.chunk, &self.header, self.block)?;

self.inner
.read_discard(self.header.excess_raw_chunk_bytes().into())?;

let data: ChunkData;

match raw_chunk.chunk_type.get() {
Expand Down

0 comments on commit c0e6526

Please sign in to comment.