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).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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