Skip to content

PackageIdSpec::parse panics on URL package specs with an empty fragment (...#) #16731

@meng-xu-cs

Description

@meng-xu-cs

Problem

PackageIdSpec::parse can panic when given a URL-form package ID specification whose fragment is present but empty, such as https://example.com/foo#.

The panic happens in crates/cargo-util-schemas/src/core/package_id_spec.rs inside PackageIdSpec::from_url, where the code does fragment.chars().next().unwrap() without handling the case where fragment == "".

Some(fragment) => match parse_spec(&fragment)? {
Some((name, ver)) => (name, ver),
None => {
if fragment.chars().next().unwrap().is_alphabetic() {
(String::from(fragment.as_str()), None)
} else {
let version = fragment.parse::<PartialVersion>()?;
(String::from(path_name), Some(version))
}
}
},

Steps

Minimal library-level reproduction:

use cargo_util_schemas::core::PackageIdSpec;

fn main() {
    // Panics today instead of returning Result::Err(...)
    let _ = PackageIdSpec::parse("https://example.com/foo#");
}

Equivalent test:

#[test]
fn empty_fragment_should_not_panic() {
    let _ = cargo_util_schemas::core::PackageIdSpec::parse("https://example.com/foo#");
}

Cargo should not panic on malformed package ID specifications.

For an empty fragment, one of these would be reasonable:

  • return a normal Err(...) explaining that an empty fragment is invalid, or
  • treat an empty fragment the same as no fragment at all.

Returning an error seems preferable, because the package ID spec grammar documents the fragment as #(pkgname | semver), so # by itself is not a valid spec.

Possible Solution(s)

Handle the empty-fragment case before calling chars().next().unwrap().

Notes

No response

Version


Metadata

Metadata

Assignees

Labels

A-cliArea: Command-line interface, option parsing, etc.C-bugCategory: bugS-acceptedStatus: Issue or feature is accepted, and has a team member available to help mentor or review

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions