From 0d06193bf1ff4d1f79e1676cd8079704368f357b Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 21 Oct 2021 17:03:58 +0800 Subject: [PATCH] Only canonicalize executable path if it has relative directories Otherwise symbolic links may also accidentally be resolved which may lead to unexpected results in the case of 'coreutils', a binary that depends on the executable name being a symbolic link. This means a path like /bin/echo being canonicalized to /bin/coreutils will loose all information about the desired functionality. Test failures will occur if 'echo' is resolved that way and it's not trivial to find the cause of it in the provided error messages. --- crates/cargo-util/src/paths.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/crates/cargo-util/src/paths.rs b/crates/cargo-util/src/paths.rs index d63611d7a..66ff79d21 100644 --- a/crates/cargo-util/src/paths.rs +++ b/crates/cargo-util/src/paths.rs @@ -125,7 +125,19 @@ pub fn resolve_executable(exec: &Path) -> Result { if candidate.is_file() { // PATH may have a component like "." in it, so we still need to // canonicalize. - return Ok(candidate.canonicalize()?); + // Only do so if there are relative path components, otherwise symlinks to 'echo' may be resolved to their + // root program like 'coreutils' which relies on the executable name for proper function. + let has_relative_path_components = candidate.components().any(|c| { + matches!( + c, + std::path::Component::ParentDir | std::path::Component::CurDir + ) + }); + return Ok(if has_relative_path_components { + candidate.canonicalize()? + } else { + candidate + }); } }