Skip to content

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

@jrey8343

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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions