From b8c15c7413413163b255e4652c950361b46413b1 Mon Sep 17 00:00:00 2001 From: raisinten Date: Wed, 23 Dec 2020 20:29:39 +0530 Subject: [PATCH] src: fix leading backslash bug in URL The associated condition mentioned in the URL parsing algorithm of the WHATWG URL Standard is: url is special and c is U+005C (\) So, `special_back_slash` must be updated whenever `special` is updated. Fixes: https://github.com/nodejs/node/issues/36559 PR-URL: https://github.com/nodejs/node/pull/36613 Reviewed-By: Rich Trott Reviewed-By: Daijiro Wachi Reviewed-By: James M Snell --- src/node_url.cc | 6 +++++- test/cctest/test_url.cc | 46 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/node_url.cc b/src/node_url.cc index e3f860ef311677..82fe8078a8db0a 100644 --- a/src/node_url.cc +++ b/src/node_url.cc @@ -1429,7 +1429,7 @@ void URL::Parse(const char* input, const char ch = p < end ? p[0] : kEOL; bool special = (url->flags & URL_FLAGS_SPECIAL); bool cannot_be_base; - const bool special_back_slash = (special && ch == '\\'); + bool special_back_slash = (special && ch == '\\'); switch (state) { case kSchemeStart: @@ -1477,6 +1477,7 @@ void URL::Parse(const char* input, url->flags &= ~URL_FLAGS_SPECIAL; special = false; } + special_back_slash = (special && ch == '\\'); buffer.clear(); if (has_state_override) return; @@ -1521,6 +1522,7 @@ void URL::Parse(const char* input, url->flags &= ~URL_FLAGS_SPECIAL; special = false; } + special_back_slash = (special && ch == '\\'); if (base->flags & URL_FLAGS_HAS_PATH) { url->flags |= URL_FLAGS_HAS_PATH; url->path = base->path; @@ -1544,6 +1546,7 @@ void URL::Parse(const char* input, url->flags |= URL_FLAGS_SPECIAL; special = true; state = kFile; + special_back_slash = (special && ch == '\\'); continue; } break; @@ -1573,6 +1576,7 @@ void URL::Parse(const char* input, url->flags &= ~URL_FLAGS_SPECIAL; special = false; } + special_back_slash = (special && ch == '\\'); switch (ch) { case kEOL: if (base->flags & URL_FLAGS_HAS_USERNAME) { diff --git a/test/cctest/test_url.cc b/test/cctest/test_url.cc index 686ebcd11b301e..aa2b380dd11eda 100644 --- a/test/cctest/test_url.cc +++ b/test/cctest/test_url.cc @@ -81,6 +81,52 @@ TEST_F(URLTest, Base3) { EXPECT_EQ(simple.path(), "/baz"); } +TEST_F(URLTest, Base4) { + const char* input = "\\x"; + const char* base = "http://example.org/foo/bar"; + + URL simple(input, strlen(input), base, strlen(base)); + + EXPECT_FALSE(simple.flags() & URL_FLAGS_FAILED); + EXPECT_EQ(simple.protocol(), "http:"); + EXPECT_EQ(simple.host(), "example.org"); + EXPECT_EQ(simple.path(), "/x"); +} + +TEST_F(URLTest, Base5) { + const char* input = "/x"; + const char* base = "http://example.org/foo/bar"; + + URL simple(input, strlen(input), base, strlen(base)); + + EXPECT_FALSE(simple.flags() & URL_FLAGS_FAILED); + EXPECT_EQ(simple.protocol(), "http:"); + EXPECT_EQ(simple.host(), "example.org"); + EXPECT_EQ(simple.path(), "/x"); +} + +TEST_F(URLTest, Base6) { + const char* input = "\\\\x"; + const char* base = "http://example.org/foo/bar"; + + URL simple(input, strlen(input), base, strlen(base)); + + EXPECT_FALSE(simple.flags() & URL_FLAGS_FAILED); + EXPECT_EQ(simple.protocol(), "http:"); + EXPECT_EQ(simple.host(), "x"); +} + +TEST_F(URLTest, Base7) { + const char* input = "//x"; + const char* base = "http://example.org/foo/bar"; + + URL simple(input, strlen(input), base, strlen(base)); + + EXPECT_FALSE(simple.flags() & URL_FLAGS_FAILED); + EXPECT_EQ(simple.protocol(), "http:"); + EXPECT_EQ(simple.host(), "x"); +} + TEST_F(URLTest, TruncatedAfterProtocol) { char input[2] = { 'q', ':' }; URL simple(input, sizeof(input));