@@ -9,7 +9,7 @@ use ar_archive_writer::{
99 ArchiveKind , COFFShortExport , MachineTypes , NewArchiveMember , write_archive_to_stream,
1010} ;
1111pub use ar_archive_writer:: { DEFAULT_OBJECT_READER , ObjectReader } ;
12- use object:: read:: archive:: ArchiveFile ;
12+ use object:: read:: archive:: { ArchiveFile , ArchiveKind as ObjectArchiveKind } ;
1313use object:: read:: macho:: FatArch ;
1414use rustc_data_structures:: fx:: FxIndexSet ;
1515use rustc_data_structures:: memmap:: Mmap ;
@@ -320,6 +320,43 @@ pub trait ArchiveBuilder {
320320 fn build ( self : Box < Self > , output : & Path ) -> bool ;
321321}
322322
323+ fn target_archive_format_to_object_kind ( format : & str ) -> Option < ObjectArchiveKind > {
324+ match format {
325+ "gnu" => Some ( ObjectArchiveKind :: Gnu ) ,
326+ "bsd" => Some ( ObjectArchiveKind :: Bsd ) ,
327+ "darwin" => Some ( ObjectArchiveKind :: Bsd64 ) ,
328+ "coff" => Some ( ObjectArchiveKind :: Coff ) ,
329+ "aix_big" => Some ( ObjectArchiveKind :: AixBig ) ,
330+ _ => None ,
331+ }
332+ }
333+
334+ fn archive_kinds_compatible ( actual : ObjectArchiveKind , expected : ObjectArchiveKind ) -> bool {
335+ matches ! (
336+ ( actual, expected) ,
337+ ( ObjectArchiveKind :: Gnu , ObjectArchiveKind :: Gnu )
338+ | ( ObjectArchiveKind :: Bsd , ObjectArchiveKind :: Bsd )
339+ | ( ObjectArchiveKind :: Bsd64 , ObjectArchiveKind :: Bsd64 )
340+ | ( ObjectArchiveKind :: Coff , ObjectArchiveKind :: Coff )
341+ | ( ObjectArchiveKind :: AixBig , ObjectArchiveKind :: AixBig )
342+ // 64-bit symbol table variants are compatible with their 32-bit counterparts
343+ | ( ObjectArchiveKind :: Gnu64 , ObjectArchiveKind :: Gnu )
344+ | ( ObjectArchiveKind :: Bsd64 , ObjectArchiveKind :: Bsd )
345+ | ( ObjectArchiveKind :: Bsd , ObjectArchiveKind :: Bsd64 )
346+ )
347+ }
348+
349+ fn archive_format_display_name ( format : & str ) -> String {
350+ match format {
351+ "gnu" | "Gnu" | "Gnu64" => "GNU" . to_string ( ) ,
352+ "bsd" | "Bsd" => "BSD" . to_string ( ) ,
353+ "darwin" | "Bsd64" => "Darwin" . to_string ( ) ,
354+ "coff" | "Coff" => "COFF" . to_string ( ) ,
355+ "aix_big" | "AixBig" => "AIX big" . to_string ( ) ,
356+ other => other. to_string ( ) ,
357+ }
358+ }
359+
323360pub struct ArArchiveBuilderBuilder ;
324361
325362impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
@@ -420,6 +457,21 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> {
420457 . map_err ( |err| io:: Error :: new ( io:: ErrorKind :: InvalidData , err) ) ?;
421458 let archive_index = self . src_archives . len ( ) ;
422459
460+ if let Some ( expected_kind) =
461+ target_archive_format_to_object_kind ( & self . sess . target . archive_format )
462+ {
463+ let actual_kind = archive. kind ( ) ;
464+ if actual_kind != ObjectArchiveKind :: Unknown
465+ && !archive_kinds_compatible ( actual_kind, expected_kind)
466+ {
467+ self . sess . dcx ( ) . emit_warn ( crate :: errors:: IncompatibleArchiveFormat {
468+ path : archive_path. clone ( ) ,
469+ actual : archive_format_display_name ( & format ! ( "{actual_kind:?}" ) ) ,
470+ expected : archive_format_display_name ( & self . sess . target . archive_format ) ,
471+ } ) ;
472+ }
473+ }
474+
423475 for entry in archive. members ( ) {
424476 let entry = entry. map_err ( |err| io:: Error :: new ( io:: ErrorKind :: InvalidData , err) ) ?;
425477 let file_name = String :: from_utf8 ( entry. name ( ) . to_vec ( ) )
@@ -482,9 +534,25 @@ impl<'a> ArArchiveBuilder<'a> {
482534 match entry {
483535 ArchiveEntry :: FromArchive { archive_index, file_range } => {
484536 let src_archive = & self . src_archives [ archive_index] ;
485-
486- let data = & src_archive. 1
487- [ file_range. 0 as usize ..file_range. 0 as usize + file_range. 1 as usize ] ;
537+ let archive_data = & src_archive. 1 ;
538+ let start = file_range. 0 as usize ;
539+ let end = start + file_range. 1 as usize ;
540+ if end > archive_data. len ( ) {
541+ return Err ( io_error_context (
542+ "invalid archive member" ,
543+ io:: Error :: new (
544+ io:: ErrorKind :: InvalidData ,
545+ format ! (
546+ "archive member at offset {start} with size {} \
547+ exceeds archive size {} in `{}`",
548+ file_range. 1 ,
549+ archive_data. len( ) ,
550+ src_archive. 0 . display( ) ,
551+ ) ,
552+ ) ,
553+ ) ) ;
554+ }
555+ let data = & archive_data[ start..end] ;
488556
489557 Box :: new ( data) as Box < dyn AsRef < [ u8 ] > >
490558 }
0 commit comments