From b9eedea4b0368fd1f00f204db75109ff444fab5b Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 26 May 2022 11:27:44 -0400 Subject: [PATCH] Panic if `dist` generates a symbolic link in a generated tarball This avoids regressions in rustup-toolchain-install-master --- Cargo.lock | 1 + src/bootstrap/Cargo.toml | 1 + src/bootstrap/dist.rs | 7 ++++++- src/bootstrap/tarball.rs | 20 +++++++++++++++++++- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f5aacba20cd..c5e4464ef55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -225,6 +225,7 @@ dependencies = [ "serde_json", "tar", "toml", + "walkdir", "winapi", "xz2", ] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index dea8d998bde..8c23491a6c4 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -48,6 +48,7 @@ ignore = "0.4.10" opener = "0.5" once_cell = "1.7.2" xz2 = "0.1" +walkdir = "2" [target.'cfg(windows)'.dependencies.winapi] version = "0.3" diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index d37a59426f8..a528912fb81 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -848,7 +848,12 @@ impl Step for PlainSourceTarball { /// Creates the plain source tarball fn run(self, builder: &Builder<'_>) -> GeneratedTarball { - let tarball = Tarball::new(builder, "rustc", "src"); + // NOTE: This is a strange component in a lot of ways. It uses `src` as the target, which + // means neither rustup nor rustup-toolchain-install-master know how to download it. + // It also contains symbolic links, unlike other any other dist tarball. + // It's used for distros building rustc from source in a pre-vendored environment. + let mut tarball = Tarball::new(builder, "rustc", "src"); + tarball.permit_symlinks(true); let plain_dst_src = tarball.image_dir(); // This is the set of root paths which will become part of the source package diff --git a/src/bootstrap/tarball.rs b/src/bootstrap/tarball.rs index 689b4819cdd..7b0c029c191 100644 --- a/src/bootstrap/tarball.rs +++ b/src/bootstrap/tarball.rs @@ -102,6 +102,7 @@ pub(crate) struct Tarball<'a> { include_target_in_component_name: bool, is_preview: bool, + permit_symlinks: bool, } impl<'a> Tarball<'a> { @@ -141,6 +142,7 @@ impl<'a> Tarball<'a> { include_target_in_component_name: false, is_preview: false, + permit_symlinks: false, } } @@ -160,6 +162,10 @@ impl<'a> Tarball<'a> { self.is_preview = is; } + pub(crate) fn permit_symlinks(&mut self, flag: bool) { + self.permit_symlinks = flag; + } + pub(crate) fn image_dir(&self) -> &Path { t!(std::fs::create_dir_all(&self.image_dir)); &self.image_dir @@ -316,6 +322,18 @@ impl<'a> Tarball<'a> { } self.builder.run(&mut cmd); + // Ensure there are no symbolic links in the tarball. In particular, + // rustup-toolchain-install-master and most versions of Windows can't handle symbolic links. + let decompressed_output = self.temp_dir.join(&package_name); + if !self.builder.config.dry_run && !self.permit_symlinks { + for entry in walkdir::WalkDir::new(&decompressed_output) { + let entry = t!(entry); + if entry.path_is_symlink() { + panic!("generated a symlink in a tarball: {}", entry.path().display()); + } + } + } + // Use either the first compression format defined, or "gz" as the default. let ext = self .builder @@ -328,7 +346,7 @@ impl<'a> Tarball<'a> { GeneratedTarball { path: crate::dist::distdir(self.builder).join(format!("{}.tar.{}", package_name, ext)), - decompressed_output: self.temp_dir.join(package_name), + decompressed_output, work: self.temp_dir, } }