Skip to content

Commit

Permalink
CVE-2022-36113: add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
weihanglo authored and pietroalbini committed Sep 14, 2022
1 parent 97b8091 commit dafe4a7
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 7 deletions.
40 changes: 33 additions & 7 deletions crates/cargo-test-support/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,10 +403,17 @@ pub struct Dependency {
optional: bool,
}

/// Entry with data that corresponds to [`tar::EntryType`].
#[non_exhaustive]
enum EntryData {
Regular(String),
Symlink(PathBuf),
}

/// A file to be created in a package.
struct PackageFile {
path: String,
contents: String,
contents: EntryData,
/// The Unix mode for the file. Note that when extracted on Windows, this
/// is mostly ignored since it doesn't have the same style of permissions.
mode: u32,
Expand Down Expand Up @@ -780,13 +787,24 @@ impl Package {
pub fn file_with_mode(&mut self, path: &str, mode: u32, contents: &str) -> &mut Package {
self.files.push(PackageFile {
path: path.to_string(),
contents: contents.to_string(),
contents: EntryData::Regular(contents.into()),
mode,
extra: false,
});
self
}

/// Adds a symlink to a path to the package.
pub fn symlink(&mut self, dst: &str, src: &str) -> &mut Package {
self.files.push(PackageFile {
path: dst.to_string(),
contents: EntryData::Symlink(src.into()),
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 All @@ -795,7 +813,7 @@ impl Package {
pub fn extra_file(&mut self, path: &str, contents: &str) -> &mut Package {
self.files.push(PackageFile {
path: path.to_string(),
contents: contents.to_string(),
contents: EntryData::Regular(contents.to_string()),
mode: DEFAULT_MODE,
extra: true,
});
Expand Down Expand Up @@ -1033,7 +1051,7 @@ impl Package {
self.append_manifest(&mut a);
}
if self.files.is_empty() {
self.append(&mut a, "src/lib.rs", DEFAULT_MODE, "");
self.append(&mut a, "src/lib.rs", DEFAULT_MODE, &EntryData::Regular("".into()));
} else {
for PackageFile {
path,
Expand Down Expand Up @@ -1107,10 +1125,10 @@ impl Package {
manifest.push_str("[lib]\nproc-macro = true\n");
}

self.append(ar, "Cargo.toml", DEFAULT_MODE, &manifest);
self.append(ar, "Cargo.toml", DEFAULT_MODE, &EntryData::Regular(manifest.into()));
}

fn append<W: Write>(&self, ar: &mut Builder<W>, file: &str, mode: u32, contents: &str) {
fn append<W: Write>(&self, ar: &mut Builder<W>, file: &str, mode: u32, contents: &EntryData) {
self.append_raw(
ar,
&format!("{}-{}/{}", self.name, self.vers, file),
Expand All @@ -1119,8 +1137,16 @@ impl Package {
);
}

fn append_raw<W: Write>(&self, ar: &mut Builder<W>, path: &str, mode: u32, contents: &str) {
fn append_raw<W: Write>(&self, ar: &mut Builder<W>, path: &str, mode: u32, contents: &EntryData) {
let mut header = Header::new_ustar();
let contents = match contents {
EntryData::Regular(contents) => contents.as_str(),
EntryData::Symlink(src) => {
header.set_entry_type(tar::EntryType::Symlink);
t!(header.set_link_name(src));
"" // Symlink has no contents.
}
};
header.set_size(contents.len() as u64);
t!(header.set_path(path));
header.set_mode(mode);
Expand Down
41 changes: 41 additions & 0 deletions tests/testsuite/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2583,6 +2583,47 @@ fn package_lock_inside_package_is_overwritten() {
assert_eq!(ok.metadata().unwrap().len(), 2);
}

#[cargo_test]
fn package_lock_as_a_symlink_inside_package_is_overwritten() {
let registry = registry::init();
let p = project()
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = ">= 0.0.0"
"#,
)
.file("src/main.rs", "fn main() {}")
.build();

Package::new("bar", "0.0.1")
.file("src/lib.rs", "pub fn f() {}")
.symlink(".cargo-ok", "src/lib.rs")
.publish();

p.cargo("build").run();

let id = SourceId::for_registry(registry.index_url()).unwrap();
let hash = cargo::util::hex::short_hash(&id);
let pkg_root = cargo_home()
.join("registry")
.join("src")
.join(format!("-{}", hash))
.join("bar-0.0.1");
let ok = pkg_root.join(".cargo-ok");
let librs = pkg_root.join("src/lib.rs");

// Is correctly overwritten and doesn't affect the file linked to
assert_eq!(ok.metadata().unwrap().len(), 2);
assert_eq!(fs::read_to_string(librs).unwrap(), "pub fn f() {}");
}

#[cargo_test]
fn ignores_unknown_index_version_http() {
let _server = setup_http();
Expand Down

0 comments on commit dafe4a7

Please sign in to comment.