Skip to content

Commit f06b768

Browse files
kkent030315dapa
andauthored
COFF: fix subtract with overflow in COFF header parser (#453)
Co-authored-by: dapa <dapa@github>
1 parent 9c9ded7 commit f06b768

File tree

1 file changed

+32
-2
lines changed

1 file changed

+32
-2
lines changed

src/pe/header.rs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,12 @@ impl CoffHeader {
841841
+ symbol::SymbolTable::size(self.number_of_symbol_table as usize);
842842

843843
let length_field_size = core::mem::size_of::<u32>();
844-
let length = bytes.pread_with::<u32>(offset, scroll::LE)? as usize - length_field_size;
844+
let length = bytes
845+
.pread_with::<u32>(offset, scroll::LE)?
846+
.checked_sub(length_field_size as u32)
847+
.ok_or(error::Error::Malformed(format!(
848+
"COFF length field size ({length_field_size:#x}) is larger than the parsed length value"
849+
)))? as usize;
845850

846851
// The offset needs to be advanced in order to read the strings.
847852
offset += length_field_size;
@@ -1374,7 +1379,10 @@ pub fn machine_to_str(machine: u16) -> &'static str {
13741379
mod tests {
13751380
use crate::{
13761381
error,
1377-
pe::header::{DosStub, TeHeader},
1382+
pe::{
1383+
header::{DosStub, TeHeader},
1384+
Coff,
1385+
},
13781386
};
13791387

13801388
use super::{
@@ -1596,6 +1604,14 @@ mod tests {
15961604
0x00,
15971605
];
15981606

1607+
/// An invalid small COFF object file
1608+
///
1609+
/// https://github.com/m4b/goblin/issues/450
1610+
const INVALID_COFF_OBJECT: [u8; 20] = [
1611+
0x4C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1612+
0x00, 0x0F, 0x00, 0xFF, 0x80,
1613+
];
1614+
15991615
/// Malformed very small TE with valid TE magic.
16001616
///
16011617
/// https://github.com/m4b/goblin/issues/450
@@ -1748,6 +1764,20 @@ mod tests {
17481764
}
17491765
}
17501766

1767+
#[test]
1768+
fn parse_invalid_small_coff() {
1769+
let header = Coff::parse(&INVALID_COFF_OBJECT);
1770+
assert_eq!(header.is_err(), true);
1771+
if let Err(error::Error::Malformed(msg)) = header {
1772+
assert_eq!(
1773+
msg,
1774+
"COFF length field size (0x4) is larger than the parsed length value"
1775+
);
1776+
} else {
1777+
panic!("Expected a Malformed error but got {:?}", header);
1778+
}
1779+
}
1780+
17511781
fn parse_with_omitted_dos_stub() {
17521782
let header = Header::parse(&HEADER_WITH_OMITTED_DOS_STUB).unwrap();
17531783

0 commit comments

Comments
 (0)