Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ similar = "2.7.0"
supports-hyperlinks = "3.2.0"
supports-unicode = "3.0.0"
snapbox = { version = "1.0.0", features = ["diff", "dir", "term-svg", "regex", "json"] }
tar = { version = "0.4.44", default-features = false }
tar = { version = "0.4.45", default-features = false }
tempfile = "3.25.0"
thiserror = "2.0.18"
time = { version = "0.3.47", features = ["parsing", "formatting", "serde"] }
Expand Down
16 changes: 16 additions & 0 deletions crates/cargo-test-support/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,7 @@ pub struct Dependency {
enum EntryData {
Regular(String),
Symlink(PathBuf),
Directory,
}

/// A file to be created in a package.
Expand Down Expand Up @@ -1330,6 +1331,17 @@ impl Package {
self
}

/// Adds an empty directory at the given path.
pub fn directory(&mut self, path: &str) -> &mut Package {
self.files.push(PackageFile {
path: path.to_string(),
contents: EntryData::Directory,
mode: DEFAULT_MODE,
extra: false,
});
self
}

/// Adds an "extra" file that is not rooted within the package.
///
/// Normal files are automatically placed within a directory named
Expand Down Expand Up @@ -1742,6 +1754,10 @@ impl Package {
t!(header.set_link_name(src));
"" // Symlink has no contents.
}
EntryData::Directory => {
header.set_entry_type(tar::EntryType::Directory);
""
}
};
header.set_size(contents.len() as u64);
t!(header.set_path(path));
Expand Down
74 changes: 74 additions & 0 deletions tests/testsuite/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4695,3 +4695,77 @@ fn deterministic_mtime() {
assert_deterministic_mtime(pkg_root.join("Cargo.toml"));
assert_deterministic_mtime(pkg_root.join(".cargo_vcs_info.json"));
}

#[cargo_test]
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();
#[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,
0o700
);
}

Package::new("bar", "1.0.0")
.file("src/lib.rs", "")
.symlink("smuggled", victim.to_str().unwrap())
.directory("smuggled")
.publish();

let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
edition = "2015"

[dependencies]
bar = "1.0"
"#,
)
.file("src/lib.rs", "")
.build();

p.cargo("fetch")
.with_status(101)
.with_stderr_data(str![[r#"
[UPDATING] `dummy-registry` index
[LOCKING] 1 package to latest compatible version
[DOWNLOADING] crates ...
[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)
[ERROR] failed to download replaced source registry `crates-io`

Caused by:
failed to unpack package `bar v1.0.0 (registry `dummy-registry`)`

Caused by:
failed to unpack entry at `bar-1.0.0/smuggled`

Caused by:
failed to unpack `[ROOT]/home/.cargo/registry/src/-[HASH]/bar-1.0.0/smuggled`

Caused by:
[..] when creating dir [ROOT]/home/.cargo/registry/src/-[HASH]/bar-1.0.0/smuggled

"#]])
.run();

#[cfg(unix)]
{
// Permissions should not change.
use std::os::unix::fs::PermissionsExt;
assert_eq!(
victim.metadata().unwrap().permissions().mode() & 0o777,
0o700
);
}
}