Modified: trunk/Source/WebCore/platform/URLParser.cpp (204700 => 204701)
--- trunk/Source/WebCore/platform/URLParser.cpp 2016-08-22 04:04:54 UTC (rev 204700)
+++ trunk/Source/WebCore/platform/URLParser.cpp 2016-08-22 05:42:12 UTC (rev 204701)
@@ -28,6 +28,7 @@
#include "Logging.h"
#include "NotImplemented.h"
+#include <array>
#include <wtf/text/StringBuilder.h>
namespace WebCore {
@@ -394,11 +395,139 @@
m_authorityOrHostBuffer.clear();
}
+static void serializeIPv4(uint32_t address, StringBuilder& buffer)
+{
+ buffer.appendNumber(address >> 24);
+ buffer.append('.');
+ buffer.appendNumber((address >> 16) & 0xFF);
+ buffer.append('.');
+ buffer.appendNumber((address >> 8) & 0xFF);
+ buffer.append('.');
+ buffer.appendNumber(address & 0xFF);
+}
+
+static Optional<uint32_t> parseIPv4Number(StringView::CodePoints::Iterator& iterator, const StringView::CodePoints::Iterator& end)
+{
+ // FIXME: Check for overflow.
+ enum class State : uint8_t {
+ UnknownBase,
+ Decimal,
+ OctalOrHex,
+ Octal,
+ Hex,
+ };
+ State state = State::UnknownBase;
+ uint32_t value = 0;
+ while (iterator != end) {
+ if (*iterator == '.') {
+ ++iterator;
+ return value;
+ }
+ switch (state) {
+ case State::UnknownBase:
+ if (*iterator == '0') {
+ ++iterator;
+ state = State::OctalOrHex;
+ break;
+ }
+ state = State::Decimal;
+ break;
+ case State::OctalOrHex:
+ if (*iterator == 'x' || *iterator == 'X') {
+ ++iterator;
+ state = State::Hex;
+ break;
+ }
+ state = State::Octal;
+ break;
+ case State::Decimal:
+ if (*iterator < '0' || *iterator > '9')
+ return Nullopt;
+ value *= 10;
+ value += *iterator - '0';
+ ++iterator;
+ break;
+ case State::Octal:
+ if (*iterator < '0' || *iterator > '7')
+ return Nullopt;
+ value *= 8;
+ value += *iterator - '0';
+ ++iterator;
+ break;
+ case State::Hex:
+ if (!isASCIIHexDigit(*iterator))
+ return Nullopt;
+ value *= 16;
+ value += toASCIIHexValue(*iterator);
+ ++iterator;
+ break;
+ }
+ }
+ return value;
+}
+
+static uint64_t pow256(size_t exponent)
+{
+ RELEASE_ASSERT(exponent <= 4);
+ uint64_t values[5] = {1, 256, 256 * 256, 256 * 256 * 256, 256ull * 256 * 256 * 256 };
+ return values[exponent];
+}
+
+static Optional<uint32_t> parseIPv4Host(StringView::CodePoints::Iterator iterator, const StringView::CodePoints::Iterator& end)
+{
+ Vector<uint32_t, 4> items;
+ items.reserveInitialCapacity(4);
+ while (iterator != end) {
+ if (items.size() >= 4)
+ return Nullopt;
+ if (auto item = parseIPv4Number(iterator, end))
+ items.append(item.value());
+ else
+ return Nullopt;
+ }
+ if (!items.size() || items.size() > 4)
+ return Nullopt;
+ for (size_t i = 0; i < items.size() - 2; i++) {
+ if (items[i] > 255)
+ return Nullopt;
+ }
+ if (items[items.size() - 1] >= pow256(5 - items.size()))
+ return Nullopt;
+ for (auto item : items) {
+ if (item > 255)
+ return Nullopt;
+ }
+ uint32_t ipv4 = items.takeLast();
+ for (size_t counter = 0; counter < items.size(); ++counter)
+ ipv4 += items[counter] * pow256(3 - counter);
+ return ipv4;
+}
+
+static Optional<std::array<uint16_t, 8>> parseIPv6Host(StringView::CodePoints::Iterator, StringView::CodePoints::Iterator)
+{
+ notImplemented();
+ return Nullopt;
+}
+
void URLParser::hostEndReached()
{
auto codePoints = StringView(m_authorityOrHostBuffer.toString()).codePoints();
auto iterator = codePoints.begin();
auto end = codePoints.end();
+ if (iterator == end)
+ return;
+ if (*iterator == '[') {
+ ++iterator;
+ parseIPv6Host(iterator, end);
+ return;
+ }
+ if (auto address = parseIPv4Host(iterator, end)) {
+ serializeIPv4(address.value(), m_buffer);
+ m_url.m_hostEnd = m_buffer.length();
+ // FIXME: Handle the port correctly.
+ m_url.m_portEnd = m_buffer.length();
+ return;
+ }
for (; iterator != end; ++iterator) {
if (*iterator == ':') {
++iterator;
Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp (204700 => 204701)
--- trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp 2016-08-22 04:04:54 UTC (rev 204700)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp 2016-08-22 05:42:12 UTC (rev 204701)
@@ -88,8 +88,47 @@
checkURL("http://user:[email protected]:123", {"http", "user", "pass", "webkit.org", 123, "/", "", "", "http://user:[email protected]:123/"});
checkURL("http://user:[email protected]", {"http", "user", "pass", "webkit.org", 0, "/", "", "", "http://user:[email protected]/"});
checkURL("http://webkit.org", {"http", "", "", "webkit.org", 0, "/", "", "", "http://webkit.org/"});
+ checkURL("http://127.0.0.1", {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"});
}
+static void checkURLDifferences(const String& urlString, const ExpectedParts& partsNew, const ExpectedParts& partsOld)
+{
+ URLParser parser;
+ auto url = ""
+ EXPECT_STREQ(s(partsNew.protocol), s(url->protocol()));
+ EXPECT_STREQ(s(partsNew.user), s(url->user()));
+ EXPECT_STREQ(s(partsNew.password), s(url->pass()));
+ EXPECT_STREQ(s(partsNew.host), s(url->host()));
+ EXPECT_EQ(partsNew.port, url->port());
+ EXPECT_STREQ(s(partsNew.path), s(url->path()));
+ EXPECT_STREQ(s(partsNew.query), s(url->query()));
+ EXPECT_STREQ(s(partsNew.fragment), s(url->fragmentIdentifier()));
+ EXPECT_STREQ(s(partsNew.string), s(url->string()));
+
+ auto oldURL = URL(URL(), urlString);
+ EXPECT_STREQ(s(partsOld.protocol), s(oldURL.protocol()));
+ EXPECT_STREQ(s(partsOld.user), s(oldURL.user()));
+ EXPECT_STREQ(s(partsOld.password), s(oldURL.pass()));
+ EXPECT_STREQ(s(partsOld.host), s(oldURL.host()));
+ EXPECT_EQ(partsOld.port, oldURL.port());
+ EXPECT_STREQ(s(partsOld.path), s(oldURL.path()));
+ EXPECT_STREQ(s(partsOld.query), s(oldURL.query()));
+ EXPECT_STREQ(s(partsOld.fragment), s(oldURL.fragmentIdentifier()));
+ EXPECT_STREQ(s(partsOld.string), s(oldURL.string()));
+
+ EXPECT_FALSE(URLParser::allValuesEqual(url.value(), oldURL));
+}
+
+TEST_F(URLParserTest, ParserDifferences)
+{
+ checkURLDifferences("http://127.0.1",
+ {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"},
+ {"http", "", "", "127.0.1", 0, "/", "", "", "http://127.0.1/"});
+ checkURLDifferences("http://011.11.0X11.0x011",
+ {"http", "", "", "9.11.17.17", 0, "/", "", "", "http://9.11.17.17/"},
+ {"http", "", "", "011.11.0x11.0x011", 0, "/", "", "", "http://011.11.0x11.0x011/"});
+}
+
static void shouldFail(const String& urlString)
{
URLParser parser;