@@ -12,10 +12,10 @@ use {
12
12
FileHeader32 , FileHeader64 , ET_DYN , ET_EXEC , SHN_UNDEF , STB_GLOBAL , STB_WEAK , STV_DEFAULT ,
13
13
STV_HIDDEN ,
14
14
} ,
15
- macho:: { MachHeader32 , MachHeader64 , MH_OBJECT , MH_TWOLEVEL } ,
15
+ macho:: { LC_CODE_SIGNATURE , MH_OBJECT , MH_TWOLEVEL , MachHeader32 , MachHeader64 } ,
16
16
read:: {
17
17
elf:: { Dyn , FileHeader , SectionHeader , Sym } ,
18
- macho:: { LoadCommandVariant , MachHeader , Nlist } ,
18
+ macho:: { LoadCommandVariant , MachHeader , Nlist , Section , Segment } ,
19
19
pe:: { ImageNtHeaders , PeFile , PeFile32 , PeFile64 } ,
20
20
} ,
21
21
Architecture , Endianness , FileKind , Object , SectionIndex , SymbolScope ,
@@ -1264,6 +1264,8 @@ fn validate_macho<Mach: MachHeader<Endian = Endianness>>(
1264
1264
let mut undefined_symbols = vec ! [ ] ;
1265
1265
let mut target_version = None ;
1266
1266
let mut sdk_version = None ;
1267
+ let mut has_code_signature = false ;
1268
+ let mut lowest_file_offset = u64:: MAX ;
1267
1269
1268
1270
while let Some ( load_command) = load_commands. next ( ) ? {
1269
1271
match load_command. variant ( ) ? {
@@ -1386,10 +1388,38 @@ fn validate_macho<Mach: MachHeader<Endian = Endianness>>(
1386
1388
}
1387
1389
}
1388
1390
}
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
+ }
1389
1408
_ => { }
1390
1409
}
1391
1410
}
1392
1411
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
+
1393
1423
if let Some ( actual_target_version) = target_version {
1394
1424
if actual_target_version != advertised_target_version {
1395
1425
context. errors . push ( format ! (
0 commit comments