@@ -12,10 +12,10 @@ use {
1212 FileHeader32 , FileHeader64 , ET_DYN , ET_EXEC , SHN_UNDEF , STB_GLOBAL , STB_WEAK , STV_DEFAULT ,
1313 STV_HIDDEN ,
1414 } ,
15- macho:: { MachHeader32 , MachHeader64 , MH_OBJECT , MH_TWOLEVEL } ,
15+ macho:: { LC_CODE_SIGNATURE , MH_OBJECT , MH_TWOLEVEL , MachHeader32 , MachHeader64 } ,
1616 read:: {
1717 elf:: { Dyn , FileHeader , SectionHeader , Sym } ,
18- macho:: { LoadCommandVariant , MachHeader , Nlist } ,
18+ macho:: { LoadCommandVariant , MachHeader , Nlist , Section , Segment } ,
1919 pe:: { ImageNtHeaders , PeFile , PeFile32 , PeFile64 } ,
2020 } ,
2121 Architecture , Endianness , FileKind , Object , SectionIndex , SymbolScope ,
@@ -1264,6 +1264,8 @@ fn validate_macho<Mach: MachHeader<Endian = Endianness>>(
12641264 let mut undefined_symbols = vec ! [ ] ;
12651265 let mut target_version = None ;
12661266 let mut sdk_version = None ;
1267+ let mut has_code_signature = false ;
1268+ let mut lowest_file_offset = u64:: MAX ;
12671269
12681270 while let Some ( load_command) = load_commands. next ( ) ? {
12691271 match load_command. variant ( ) ? {
@@ -1386,10 +1388,34 @@ fn validate_macho<Mach: MachHeader<Endian = Endianness>>(
13861388 }
13871389 }
13881390 }
1391+ LoadCommandVariant :: Segment32 ( segment, segment_data) => {
1392+ for section in segment. sections ( endian, segment_data) ? {
1393+ lowest_file_offset = lowest_file_offset. min ( section. offset ( endian) . into ( ) ) ;
1394+ }
1395+ }
1396+ LoadCommandVariant :: Segment64 ( segment, segment_data) => {
1397+ for section in segment. sections ( endian, segment_data) ? {
1398+ lowest_file_offset = lowest_file_offset. min ( section. offset ( endian) . into ( ) ) ;
1399+ }
1400+ }
1401+ LoadCommandVariant :: LinkeditData ( c) if c. cmd . get ( endian) == LC_CODE_SIGNATURE => {
1402+ has_code_signature = true ;
1403+ }
13891404 _ => { }
13901405 }
13911406 }
13921407
1408+ let end_of_load_commands =
1409+ std:: mem:: size_of_val ( header) as u64 + header. sizeofcmds ( endian) as u64 ;
1410+ if header. filetype ( endian) != MH_OBJECT
1411+ && end_of_load_commands + if has_code_signature { 0 } else { 16 } > lowest_file_offset
1412+ {
1413+ context. errors . push ( format ! (
1414+ "{}: Insufficient headerpad between end of load commands {end_of_load_commands:#x} and beginning of code {lowest_file_offset:#x}" ,
1415+ path. display( ) ,
1416+ ) ) ;
1417+ }
1418+
13931419 if let Some ( actual_target_version) = target_version {
13941420 if actual_target_version != advertised_target_version {
13951421 context. errors . push ( format ! (
0 commit comments