Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix parsing PE with zero raw_data_size of section #396

Merged
merged 7 commits into from
Oct 27, 2024
29 changes: 21 additions & 8 deletions src/pe/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -791,14 +791,7 @@ pub struct Header {
}

impl Header {
pub fn parse(bytes: &[u8]) -> error::Result<Self> {
let dos_header = DosHeader::parse(&bytes)?;
let dos_stub = bytes.pread(DOS_STUB_OFFSET as usize).map_err(|_| {
error::Error::Malformed(format!(
"cannot parse DOS stub (offset {:#x})",
DOS_STUB_OFFSET
))
})?;
fn parse_impl(bytes: &[u8], dos_header: DosHeader, dos_stub: DosStub) -> error::Result<Self> {
let mut offset = dos_header.pe_pointer as usize;
let signature = bytes.gread_with(&mut offset, scroll::LE).map_err(|_| {
error::Error::Malformed(format!("cannot parse PE signature (offset {:#x})", offset))
Expand All @@ -809,6 +802,7 @@ impl Header {
} else {
None
};

Ok(Header {
dos_header,
dos_stub,
Expand All @@ -817,6 +811,25 @@ impl Header {
optional_header,
})
}

/// Parses PE header from the given bytes; this will fail if the DosHeader or DosStub is malformed or missing in some way
pub fn parse(bytes: &[u8]) -> error::Result<Self> {
let dos_header = DosHeader::parse(&bytes)?;
let dos_stub = bytes.pread(DOS_STUB_OFFSET as usize).map_err(|_| {
error::Error::Malformed(format!(
"cannot parse DOS stub (offset {:#x})",
DOS_STUB_OFFSET
))
})?;

Header::parse_impl(bytes, dos_header, dos_stub)
}

/// Parses PE header from the given bytes, a default DosHeader and DosStub are generated, and any malformed header or stub is ignored
pub fn parse_without_dos(bytes: &[u8]) -> error::Result<Self> {
let dos_header = DosHeader::default();
Header::parse_impl(bytes, dos_header, DosStub::default())
}
}

impl ctx::TryIntoCtx<scroll::Endian> for Header {
Expand Down
2 changes: 2 additions & 0 deletions src/pe/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ fn section_read_size(section: &section_table::SectionTable, file_alignment: u32)

if virtual_size == 0 {
read_size
} else if read_size == 0 {
virtual_size
} else {
cmp::min(read_size, round_size(virtual_size))
}
Expand Down
Loading