1+ use alloc:: vec:: Vec ;
12use core:: iter:: FusedIterator ;
23
4+ use scroll:: { ctx, IOread , IOwrite , Pread , Pwrite , SizeWith } ;
5+
36use crate :: error;
47use crate :: pe:: { data_directories, debug, optional_header, section_table, symbol} ;
58use crate :: strtab;
6- use alloc:: vec:: Vec ;
7- use scroll:: { ctx, IOread , IOwrite , Pread , Pwrite , SizeWith } ;
89
910/// In `winnt.h` and `pe.h`, it's `IMAGE_DOS_HEADER`. It's a DOS header present in all PE binaries.
1011///
@@ -394,6 +395,7 @@ impl DosHeader {
394395pub struct DosStub < ' a > {
395396 pub data : & ' a [ u8 ] ,
396397}
398+
397399impl < ' a > Default for DosStub < ' a > {
398400 /// This is the very basic DOS program bytecode representation embedded in MSVC linker.
399401 ///
@@ -442,6 +444,7 @@ impl<'a> Default for DosStub<'a> {
442444 }
443445 }
444446}
447+
445448impl < ' a > ctx:: TryIntoCtx < scroll:: Endian > for DosStub < ' a > {
446449 type Error = error:: Error ;
447450
@@ -870,9 +873,16 @@ impl<'a> Header<'a> {
870873 bytes : & ' a [ u8 ] ,
871874 dos_header : DosHeader ,
872875 dos_stub : DosStub < ' a > ,
876+ parse_rich_header : bool ,
873877 ) -> error:: Result < Self > {
874878 let mut offset = dos_header. pe_pointer as usize ;
875- let rich_header = RichHeader :: parse ( & bytes) ?;
879+
880+ let rich_header = if parse_rich_header {
881+ RichHeader :: parse ( & bytes) ?
882+ } else {
883+ None
884+ } ;
885+
876886 let signature = bytes. gread_with ( & mut offset, scroll:: LE ) . map_err ( |_| {
877887 error:: Error :: Malformed ( format ! ( "cannot parse PE signature (offset {:#x})" , offset) )
878888 } ) ?;
@@ -898,13 +908,13 @@ impl<'a> Header<'a> {
898908 let dos_header = DosHeader :: parse ( & bytes) ?;
899909 let dos_stub = DosStub :: parse ( bytes, dos_header. pe_pointer ) ?;
900910
901- Header :: parse_impl ( bytes, dos_header, dos_stub)
911+ Header :: parse_impl ( bytes, dos_header, dos_stub, true )
902912 }
903913
904914 /// Parses PE header from the given bytes, a default DosHeader and DosStub are generated, and any malformed header or stub is ignored
905915 pub fn parse_without_dos ( bytes : & ' a [ u8 ] ) -> error:: Result < Self > {
906916 let dos_header = DosHeader :: default ( ) ;
907- Header :: parse_impl ( bytes, dos_header, DosStub :: default ( ) )
917+ Header :: parse_impl ( bytes, dos_header, DosStub :: default ( ) , false )
908918 }
909919}
910920
@@ -1018,6 +1028,7 @@ impl Iterator for RichMetadataIterator<'_> {
10181028}
10191029
10201030impl FusedIterator for RichMetadataIterator < ' _ > { }
1031+
10211032impl ExactSizeIterator for RichMetadataIterator < ' _ > { }
10221033
10231034impl < ' a > RichHeader < ' a > {
@@ -1354,9 +1365,7 @@ pub fn machine_to_str(machine: u16) -> &'static str {
13541365mod tests {
13551366 use crate :: { error, pe:: header:: DosStub } ;
13561367
1357- use super :: {
1358- machine_to_str, Header , RichHeader , RichMetadata , COFF_MACHINE_X86 , DOS_MAGIC , PE_MAGIC ,
1359- } ;
1368+ use super :: { COFF_MACHINE_X86 , DOS_MAGIC , DosHeader , Header , machine_to_str, PE_MAGIC , RichHeader , RichMetadata } ;
13601369
13611370 const CRSS_HEADER : [ u8 ; 688 ] = [
13621371 0x4d , 0x5a , 0x90 , 0x00 , 0x03 , 0x00 , 0x00 , 0x00 , 0x04 , 0x00 , 0x00 , 0x00 , 0xff , 0xff , 0x00 ,
@@ -1534,6 +1543,9 @@ mod tests {
15341543 0x00 ,
15351544 ] ;
15361545
1546+ const WELL_FORMED_WITH_RICH_HEADER : & [ u8 ] =
1547+ include_bytes ! ( "../../tests/bins/pe/well_formed_import.exe.bin" ) ;
1548+
15371549 #[ test]
15381550 fn crss_header ( ) {
15391551 let header = Header :: parse ( & & CRSS_HEADER [ ..] ) . unwrap ( ) ;
@@ -1545,15 +1557,16 @@ mod tests {
15451557 }
15461558
15471559 #[ test]
1548- fn parse_without_dos ( ) {
1549- let header = Header :: parse_without_dos ( & BORLAND_PE32_VALID_NO_RICH_HEADER ) . unwrap ( ) ;
1550- assert_eq ! ( header. dos_stub, DosStub :: default ( ) ) ;
1551- assert_eq ! ( header. rich_header. is_none( ) , true ) ;
1552-
1553- // DOS stub is default but rich parser still works
1554- let header = Header :: parse_without_dos ( & CORRECT_RICH_HEADER ) . unwrap ( ) ;
1555- assert_eq ! ( header. dos_stub, DosStub :: default ( ) ) ;
1556- assert_eq ! ( header. rich_header. is_some( ) , true ) ;
1560+ fn parse_without_dos_rich ( ) {
1561+ // Get a PE pointer (e_lfanew)
1562+ let dos_header = DosHeader :: parse ( & WELL_FORMED_WITH_RICH_HEADER ) . unwrap ( ) ;
1563+ // Skip DOS header and DOS stub
1564+ let buf = & WELL_FORMED_WITH_RICH_HEADER [ dos_header. pe_pointer as usize ..] ;
1565+ let header = Header :: parse_without_dos ( buf) . unwrap ( ) ;
1566+
1567+ assert_eq ! ( header. coff_header. number_of_sections, 6 ) ;
1568+ assert_eq ! ( header. rich_header, None ) ;
1569+ assert_eq ! ( header. dos_header, DosHeader :: default ( ) ) ;
15571570 }
15581571
15591572 #[ test]
0 commit comments