about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDan Cross <dcross@google.com>2020-08-14 20:29:04 -0400
committerDan Cross <dcross@google.com>2020-08-17 13:23:29 -0400
commit6ad6d8c25c399cdc001ca65801017e8c5c51e9e2 (patch)
tree08919bb4238e6ce83a1ea1c8e949445bbdbd3c79
parente8df0b893235aa06c6362d1a8646296310f79f81 (diff)
downloadrust-6ad6d8c25c399cdc001ca65801017e8c5c51e9e2.tar.gz
rust-6ad6d8c25c399cdc001ca65801017e8c5c51e9e2.zip
librustc_metadata::locator: Properly detect file type.
Make sure to test for file types against the non-canonicalized name
to avoid detecting the wrong type.  Some systems save build artifacts
into associative file stores that do not preserve extensions, and
then link to those using conventionally-named symbolic links that
are the arguments to `rustc` et al.  If we canonicalize before
testing the type, we resolve the symlink, the extension is lost and
we might treat rlibs and rmetas as dylibs.

The fix is to introduce a temporary to hold the canonicalized name,
compare against the non-canonical name, and add a comment
explaining what's going on for the would-be maintainer who sees a
potential cleanup.

Signed-off-by: Dan Cross <dcross@google.com>
-rw-r--r--src/librustc_metadata/locator.rs14
1 files changed, 10 insertions, 4 deletions
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index bdd20a4bf6f..8fa14a44f52 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -685,13 +685,19 @@ impl<'a> CrateLocator<'a> {
                     && file.ends_with(&self.target.options.dll_suffix)
             {
                 // Make sure there's at most one rlib and at most one dylib.
-                let loc = fs::canonicalize(&loc).unwrap_or_else(|_| loc.clone());
+                // Note to take care and match against the non-canonicalized name:
+                // some systems save build artifacts into content-addressed stores
+                // that do not preserve extensions, and then link to them using
+                // e.g. symbolic links. If we canonicalize too early, we resolve
+                // the symlink, the file type is lost and we might treat rlibs and
+                // rmetas as dylibs.
+                let loc_canon = fs::canonicalize(&loc).unwrap_or_else(|_| loc.clone());
                 if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") {
-                    rlibs.insert(loc, PathKind::ExternFlag);
+                    rlibs.insert(loc_canon, PathKind::ExternFlag);
                 } else if loc.file_name().unwrap().to_str().unwrap().ends_with(".rmeta") {
-                    rmetas.insert(loc, PathKind::ExternFlag);
+                    rmetas.insert(loc_canon, PathKind::ExternFlag);
                 } else {
-                    dylibs.insert(loc, PathKind::ExternFlag);
+                    dylibs.insert(loc_canon, PathKind::ExternFlag);
                 }
             } else {
                 self.rejected_via_filename