Title: [204701] trunk
Revision
204701
Author
[email protected]
Date
2016-08-21 22:42:12 -0700 (Sun, 21 Aug 2016)

Log Message

URLParser should parse IPv4 addresses
https://bugs.webkit.org/show_bug.cgi?id=161023

Patch by Alex Christensen <[email protected]> on 2016-08-21
Reviewed by Darin Adler.

Source/WebCore:

Covered by new API tests because URLParser isn't used anywhere in WebCore yet.

* platform/URLParser.cpp:
(WebCore::URLParser::authorityEndReached):
(WebCore::serializeIPv4):
(WebCore::parseIPv4Number):
(WebCore::pow256):
(WebCore::parseIPv4Host):
(WebCore::parseIPv6Host):
(WebCore::URLParser::hostEndReached):

Tools:

* TestWebKitAPI/Tests/WebCore/URLParser.cpp:
(TestWebKitAPI::TEST_F):
(TestWebKitAPI::checkURLDifferences):
We are already getting differences between the old URL::parse and the new URLParser.
(TestWebKitAPI::shouldFail):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (204700 => 204701)


--- trunk/Source/WebCore/ChangeLog	2016-08-22 04:04:54 UTC (rev 204700)
+++ trunk/Source/WebCore/ChangeLog	2016-08-22 05:42:12 UTC (rev 204701)
@@ -1,3 +1,21 @@
+2016-08-21  Alex Christensen  <[email protected]>
+
+        URLParser should parse IPv4 addresses
+        https://bugs.webkit.org/show_bug.cgi?id=161023
+
+        Reviewed by Darin Adler.
+
+        Covered by new API tests because URLParser isn't used anywhere in WebCore yet.
+
+        * platform/URLParser.cpp:
+        (WebCore::URLParser::authorityEndReached):
+        (WebCore::serializeIPv4):
+        (WebCore::parseIPv4Number):
+        (WebCore::pow256):
+        (WebCore::parseIPv4Host):
+        (WebCore::parseIPv6Host):
+        (WebCore::URLParser::hostEndReached):
+
 2016-08-21  Sam Weinig  <[email protected]>
 
         Remove a few custom bindings

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/ChangeLog (204700 => 204701)


--- trunk/Tools/ChangeLog	2016-08-22 04:04:54 UTC (rev 204700)
+++ trunk/Tools/ChangeLog	2016-08-22 05:42:12 UTC (rev 204701)
@@ -1,3 +1,16 @@
+2016-08-21  Alex Christensen  <[email protected]>
+
+        URLParser should parse IPv4 addresses
+        https://bugs.webkit.org/show_bug.cgi?id=161023
+
+        Reviewed by Darin Adler.
+
+        * TestWebKitAPI/Tests/WebCore/URLParser.cpp:
+        (TestWebKitAPI::TEST_F):
+        (TestWebKitAPI::checkURLDifferences):
+        We are already getting differences between the old URL::parse and the new URLParser.
+        (TestWebKitAPI::shouldFail):
+
 2016-08-21  Daniel Bates  <[email protected]>
 
         prepare-ChangeLog lists unmodified functions as modified and marks functions with few changes as deleted

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;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to