From 731a5e86aaa5239b6a9f4bb3c8bc9d1822d6e78f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 13 Aug 2021 10:49:42 +0300 Subject: [PATCH] link: switch from `tar` to `ar` for `.rlib`s. --- Cargo.lock | 8 +++- crates/rustc_codegen_spirv/Cargo.toml | 2 +- crates/rustc_codegen_spirv/src/link.rs | 60 +++++++++++++++++--------- deny.toml | 13 ++---- 4 files changed, 52 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cf73919991..d5ae432cd1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,6 +77,12 @@ version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486" +[[package]] +name = "ar" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "450575f58f7bee32816abbff470cbc47797397c2a81e0eaced4b98436daf52e1" + [[package]] name = "arrayvec" version = "0.5.2" @@ -2234,6 +2240,7 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" name = "rustc_codegen_spirv" version = "0.4.0-alpha.12" dependencies = [ + "ar", "bimap", "hashbrown 0.11.2", "indexmap", @@ -2249,7 +2256,6 @@ dependencies = [ "smallvec", "spirv-tools", "syn", - "tar", "tempfile", "topological-sort", ] diff --git a/crates/rustc_codegen_spirv/Cargo.toml b/crates/rustc_codegen_spirv/Cargo.toml index acd792804b..6a5aefeff8 100644 --- a/crates/rustc_codegen_spirv/Cargo.toml +++ b/crates/rustc_codegen_spirv/Cargo.toml @@ -35,6 +35,7 @@ num-traits = { version = "0.2", features = ["libm"] } syn = { version = "1", features = ["visit", "visit-mut"] } # Normal dependencies. +ar = "0.8.0" bimap = "0.6" indexmap = "1.6.0" rspirv = { git = "https://github.com/gfx-rs/rspirv.git", rev = "c2a11ba7961fa7c675800f50c1903f0e96c633f8" } @@ -44,7 +45,6 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" smallvec = "1.6.1" spirv-tools = { version = "0.6.1", default-features = false } -tar = "0.4.30" topological-sort = "0.1" [dev-dependencies] diff --git a/crates/rustc_codegen_spirv/src/link.rs b/crates/rustc_codegen_spirv/src/link.rs index 4b64bc14d6..2e13664c0e 100644 --- a/crates/rustc_codegen_spirv/src/link.rs +++ b/crates/rustc_codegen_spirv/src/link.rs @@ -2,6 +2,7 @@ use crate::codegen_cx::{CodegenArgs, ModuleOutputType}; use crate::{ linker, CompileResult, ModuleResult, SpirvCodegenBackend, SpirvModuleBuffer, SpirvThinBuffer, }; +use ar::{Archive, GnuBuilder, Header}; use rspirv::binary::Assemble; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared}; use rustc_codegen_ssa::back::write::CodegenContext; @@ -19,12 +20,12 @@ use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, use rustc_session::utils::NativeLibKind; use rustc_session::Session; use std::env; -use std::ffi::{CString, OsStr}; +use std::ffi::CString; use std::fs::File; use std::io::{BufWriter, Read}; +use std::iter; use std::path::{Path, PathBuf}; use std::sync::Arc; -use tar::{Archive, Builder, Header}; pub fn link<'a>( sess: &'a Session, @@ -439,25 +440,42 @@ fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool { } fn create_archive(files: &[&Path], metadata: &[u8], out_filename: &Path) { - let file = File::create(out_filename).unwrap(); - let mut builder = Builder::new(file); - { - let mut header = Header::new_gnu(); - header.set_path(METADATA_FILENAME).unwrap(); - header.set_size(metadata.len() as u64); - header.set_cksum(); - builder.append(&header, metadata).unwrap(); - } + let files_with_names = files.iter().map(|file| { + ( + file, + file.file_name() + .unwrap() + .to_str() + .expect("archive file names should be valid ASCII/UTF-8"), + ) + }); + let out_file = File::create(out_filename).unwrap(); + let mut builder = GnuBuilder::new( + out_file, + iter::once(METADATA_FILENAME) + .chain(files_with_names.clone().map(|(_, name)| name)) + .map(|name| name.as_bytes().to_vec()) + .collect(), + ); + builder + .append( + &Header::new(METADATA_FILENAME.as_bytes().to_vec(), metadata.len() as u64), + metadata, + ) + .unwrap(); + let mut filenames = FxHashSet::default(); - filenames.insert(OsStr::new(METADATA_FILENAME)); - for file in files { + filenames.insert(METADATA_FILENAME); + for (file, name) in files_with_names { assert!( - filenames.insert(file.file_name().unwrap()), + filenames.insert(name), "Duplicate filename in archive: {:?}", file.file_name().unwrap() ); + // NOTE(eddyb) this could just be `builder.append_path(file)`, but we + // have to work around https://github.com/mdsteele/rust-ar/issues/19. builder - .append_path_with_name(file, file.file_name().unwrap()) + .append_file(name.as_bytes(), &mut File::open(file).unwrap()) .unwrap(); } builder.into_inner().unwrap(); @@ -465,9 +483,10 @@ fn create_archive(files: &[&Path], metadata: &[u8], out_filename: &Path) { pub fn read_metadata(rlib: &Path) -> Result { fn read_metadata_internal(rlib: &Path) -> Result, std::io::Error> { - for entry in Archive::new(File::open(rlib)?).entries()? { + let mut archive = Archive::new(File::open(rlib).unwrap()); + while let Some(entry) = archive.next_entry() { let mut entry = entry?; - if entry.path()? == Path::new(METADATA_FILENAME) { + if entry.header().identifier() == METADATA_FILENAME.as_bytes() { let mut bytes = Vec::new(); entry.read_to_end(&mut bytes)?; let buf: OwningRef, [u8]> = OwningRef::new(bytes); @@ -507,12 +526,13 @@ fn do_link( // `rlibs` are archive files we've created in `create_archive`, usually produced by crates that are being // referenced. We need to unpack them and add the modules inside. for rlib in rlibs { - for entry in Archive::new(File::open(rlib).unwrap()).entries().unwrap() { + let mut archive = Archive::new(File::open(rlib).unwrap()); + while let Some(entry) = archive.next_entry() { let mut entry = entry.unwrap(); - if entry.path().unwrap() != Path::new(METADATA_FILENAME) { + if entry.header().identifier() != METADATA_FILENAME.as_bytes() { // std::fs::read adds 1 to the size, so do the same here - see comment: // https://github.com/rust-lang/rust/blob/72868e017bdade60603a25889e253f556305f996/library/std/src/fs.rs#L200-L202 - let mut bytes = Vec::with_capacity(entry.size() as usize + 1); + let mut bytes = Vec::with_capacity(entry.header().size() as usize + 1); entry.read_to_end(&mut bytes).unwrap(); modules.push(load(&bytes)); } diff --git a/deny.toml b/deny.toml index 101e52db3f..3d55ec6052 100644 --- a/deny.toml +++ b/deny.toml @@ -6,12 +6,7 @@ vulnerability = "deny" unmaintained = "warn" yanked = "warn" notice = "warn" -ignore = [ - # The tar crate allows creating directories outside dst when unpacking. - # Safe to ignore: we both create/control all input tar files, and we do not unpack them. - # https://github.com/alexcrichton/tar-rs/issues/238 - "RUSTSEC-2021-0080", -] +ignore = [] # This section is considered when running `cargo deny check bans`. # More documentation about the 'bans' section can be found here: @@ -32,8 +27,8 @@ deny = [ skip = [ #{ name = "ansi_term", version = "=0.11.0" }, ] -# Similarly to `skip` allows you to skip certain crates during duplicate -# detection. Unlike skip, it also includes the entire tree of transitive +# Similarly to `skip` allows you to skip certain crates during duplicate +# detection. Unlike skip, it also includes the entire tree of transitive # dependencies starting at the specified crate, up to a certain depth, which is # by default infinite skip-tree = [ @@ -60,7 +55,7 @@ allow = [ "BSD-2-Clause", "BSD-3-Clause", "ISC", - + "Zlib", ] # Allow 1 or more licenses on a per-crate basis, so that particular licenses