@@ -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,38 @@ 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+ if let Some ( ( offset, _) ) = section. file_range ( endian) {
1394+ lowest_file_offset = lowest_file_offset. min ( offset) ;
1395+ }
1396+ }
1397+ }
1398+ LoadCommandVariant :: Segment64 ( segment, segment_data) => {
1399+ for section in segment. sections ( endian, segment_data) ? {
1400+ if let Some ( ( offset, _) ) = section. file_range ( endian) {
1401+ lowest_file_offset = lowest_file_offset. min ( offset) ;
1402+ }
1403+ }
1404+ }
1405+ LoadCommandVariant :: LinkeditData ( c) if c. cmd . get ( endian) == LC_CODE_SIGNATURE => {
1406+ has_code_signature = true ;
1407+ }
13891408 _ => { }
13901409 }
13911410 }
13921411
1412+ let end_of_load_commands =
1413+ std:: mem:: size_of_val ( header) as u64 + header. sizeofcmds ( endian) as u64 ;
1414+ if header. filetype ( endian) != MH_OBJECT
1415+ && end_of_load_commands + if has_code_signature { 0 } else { 16 } > lowest_file_offset
1416+ {
1417+ context. errors . push ( format ! (
1418+ "{}: Insufficient headerpad between end of load commands {end_of_load_commands:#x} and beginning of code {lowest_file_offset:#x}" ,
1419+ path. display( ) ,
1420+ ) ) ;
1421+ }
1422+
13931423 if let Some ( actual_target_version) = target_version {
13941424 if actual_target_version != advertised_target_version {
13951425 context. errors . push ( format ! (
0 commit comments