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 <rtrott@gmail.com>
Reviewed-By: Daijiro Wachi <daijiro.wachi@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
raisinten 2020-12-23 20:29:39 +05:30 committed by James M Snell
parent 6ab768ea4a
commit b8c15c7413
No known key found for this signature in database
GPG Key ID: 7341B15C070877AC
2 changed files with 51 additions and 1 deletions

View File

@ -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) {

View File

@ -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));