From 841563e56c4e1f138003c96f2c40f7c1974caff2 Mon Sep 17 00:00:00 2001 From: Darshan Sen Date: Thu, 17 Jun 2021 14:24:43 +0530 Subject: [PATCH] url: prevent pathname setter from erasing path of path-only URLs This change prevents the pathname setter from erasing the path of path-only URLs as that would make them cannot-be-a-base URLs. The changes in all files except `src/node_url.cc` have been done by running: ```console git node wpt url ``` Fixes: https://github.com/nodejs/node/issues/39059 Signed-off-by: Darshan Sen --- src/node_url.cc | 2 + test/fixtures/wpt/README.md | 4 +- .../wpt/url/resources/setters_tests.json | 58 +++++ .../wpt/url/resources/urltestdata.json | 224 +++++++++++++++++- test/fixtures/wpt/versions.json | 2 +- 5 files changed, 286 insertions(+), 4 deletions(-) diff --git a/src/node_url.cc b/src/node_url.cc index 4343b672c6a982..9aa2a8ed398108 100644 --- a/src/node_url.cc +++ b/src/node_url.cc @@ -1477,6 +1477,8 @@ void URL::Parse(const char* input, if (ch != '/') { continue; } + } else if (has_state_override && url->host.empty()) { + url->path.emplace_back(""); } break; case kPath: diff --git a/test/fixtures/wpt/README.md b/test/fixtures/wpt/README.md index b68466264ebdf8..39066c73098f9e 100644 --- a/test/fixtures/wpt/README.md +++ b/test/fixtures/wpt/README.md @@ -21,7 +21,7 @@ Last update: - html/webappapis/timers: https://github.com/web-platform-tests/wpt/tree/5873f2d8f1/html/webappapis/timers - interfaces: https://github.com/web-platform-tests/wpt/tree/79fa4cf76e/interfaces - resources: https://github.com/web-platform-tests/wpt/tree/972ca5b669/resources -- url: https://github.com/web-platform-tests/wpt/tree/1fcb39223d/url +- url: https://github.com/web-platform-tests/wpt/tree/41590413af/url [Web Platform Tests]: https://github.com/web-platform-tests/wpt -[`git node wpt`]: https://github.com/nodejs/node-core-utils/blob/master/docs/git-node.md#git-node-wpt +[`git node wpt`]: https://github.com/nodejs/node-core-utils/blob/main/docs/git-node.md#git-node-wpt diff --git a/test/fixtures/wpt/url/resources/setters_tests.json b/test/fixtures/wpt/url/resources/setters_tests.json index 56bcae464a6f54..69c36d01536bdc 100644 --- a/test/fixtures/wpt/url/resources/setters_tests.json +++ b/test/fixtures/wpt/url/resources/setters_tests.json @@ -990,6 +990,26 @@ "hostname": "test", "port": "12" } + }, + { + "comment": "Leading / is not stripped", + "href": "http://example.com/", + "new_value": "///bad.com", + "expected": { + "href": "http://example.com/", + "host": "example.com", + "hostname": "example.com" + } + }, + { + "comment": "Leading / is not stripped", + "href": "sc://example.com/", + "new_value": "///bad.com", + "expected": { + "href": "sc:///", + "host": "", + "hostname": "" + } } ], "hostname": [ @@ -1345,6 +1365,26 @@ "hostname": "", "pathname": "//p" } + }, + { + "comment": "Leading / is not stripped", + "href": "http://example.com/", + "new_value": "///bad.com", + "expected": { + "href": "http://example.com/", + "host": "example.com", + "hostname": "example.com" + } + }, + { + "comment": "Leading / is not stripped", + "href": "sc://example.com/", + "new_value": "///bad.com", + "expected": { + "href": "sc:///", + "host": "", + "hostname": "" + } } ], "port": [ @@ -1667,6 +1707,24 @@ "pathname": "/%23" } }, + { + "comment": "? doesn't mess up encoding", + "href": "http://example.net", + "new_value": "/?é", + "expected": { + "href": "http://example.net/%3F%C3%A9", + "pathname": "/%3F%C3%A9" + } + }, + { + "comment": "# doesn't mess up encoding", + "href": "http://example.net", + "new_value": "/#é", + "expected": { + "href": "http://example.net/%23%C3%A9", + "pathname": "/%23%C3%A9" + } + }, { "comment": "File URLs and (back)slashes", "href": "file://monkey/", diff --git a/test/fixtures/wpt/url/resources/urltestdata.json b/test/fixtures/wpt/url/resources/urltestdata.json index 96c42d2284ebf7..a56b30caf98cb1 100644 --- a/test/fixtures/wpt/url/resources/urltestdata.json +++ b/test/fixtures/wpt/url/resources/urltestdata.json @@ -539,6 +539,36 @@ "search": "", "hash": "" }, + { + "input": "\\x", + "base": "http://example.org/foo/bar", + "href": "http://example.org/x", + "origin": "http://example.org", + "protocol": "http:", + "username": "", + "password": "", + "host": "example.org", + "hostname": "example.org", + "port": "", + "pathname": "/x", + "search": "", + "hash": "" + }, + { + "input": "\\\\x\\hello", + "base": "http://example.org/foo/bar", + "href": "http://x/hello", + "origin": "http://x", + "protocol": "http:", + "username": "", + "password": "", + "host": "x", + "hostname": "x", + "port": "", + "pathname": "/hello", + "search": "", + "hash": "" + }, { "input": "::", "base": "http://example.org/foo/bar", @@ -4698,6 +4728,140 @@ "base": "about:blank", "failure": true }, + { + "input": "foo://ho\u0000st/", + "base": "about:blank", + "failure": true + }, + { + "input": "foo://ho|st/", + "base": "about:blank", + "failure": true + }, + "Forbidden host codepoints: tabs and newlines are removed during preprocessing", + { + "input": "foo://ho\u0009st/", + "base": "about:blank", + "hash": "", + "host": "host", + "hostname": "host", + "href":"foo://host/", + "password": "", + "pathname": "/", + "port":"", + "protocol": "foo:", + "search": "", + "username": "" + }, + { + "input": "foo://ho\u000Ast/", + "base": "about:blank", + "hash": "", + "host": "host", + "hostname": "host", + "href":"foo://host/", + "password": "", + "pathname": "/", + "port":"", + "protocol": "foo:", + "search": "", + "username": "" + }, + { + "input": "foo://ho\u000Dst/", + "base": "about:blank", + "hash": "", + "host": "host", + "hostname": "host", + "href":"foo://host/", + "password": "", + "pathname": "/", + "port":"", + "protocol": "foo:", + "search": "", + "username": "" + }, + "Encoded forbidden host codepoints in special URLs", + { + "input": "http://ho%00st/", + "base": "about:blank", + "failure": true + }, + { + "input": "http://ho%09st/", + "base": "about:blank", + "failure": true + }, + { + "input": "http://ho%0Ast/", + "base": "about:blank", + "failure": true + }, + { + "input": "http://ho%0Dst/", + "base": "about:blank", + "failure": true + }, + { + "input": "http://ho%20st/", + "base": "about:blank", + "failure": true + }, + { + "input": "http://ho%23st/", + "base": "about:blank", + "failure": true + }, + { + "input": "http://ho%2Fst/", + "base": "about:blank", + "failure": true + }, + { + "input": "http://ho%3Ast/", + "base": "about:blank", + "failure": true + }, + { + "input": "http://ho%3Cst/", + "base": "about:blank", + "failure": true + }, + { + "input": "http://ho%3Est/", + "base": "about:blank", + "failure": true + }, + { + "input": "http://ho%3Fst/", + "base": "about:blank", + "failure": true + }, + { + "input": "http://ho%40st/", + "base": "about:blank", + "failure": true + }, + { + "input": "http://ho%5Bst/", + "base": "about:blank", + "failure": true + }, + { + "input": "http://ho%5Cst/", + "base": "about:blank", + "failure": true + }, + { + "input": "http://ho%5Dst/", + "base": "about:blank", + "failure": true + }, + { + "input": "http://ho%7Cst/", + "base": "about:blank", + "failure": true + }, "Allowed host code points", { "input": "http://\u001F!\"$&'()*+,-.;=_`{}~/", @@ -7676,7 +7840,8 @@ "search": "", "username": "joe" }, - { "input": "foo://!\"$%&'()*+,-.;=_`{}~/", + { + "input": "foo://!\"$%&'()*+,-.;=_`{}~/", "base": "about:blank", "hash": "", "host": "!\"$%&'()*+,-.;=_`{}~", @@ -7794,5 +7959,62 @@ "protocol": "wss:", "search": "", "username": "" + }, + "Ensure that input schemes are not ignored when resolving non-special URLs", + { + "input": "abc:rootless", + "base": "abc://host/path", + "hash": "", + "host": "", + "hostname": "", + "href":"abc:rootless", + "password": "", + "pathname": "rootless", + "port":"", + "protocol": "abc:", + "search": "", + "username": "" + }, + { + "input": "abc:rootless", + "base": "abc:/path", + "hash": "", + "host": "", + "hostname": "", + "href":"abc:rootless", + "password": "", + "pathname": "rootless", + "port":"", + "protocol": "abc:", + "search": "", + "username": "" + }, + { + "input": "abc:rootless", + "base": "abc:path", + "hash": "", + "host": "", + "hostname": "", + "href":"abc:rootless", + "password": "", + "pathname": "rootless", + "port":"", + "protocol": "abc:", + "search": "", + "username": "" + }, + { + "input": "abc:/rooted", + "base": "abc://host/path", + "hash": "", + "host": "", + "hostname": "", + "href":"abc:/rooted", + "password": "", + "pathname": "/rooted", + "port":"", + "protocol": "abc:", + "search": "", + "username": "" } ] diff --git a/test/fixtures/wpt/versions.json b/test/fixtures/wpt/versions.json index b610d0ab47ec94..068178121882d5 100644 --- a/test/fixtures/wpt/versions.json +++ b/test/fixtures/wpt/versions.json @@ -44,7 +44,7 @@ "path": "resources" }, "url": { - "commit": "1fcb39223d3009fbb46c1b254755d6cc75e290f1", + "commit": "41590413afa23bd29e452287b816423014e84cd7", "path": "url" } } \ No newline at end of file