Skip to content
Merged
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
23 changes: 18 additions & 5 deletions crates/cargo-util-schemas/src/core/package_id_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,14 @@ impl PackageIdSpec {
let git_ref = GitReference::from_query(url.query_pairs());
url.set_query(None);
kind = Some(SourceKind::Git(git_ref));
url = strip_url_protocol(&url);
url = strip_url_protocol(&url)?;
}
"registry" => {
if url.query().is_some() {
return Err(ErrorKind::UnexpectedQueryString(url).into());
}
kind = Some(SourceKind::Registry);
url = strip_url_protocol(&url);
url = strip_url_protocol(&url)?;
}
"sparse" => {
if url.query().is_some() {
Expand All @@ -138,7 +138,7 @@ impl PackageIdSpec {
return Err(ErrorKind::UnsupportedPathPlusScheme(scheme.into()).into());
}
kind = Some(SourceKind::Path);
url = strip_url_protocol(&url);
url = strip_url_protocol(&url)?;
}
kind => return Err(ErrorKind::UnsupportedProtocol(kind.into()).into()),
}
Expand Down Expand Up @@ -225,10 +225,14 @@ fn parse_spec(spec: &str) -> Result<Option<(String, Option<PartialVersion>)>> {
Ok(Some((name, Some(ver))))
}

fn strip_url_protocol(url: &Url) -> Url {
fn strip_url_protocol(url: &Url) -> Result<Url> {
// Ridiculous hoop because `Url::set_scheme` errors when changing to http/https
let raw = url.to_string();
raw.split_once('+').unwrap().1.parse().unwrap()
let (_, rest) = raw
.split_once('+')
.ok_or_else(|| ErrorKind::InvalidPkgIdUrl(raw.clone()))?;
rest.parse()

@weihanglo weihanglo Oct 4, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the parsing part also return malformed protocol error? URL parse error is not always caused by malformed protocol, no? Also, it would be great to also have tests for missing protocol + part, if needed

View changes since the review

@rabindra789 rabindra789 Oct 5, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. you are right. I changed the error to InvalidPkgIdUrl so caees like git+https:// are not reported as malformed protocol. I also added tests for it.

.map_err(|_| ErrorKind::InvalidPkgIdUrl(raw).into())
}

impl fmt::Display for PackageIdSpec {
Expand Down Expand Up @@ -334,6 +338,9 @@ enum ErrorKind {

#[error(transparent)]
PartialVersion(#[from] crate::core::PartialVersionError),

#[error("invalid pkgid url: {0}")]
InvalidPkgIdUrl(String),
}

#[cfg(test)]
Expand Down Expand Up @@ -772,5 +779,11 @@ mod tests {
err!("registry+https://github.com", ErrorKind::NameValidation(_));
err!("https://crates.io/1foo#1.2.3", ErrorKind::NameValidation(_));
err!("https://example.com/foo#", ErrorKind::EmptyFragment);
err!("git++://x:", ErrorKind::InvalidPkgIdUrl(_));
err!(
"git++https://github.com/rust-lang/cargo",
ErrorKind::InvalidPkgIdUrl(_)
);
err!("git+https://", ErrorKind::InvalidPkgIdUrl(_));
}
}
Loading