Skip to content

Commit 86dffda

Browse files
committed
Ensure only exact name matches are added to the index
On the client side cargo checks dependency names against the index and requires an exact match. For instance, a user cannot depend on `diesel-migrations` or `Diesel_migrations` as cargo generates an error directing them to use the correct name `diesel_migrations`. This check for an exact name match is now repeated on the server when a crate is published. This ensures that bugs in cargo or third-party tooling cannot result in a dependency name that cargo is unable to locate in the index.
1 parent 005b010 commit 86dffda

File tree

3 files changed

+24
-1
lines changed

3 files changed

+24
-1
lines changed

src/models/dependency.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ pub fn add_dependencies(
8181
let git_and_new_dependencies = deps
8282
.iter()
8383
.map(|dep| {
84-
let krate = Crate::by_name(&dep.name)
84+
// Match only identical names to ensure the index always references the original crate name
85+
let krate = Crate::by_exact_name(&dep.name)
8586
.first::<Crate>(&*conn)
8687
.map_err(|_| human(&format_args!("no known crate named `{}`", &*dep.name)))?;
8788
if dep.version_req == semver::VersionReq::parse("*").unwrap() {

src/models/krate.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ type CanonCrateName<T> = self::canon_crate_name::HelperType<T>;
9191
type All = diesel::dsl::Select<crates::table, AllColumns>;
9292
type WithName<'a> = diesel::dsl::Eq<CanonCrateName<crates::name>, CanonCrateName<&'a str>>;
9393
type ByName<'a> = diesel::dsl::Filter<All, WithName<'a>>;
94+
type ByExactName<'a> = diesel::dsl::Filter<All, diesel::dsl::Eq<crates::name, &'a str>>;
9495

9596
#[derive(Insertable, AsChangeset, Default, Debug)]
9697
#[table_name = "crates"]
@@ -244,6 +245,10 @@ impl Crate {
244245
Crate::all().filter(Self::with_name(name))
245246
}
246247

248+
pub fn by_exact_name(name: &str) -> ByExactName<'_> {
249+
Crate::all().filter(crates::name.eq(name))
250+
}
251+
247252
pub fn all() -> All {
248253
crates::table.select(ALL_COLUMNS)
249254
}

src/tests/krate.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,23 @@ fn new_krate_with_dependency() {
650650
token.publish(crate_to_publish).good();
651651
}
652652

653+
#[test]
654+
fn reject_new_krate_with_non_exact_dependency() {
655+
let (app, _, user, token) = TestApp::init().with_token();
656+
657+
app.db(|conn| {
658+
CrateBuilder::new("foo-dep", user.as_model().id).expect_build(&conn);
659+
});
660+
661+
// Use non-exact name for the dependency
662+
let dependency = DependencyBuilder::new("foo_dep");
663+
664+
let crate_to_publish = PublishBuilder::new("new_dep")
665+
.version("1.0.0")
666+
.dependency(dependency);
667+
token.publish(crate_to_publish).bad_with_status(200);
668+
}
669+
653670
#[test]
654671
fn new_krate_with_wildcard_dependency() {
655672
let (app, _, user, token) = TestApp::init().with_token();

0 commit comments

Comments
 (0)