From d00475981aca9e08c5d3aeaca10d4002206f8b04 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Sat, 21 Mar 2026 01:27:07 +0000 Subject: [PATCH] Fix symlink_and_directory when running in a long target dir name (#16775) This fixes the `symlink_and_directory` test which is failing on rust-lang/rust because it runs in a longer target directory name. This causes the path to exceed the limit of 100 characters for a USTAR tar header. The fix is to just use a directory from the `tempfile` crate instead of trying to create one inside the test sandbox. I believe this should be reliably under 100 characters. Unfortunately we cannot switch to GNU tar headers which dynamically switch to using GNU extensions for long paths because it would cause the package checksums to change based on whether or not the path causes it to exceed the limit. I double checked the old tar 0.4.44, and the test fails as expected. --- crates/cargo-test-support/src/registry.rs | 4 ++++ tests/testsuite/registry.rs | 13 ++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/crates/cargo-test-support/src/registry.rs b/crates/cargo-test-support/src/registry.rs index c1b7b0d86a4..ebb46d79698 100644 --- a/crates/cargo-test-support/src/registry.rs +++ b/crates/cargo-test-support/src/registry.rs @@ -1747,6 +1747,10 @@ impl Package { mode: u32, contents: &EntryData, ) { + // Unfortunately we cannot use GNU headers with dynamic extensions for + // long paths because that would cause package checksums to change + // based on whether or not the tests are running in a long directory + // name. let mut header = Header::new_ustar(); let contents = match contents { EntryData::Regular(contents) => contents.as_str(), diff --git a/tests/testsuite/registry.rs b/tests/testsuite/registry.rs index 07a28864510..5a30dad6462 100644 --- a/tests/testsuite/registry.rs +++ b/tests/testsuite/registry.rs @@ -4701,22 +4701,25 @@ fn symlink_and_directory() { // Tests for symlink and directory entry in a tar file. The tar crate // would incorrectly change the permissions of the symlink destination, // which could be anywhere on the filesystem. - let victim = paths::root().join("victim"); - fs::create_dir(&victim).unwrap(); + // + // Use a tempfile path to keep the path length below 100 for a USTAR + // archive. Otherwise, a long target directory name would break the + // archive generation. + let victim = tempfile::tempdir().unwrap(); #[cfg(unix)] { use std::os::unix::fs::PermissionsExt; let perm = fs::Permissions::from_mode(0o700); fs::set_permissions(&victim, perm).unwrap(); assert_eq!( - victim.metadata().unwrap().permissions().mode() & 0o777, + victim.path().metadata().unwrap().permissions().mode() & 0o777, 0o700 ); } Package::new("bar", "1.0.0") .file("src/lib.rs", "") - .symlink("smuggled", victim.to_str().unwrap()) + .symlink("smuggled", victim.path().to_str().unwrap()) .directory("smuggled") .publish(); @@ -4764,7 +4767,7 @@ Caused by: // Permissions should not change. use std::os::unix::fs::PermissionsExt; assert_eq!( - victim.metadata().unwrap().permissions().mode() & 0o777, + victim.path().metadata().unwrap().permissions().mode() & 0o777, 0o700 ); }