Skip to content

Commit

Permalink
src: fix leading backslash bug in URL
Browse files Browse the repository at this point in the history
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: #36559

PR-URL: #36613
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: Daijiro Wachi <[email protected]>
Reviewed-By: James M Snell <[email protected]>
  • Loading branch information
RaisinTen authored and danielleadams committed Jan 12, 2021
1 parent edf8c6d commit a53997e
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 1 deletion.
6 changes: 5 additions & 1 deletion src/node_url.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
46 changes: 46 additions & 0 deletions test/cctest/test_url.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down

0 comments on commit a53997e

Please sign in to comment.