Skip to content

new URL gives wrong result on leading backslash #36559

Closed
@gnprice

Description

@gnprice
  • Version: v15.4.0
  • Platform: Linux 5b80145d2618 4.19.0-13-amd64 #1 SMP Debian 4.19.160-2 (2020-11-28) x86_64 GNU/Linux
  • Subsystem:

What steps will reproduce the bug?

Parse a relative-URL string that begins with a backslash. For example:

> new URL("\\x", "https://example/foo/bar").href
'https://example/foo//x'

How often does it reproduce? Is there a required condition?

Always

What is the expected behavior?

The leading backslash should have the same behavior as if it were a proper /. The input would be treated as a path-absolute URL (replacing the whole path from the base URL), or a scheme-relative URL (replacing all but the scheme from the base URL).

For example:
new URL("\\x", "https://example/foo/bar").href -> "https://example/x"
new URL("\\\\x", "https://example/foo/bar").href -> "https://x/"

What do you see instead?

The leading backslash is treated incorrectly. The effect seems to be as if the input were a path-relative-URL string -- the base URL's path, except for its last component, appears in the result. In the example:

> new URL("\\x", "https://example/foo/bar").href
'https://example/foo//x'

Additional information

The behavior of new URL is documented as being defined by the WHATWG URL Standard. An input string like \x, with a leading backslash, is never a "valid URL string" as defined in that standard... but the standard nevertheless defines what the URL constructor should return for it.

Because the example input \x is so short, it's not hard to walk through the URL parser as defined in the URL Standard and confirm what result the standard calls for. For the base URL of https://example/, it goes from "scheme start state" to "no scheme state" to "relative state" to "relative slash state" to "path state", following exactly the same track as an input of /x would do, except only that \x emits a validation error. In the URL parser as defined by the URL Standard, a "validation error" does not affect the parser's result, so the resulting URL should be the same as for /x.

As a different kind of check, Chrome (87.0.4280.88) gives the correct answer according to the spec. In the browser console:

> new URL("\\x", "https://example/foo/bar").href
"https://example/x"

So does Firefox (78.0):

» new URL("\\x", "https://example/foo/bar").href
← "https://example/x"

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugIssues with confirmed bugs.urlIssues and PRs related to the legacy built-in url module.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions