Skip to content

file:// URL parse roundtrip mismatch #1101

Description

@jrey8343

Summary

Parsing certain file:// URLs, serializing them, and re-parsing produces a different URL. This violates the expected invariant that Url::parse(url.as_str()) should produce an identical URL.

Reproduction

use url::Url;

fn main() {
    let input = "file://.cRe!+aacRddddddddddddddtpe=//t:/a|et/!..";
    let parsed = Url::parse(input).unwrap();
    let serialized = parsed.as_str();
    println!("Serialized: {:?}", serialized);
    // Serialized: "file://.cre%21+aacRddddddddddddddtpe=//t:/a|et/!.."

    let reparsed = Url::parse(serialized).unwrap();
    println!("Reparsed:   {:?}", reparsed.as_str());
    // Reparsed:   "file:///t:/a%7Cet/!.."

    assert_eq!(serialized, reparsed.as_str()); // FAILS
}

Analysis

The first parse interprets the authority as .cre%21+aacRddddddddddddddtpe= with the path //t:/a|et/!... When the serialized form is re-parsed, the parser appears to re-interpret the structure differently, producing file:///t:/a%7Cet/!.. — a completely different URL with no host and a different path.

The serialized output of a parsed URL should always re-parse to the same URL.

Found by

This bug was found by fuzzing with the fuzz_url_parse_roundtrip target (see #1100).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    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