Skip to content

set_host("localhost") on file:// URL produces non-roundtripping serialization #1102

Description

@jrey8343

Summary

Calling set_host(Some("localhost")) on a file:/// URL produces file://localhost/..., but re-parsing that serialization strips localhost per the WHATWG URL spec (which normalizes file://localhost/ to file:///). This means the URL produced by set_host does not roundtrip through Url::parse.

Reproduction

use url::Url;

fn main() {
    let mut url = Url::parse("file:///tmp/test").unwrap();
    url.set_host(Some("localhost")).unwrap();

    let modified = url.as_str().to_string();
    println!("After set_host: {:?}", modified);
    // After set_host: "file://localhost/tmp/test"

    let reparsed = Url::parse(&modified).unwrap();
    println!("Reparsed:       {:?}", reparsed.as_str());
    // Reparsed:       "file:///tmp/test"

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

Analysis

Per the WHATWG URL standard, file://localhost/ is normalized to file:/// during parsing. The set_host method should apply the same normalization — when setting the host to "localhost" on a file:// URL, it should either:

  1. Normalize it away (set host to empty/None), or
  2. Serialize it without localhost so the output roundtrips

Currently set_host stores localhost literally, producing a serialization that the parser will normalize differently on re-parse.

Found by

This bug was found by fuzzing with the fuzz_url_setters 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