@@ -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 ;
@@ -217,12 +217,10 @@ fn create_mingw_dll_import_lib(
217217 // able to control the *exact* spelling of each of the symbols that are being imported:
218218 // hence we don't want `dlltool` adding leading underscores automatically.
219219 let dlltool = find_binutils_dlltool ( sess) ;
220- let temp_prefix = {
221- let mut path = PathBuf :: from ( & output_path) ;
222- path. pop ( ) ;
223- path. push ( lib_name) ;
224- path
225- } ;
220+ // temp_prefix doesn't handle paths with spaces so
221+ // use a relative path and set the current working directory
222+ let cwd = output_path. parent ( ) . unwrap_or ( output_path) ;
223+ let temp_prefix = lib_name;
226224 // dlltool target architecture args from:
227225 // https://github.com/llvm/llvm-project-release-prs/blob/llvmorg-15.0.6/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp#L69
228226 let ( dlltool_target_arch, dlltool_target_bitness) = match & sess. target . arch {
@@ -246,7 +244,8 @@ fn create_mingw_dll_import_lib(
246244 . arg ( dlltool_target_bitness)
247245 . arg ( "--no-leading-underscore" )
248246 . arg ( "--temp-prefix" )
249- . arg ( temp_prefix) ;
247+ . arg ( temp_prefix)
248+ . current_dir ( cwd) ;
250249
251250 match dlltool_cmd. output ( ) {
252251 Err ( e) => {
@@ -320,6 +319,50 @@ pub trait ArchiveBuilder {
320319 fn build ( self : Box < Self > , output : & Path ) -> bool ;
321320}
322321
322+ fn target_archive_format_to_object_kind ( format : & str ) -> Option < ObjectArchiveKind > {
323+ match format {
324+ "gnu" => Some ( ObjectArchiveKind :: Gnu ) ,
325+ "bsd" => Some ( ObjectArchiveKind :: Bsd ) ,
326+ "darwin" => Some ( ObjectArchiveKind :: Bsd64 ) ,
327+ "coff" => Some ( ObjectArchiveKind :: Coff ) ,
328+ "aix_big" => Some ( ObjectArchiveKind :: AixBig ) ,
329+ _ => None ,
330+ }
331+ }
332+
333+ fn archive_kinds_compatible ( actual : ObjectArchiveKind , expected : ObjectArchiveKind ) -> bool {
334+ if actual == expected {
335+ return true ;
336+ }
337+ matches ! (
338+ ( actual, expected) ,
339+ // An archive without long filenames or symbol table is detected as Unknown;
340+ // this is compatible with any target format.
341+ ( ObjectArchiveKind :: Unknown , _)
342+ // 64-bit symbol table variants are compatible with their 32-bit counterparts
343+ | ( ObjectArchiveKind :: Gnu64 , ObjectArchiveKind :: Gnu )
344+ | ( ObjectArchiveKind :: Gnu , ObjectArchiveKind :: Gnu64 )
345+ | ( ObjectArchiveKind :: Bsd64 , ObjectArchiveKind :: Bsd )
346+ | ( ObjectArchiveKind :: Bsd , ObjectArchiveKind :: Bsd64 )
347+ // GNU and COFF archives share the same magic and member header format;
348+ // only the symbol table layout differs.
349+ | ( ObjectArchiveKind :: Gnu , ObjectArchiveKind :: Coff )
350+ | ( ObjectArchiveKind :: Coff , ObjectArchiveKind :: Gnu )
351+ | ( ObjectArchiveKind :: Gnu64 , ObjectArchiveKind :: Coff )
352+ )
353+ }
354+
355+ fn archive_kind_display_name ( kind : ObjectArchiveKind ) -> String {
356+ match kind {
357+ ObjectArchiveKind :: Gnu | ObjectArchiveKind :: Gnu64 => "GNU" . to_string ( ) ,
358+ ObjectArchiveKind :: Bsd => "BSD" . to_string ( ) ,
359+ ObjectArchiveKind :: Bsd64 => "Darwin" . to_string ( ) ,
360+ ObjectArchiveKind :: Coff => "COFF" . to_string ( ) ,
361+ ObjectArchiveKind :: AixBig => "AIX big" . to_string ( ) ,
362+ _ => format ! ( "{kind:?}" ) ,
363+ }
364+ }
365+
323366pub struct ArArchiveBuilderBuilder ;
324367
325368impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
@@ -420,6 +463,19 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> {
420463 . map_err ( |err| io:: Error :: new ( io:: ErrorKind :: InvalidData , err) ) ?;
421464 let archive_index = self . src_archives . len ( ) ;
422465
466+ if let Some ( expected_kind) =
467+ target_archive_format_to_object_kind ( & self . sess . target . archive_format )
468+ {
469+ let actual_kind = archive. kind ( ) ;
470+ if !archive_kinds_compatible ( actual_kind, expected_kind) {
471+ self . sess . dcx ( ) . emit_warn ( crate :: errors:: IncompatibleArchiveFormat {
472+ path : archive_path. clone ( ) ,
473+ actual : archive_kind_display_name ( actual_kind) ,
474+ expected : archive_kind_display_name ( expected_kind) ,
475+ } ) ;
476+ }
477+ }
478+
423479 for entry in archive. members ( ) {
424480 let entry = entry. map_err ( |err| io:: Error :: new ( io:: ErrorKind :: InvalidData , err) ) ?;
425481 let file_name = String :: from_utf8 ( entry. name ( ) . to_vec ( ) )
@@ -482,9 +538,24 @@ impl<'a> ArArchiveBuilder<'a> {
482538 match entry {
483539 ArchiveEntry :: FromArchive { archive_index, file_range } => {
484540 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 ] ;
541+ let archive_data = & src_archive. 1 ;
542+ let start = file_range. 0 as usize ;
543+ let end = start + file_range. 1 as usize ;
544+ let Some ( data) = archive_data. get ( start..end) else {
545+ return Err ( io_error_context (
546+ "invalid archive member" ,
547+ io:: Error :: new (
548+ io:: ErrorKind :: InvalidData ,
549+ format ! (
550+ "archive member at offset {start} with size {} \
551+ exceeds archive size {} in `{}`",
552+ file_range. 1 ,
553+ archive_data. len( ) ,
554+ src_archive. 0 . display( ) ,
555+ ) ,
556+ ) ,
557+ ) ) ;
558+ } ;
488559
489560 Box :: new ( data) as Box < dyn AsRef < [ u8 ] > >
490561 }
0 commit comments