about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJoshua Nelson <jyn514@gmail.com>2022-05-26 11:27:44 -0400
committerJoshua Nelson <jnelson@cloudflare.com>2022-06-19 15:54:31 -0500
commitb9eedea4b0368fd1f00f204db75109ff444fab5b (patch)
tree8b7396be9a5c2c4a4198a16673027d63ee85ca09
parent532be942ddf8f40d086e54d157453434b16e9647 (diff)
downloadrust-b9eedea4b0368fd1f00f204db75109ff444fab5b.tar.gz
rust-b9eedea4b0368fd1f00f204db75109ff444fab5b.zip
Panic if `dist` generates a symbolic link in a generated tarball
This avoids regressions in rustup-toolchain-install-master
-rw-r--r--Cargo.lock1
-rw-r--r--src/bootstrap/Cargo.toml1
-rw-r--r--src/bootstrap/dist.rs7
-rw-r--r--src/bootstrap/tarball.rs20
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,
         }
     }