diff options
author | jsbell <jsbell@chromium.org> | 2016-03-02 13:20:04 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-02 21:21:26 +0000 |
commit | a2f22b53a2efed11ef0171cea00e045c1cdc2e46 (patch) | |
tree | 1cdc6b89c6431a87c3dd0caf99b1977af562608d | |
parent | 1535512d6b044044e58111011a48ffd07194b49c (diff) | |
download | chromium_src-a2f22b53a2efed11ef0171cea00e045c1cdc2e46.zip chromium_src-a2f22b53a2efed11ef0171cea00e045c1cdc2e46.tar.gz chromium_src-a2f22b53a2efed11ef0171cea00e045c1cdc2e46.tar.bz2 |
Add IPV6 URL support to DatabaseIdentifiers
... and add "bad character" checks to the Blink impl.
BUG=568467
R=mkwst@chromium.org,michaeln@chromium.org
Review URL: https://codereview.chromium.org/1721973002
Cr-Commit-Position: refs/heads/master@{#378835}
4 files changed, 93 insertions, 5 deletions
diff --git a/content/common/database_identifier_unittest.cc b/content/common/database_identifier_unittest.cc index f866b76..eb94b4a 100644 --- a/content/common/database_identifier_unittest.cc +++ b/content/common/database_identifier_unittest.cc @@ -35,6 +35,9 @@ TEST(DatabaseIdentifierTest, CreateIdentifierFromOrigin) { {"data:", "__0"}, {"about:blank", "__0"}, {"non-standard://foobar.com", "__0"}, + {"http://[::1]:8080", "http_[__1]_8080"}, + {"http://[3ffe:2a00:100:7031::1]", "http_[3ffe_2a00_100_7031__1]_0"}, + {"http://[::ffff:8190:3426]", "http_[__ffff_8190_3426]_0"}, }; for (size_t i = 0; i < arraysize(cases); ++i) { @@ -203,6 +206,13 @@ TEST(DatabaseIdentifierTest, ExtractOriginDataFromIdentifier) { {"http_dot.com_0", "http", "dot.com", 0, GURL("http://dot.com"), false}, {"http_escaped%3Dfun.com_0", "http", "escaped%3dfun.com", 0, GURL("http://escaped%3dfun.com"), false}, + {"http_[__1]_8080", + "http", "[::1]", 8080, GURL("http://[::1]:8080"), false}, + {"http_[3ffe_2a00_100_7031__1]_0", + "http", "[3ffe:2a00:100:7031::1]", 0, + GURL("http://[3ffe:2a00:100:7031::1]"), false}, + {"http_[__ffff_8190_3426]_0", + "http", "[::ffff:8190:3426]", 0, GURL("http://[::ffff:8190:3426]"), false}, }; for (size_t i = 0; i < arraysize(valid_cases); ++i) { diff --git a/storage/common/database/database_identifier.cc b/storage/common/database/database_identifier.cc index 2c1aa55..1722d31 100644 --- a/storage/common/database/database_identifier.cc +++ b/storage/common/database/database_identifier.cc @@ -13,6 +13,38 @@ namespace storage { +namespace { + + +// If the passed string is of the form "[1::2:3]", returns "[1__2_3]". +std::string EscapeIPv6Hostname(const std::string& hostname) { + // Shortest IPv6 hostname would be "[::1]". + if (hostname.length() < 5 || hostname.front() != '[' || + hostname.back() != ']') + return hostname; + + // Should be canonicalized before it gets this far. + // i.e. "[::ffff:8190:3426]" not "[::FFFF:129.144.52.38]" + DCHECK(base::ContainsOnlyChars(hostname, "[]:0123456789abcdef")); + + std::string copy = hostname; + base::ReplaceChars(hostname, ":", "_", ©); + return copy; +} + +// If the passed string is of the form "[1__2_3]", returns "[1::2:3]". +std::string UnescapeIPv6Hostname(const std::string& hostname) { + if (hostname.length() < 5 || hostname.front() != '[' || + hostname.back() != ']') + return hostname; + + std::string copy = hostname; + base::ReplaceChars(hostname, "_", ":", ©); + return copy; +} + +} // namespace + // static std::string GetIdentifierFromOrigin(const GURL& origin) { return DatabaseIdentifier::CreateFromOrigin(origin).ToString(); @@ -93,8 +125,10 @@ DatabaseIdentifier DatabaseIdentifier::Parse(const std::string& identifier) { if (!base::StringToInt(port_str, &port) || port < 0 || port >= 1 << 16) return DatabaseIdentifier(); - std::string hostname(identifier.data() + first_underscore + 1, - last_underscore - first_underscore - 1); + std::string hostname = + UnescapeIPv6Hostname(std::string(identifier.data() + first_underscore + 1, + last_underscore - first_underscore - 1)); + GURL url(scheme + "://" + hostname + "/"); if (!url.IsStandard()) @@ -132,7 +166,8 @@ std::string DatabaseIdentifier::ToString() const { return "file__0"; if (is_unique_) return "__0"; - return scheme_ + "_" + hostname_ + "_" + base::IntToString(port_); + return scheme_ + "_" + EscapeIPv6Hostname(hostname_) + "_" + + base::IntToString(port_); } GURL DatabaseIdentifier::ToOrigin() const { diff --git a/third_party/WebKit/Source/platform/weborigin/DatabaseIdentifier.cpp b/third_party/WebKit/Source/platform/weborigin/DatabaseIdentifier.cpp index e0ea66e..f71b0ac 100644 --- a/third_party/WebKit/Source/platform/weborigin/DatabaseIdentifier.cpp +++ b/third_party/WebKit/Source/platform/weborigin/DatabaseIdentifier.cpp @@ -40,6 +40,36 @@ namespace blink { +namespace { + +String escapeIPv6Hostname(const String& hostname) +{ + // Shortest IPv6 hostname would be "[::1]". + if (hostname.length() < 5 || hostname[0] != '[' || hostname[hostname.length() - 1] != ']') + return hostname; + + // Should be canonicalized before it gets this far. + // i.e. "[::ffff:8190:3426]" not "[::FFFF:129.144.52.38]" + ASSERT(!hostname.contains('.')); + ASSERT(hostname == hostname.lower()); + + String copy = hostname; + copy.replace(':', '_'); + return copy; +} + +String unescapeIPv6Hostname(const String& hostname) +{ + if (hostname.length() < 5 || hostname[0] != '[' || hostname[hostname.length() - 1] != ']') + return hostname; + + String copy = hostname; + copy.replace('_', ':'); + return copy; +} + +} // namespace + const int maxAllowedPort = 65535; static const char separatorCharacter = '_'; @@ -49,6 +79,16 @@ PassRefPtr<SecurityOrigin> createSecurityOriginFromDatabaseIdentifier(const Stri if (!databaseIdentifier.containsOnlyASCII()) return SecurityOrigin::createUnique(); + // Match restrictions in storage/common/database/database_identifier.cc + // TODO(jsbell): Eliminate duplicate implementations. + if (databaseIdentifier.contains("..")) + return SecurityOrigin::createUnique(); + char forbidden[] = {'\\', '/', ':', '\0'}; + for (auto c : forbidden) { + if (databaseIdentifier.contains(c)) + return SecurityOrigin::createUnique(); + } + // Make sure there's a first separator size_t separator1 = databaseIdentifier.find(separatorCharacter); if (separator1 == kNotFound) @@ -76,7 +116,7 @@ PassRefPtr<SecurityOrigin> createSecurityOriginFromDatabaseIdentifier(const Stri // Split out the 3 sections of data String protocol = databaseIdentifier.substring(0, separator1); - String host = databaseIdentifier.substring(separator1 + 1, separator2 - separator1 - 1); + String host = unescapeIPv6Hostname(databaseIdentifier.substring(separator1 + 1, separator2 - separator1 - 1)); // Make sure the components match their canonical representation so we are sure we're round tripping correctly. KURL url(KURL(), protocol + "://" + host + ":" + String::number(port) + "/"); @@ -89,7 +129,7 @@ PassRefPtr<SecurityOrigin> createSecurityOriginFromDatabaseIdentifier(const Stri String createDatabaseIdentifierFromSecurityOrigin(const SecurityOrigin* securityOrigin) { String separatorString(&separatorCharacter, 1); - return securityOrigin->protocol() + separatorString + securityOrigin->host() + separatorString + String::number(securityOrigin->port()); + return securityOrigin->protocol() + separatorString + escapeIPv6Hostname(securityOrigin->host()) + separatorString + String::number(securityOrigin->port()); } } // namespace blink diff --git a/third_party/WebKit/Source/platform/weborigin/DatabaseIdentifierTest.cpp b/third_party/WebKit/Source/platform/weborigin/DatabaseIdentifierTest.cpp index 01bc1cf..feeb466 100644 --- a/third_party/WebKit/Source/platform/weborigin/DatabaseIdentifierTest.cpp +++ b/third_party/WebKit/Source/platform/weborigin/DatabaseIdentifierTest.cpp @@ -57,6 +57,9 @@ TEST(DatabaseIdentifierTest, CreateIdentifierFromSecurityOrigin) {"data", "", 0, "__0"}, {"about", "blank", 0, "__0"}, {"non-standard", "foobar.com", 0, "non-standard__0"}, + {"http", "[::1]", 0, "http_[__1]_0"}, + {"http", "[3ffe:2a00:100:7031::1]", 0, "http_[3ffe_2a00_100_7031__1]_0"}, + {"http", "[::ffff:8190:3426]", 0, "http_[__ffff_8190_3426]_0"}, }; for (size_t i = 0; i < WTF_ARRAY_LENGTH(cases); ++i) { |