summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsbell <jsbell@chromium.org>2016-03-02 13:20:04 -0800
committerCommit bot <commit-bot@chromium.org>2016-03-02 21:21:26 +0000
commita2f22b53a2efed11ef0171cea00e045c1cdc2e46 (patch)
tree1cdc6b89c6431a87c3dd0caf99b1977af562608d
parent1535512d6b044044e58111011a48ffd07194b49c (diff)
downloadchromium_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}
-rw-r--r--content/common/database_identifier_unittest.cc10
-rw-r--r--storage/common/database/database_identifier.cc41
-rw-r--r--third_party/WebKit/Source/platform/weborigin/DatabaseIdentifier.cpp44
-rw-r--r--third_party/WebKit/Source/platform/weborigin/DatabaseIdentifierTest.cpp3
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, ":", "_", &copy);
+ 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, "_", ":", &copy);
+ 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) {