Skip to content

Commit 8fda7a8

Browse files
kkent030315dapa
andauthored
TE: fix subtract with overflow in TE header parser (#452)
Co-authored-by: dapa <dapa@github>
1 parent b2deba6 commit 8fda7a8

File tree

1 file changed

+37
-2
lines changed

1 file changed

+37
-2
lines changed

src/pe/header.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,8 +1221,16 @@ pub const TE_MAGIC: u16 = 0x5a56;
12211221
impl TeHeader {
12221222
/// Parse the TE header from the given bytes.
12231223
pub fn parse(bytes: &[u8], offset: &mut usize) -> error::Result<Self> {
1224+
const HEADER_SIZE: usize = core::mem::size_of::<TeHeader>();
12241225
let mut header: TeHeader = bytes.gread_with(offset, scroll::LE)?;
1225-
let adj_offset = header.stripped_size as u32 - core::mem::size_of::<TeHeader>() as u32;
1226+
let stripped_size = header.stripped_size as u32;
1227+
let adj_offset = stripped_size
1228+
.checked_sub(HEADER_SIZE as u32)
1229+
.ok_or_else(|| {
1230+
error::Error::Malformed(format!(
1231+
"Stripped size ({stripped_size:#x}) is smaller than TE header size ({HEADER_SIZE:#x})",
1232+
))
1233+
})?;
12261234
header.fixup_header(adj_offset);
12271235
Ok(header)
12281236
}
@@ -1364,7 +1372,10 @@ pub fn machine_to_str(machine: u16) -> &'static str {
13641372

13651373
#[cfg(test)]
13661374
mod tests {
1367-
use crate::{error, pe::header::DosStub};
1375+
use crate::{
1376+
error,
1377+
pe::header::{DosStub, TeHeader},
1378+
};
13681379

13691380
use super::{
13701381
machine_to_str, DosHeader, Header, RichHeader, RichMetadata, COFF_MACHINE_X86, DOS_MAGIC,
@@ -1585,6 +1596,16 @@ mod tests {
15851596
0x00,
15861597
];
15871598

1599+
/// Malformed very small TE with valid TE magic.
1600+
///
1601+
/// https://github.com/m4b/goblin/issues/450
1602+
const MALFORMED_SMALL_TE: [u8; 58] = [
1603+
0x56, 0x5A, 0x52, 0x5A, 0x50, 0x00, 0x17, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00,
1604+
0x10, 0x86, 0x02, 0x0C, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x1B, 0x01, 0x01, 0x00, 0x00,
1605+
0xFF, 0xB5, 0x00, 0x00, 0x00, 0x04, 0x34, 0x00, 0x00, 0xFF, 0xB5, 0x00, 0x00, 0x00, 0x04,
1606+
0x34, 0x15, 0x40, 0x13, 0x41, 0x0E, 0x10, 0x15, 0x40, 0x13, 0x41, 0x0E, 0x10,
1607+
];
1608+
15881609
const WELL_FORMED_WITH_RICH_HEADER: &[u8] =
15891610
include_bytes!("../../tests/bins/pe/well_formed_import.exe.bin");
15901611

@@ -1713,6 +1734,20 @@ mod tests {
17131734
}
17141735

17151736
#[test]
1737+
fn parse_malformed_small_te() {
1738+
let mut offset = 0;
1739+
let header = TeHeader::parse(&MALFORMED_SMALL_TE, &mut offset);
1740+
assert_eq!(header.is_err(), true);
1741+
if let Err(error::Error::Malformed(msg)) = header {
1742+
assert_eq!(
1743+
msg,
1744+
"Stripped size (0x17) is smaller than TE header size (0x28)"
1745+
);
1746+
} else {
1747+
panic!("Expected a Malformed error but got {:?}", header);
1748+
}
1749+
}
1750+
17161751
fn parse_with_omitted_dos_stub() {
17171752
let header = Header::parse(&HEADER_WITH_OMITTED_DOS_STUB).unwrap();
17181753

0 commit comments

Comments
 (0)