Title: [206842] trunk
Revision
206842
Author
achristen...@apple.com
Date
2016-10-05 19:35:12 -0700 (Wed, 05 Oct 2016)

Log Message

URLParser should parse IPv4 addresses as the last two pieces of an IPv6 address
https://bugs.webkit.org/show_bug.cgi?id=162991

Reviewed by Saam Barati.

Source/WebCore:

The last 32 bits of an IPv6 address can be written in the form of an IPv4 address,
but the syntax is stricter than if it were just an IPv4 address.  There must be 4 pieces,
and each piece must be decimal (no octal or hex allowed).  These should serialize to
regular hex IPv6 addresses.

Covered by new API tests.

* platform/URLParser.cpp:
(WebCore::URLParser::parseIPv4Piece):
(WebCore::URLParser::parseIPv4Host):
(WebCore::URLParser::parseIPv4PieceInsideIPv6):
(WebCore::URLParser::parseIPv4AddressInsideIPv6):
(WebCore::URLParser::parseIPv6Host):
(WebCore::URLParser::parseIPv4Number): Deleted.
* platform/URLParser.h:

Tools:

* TestWebKitAPI/Tests/WebCore/URLParser.cpp:
(TestWebKitAPI::TEST_F):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (206841 => 206842)


--- trunk/Source/WebCore/ChangeLog	2016-10-06 00:50:59 UTC (rev 206841)
+++ trunk/Source/WebCore/ChangeLog	2016-10-06 02:35:12 UTC (rev 206842)
@@ -1,3 +1,26 @@
+2016-10-05  Alex Christensen  <achristen...@webkit.org>
+
+        URLParser should parse IPv4 addresses as the last two pieces of an IPv6 address
+        https://bugs.webkit.org/show_bug.cgi?id=162991
+
+        Reviewed by Saam Barati.
+
+        The last 32 bits of an IPv6 address can be written in the form of an IPv4 address,
+        but the syntax is stricter than if it were just an IPv4 address.  There must be 4 pieces,
+        and each piece must be decimal (no octal or hex allowed).  These should serialize to
+        regular hex IPv6 addresses.
+
+        Covered by new API tests.
+
+        * platform/URLParser.cpp:
+        (WebCore::URLParser::parseIPv4Piece):
+        (WebCore::URLParser::parseIPv4Host):
+        (WebCore::URLParser::parseIPv4PieceInsideIPv6):
+        (WebCore::URLParser::parseIPv4AddressInsideIPv6):
+        (WebCore::URLParser::parseIPv6Host):
+        (WebCore::URLParser::parseIPv4Number): Deleted.
+        * platform/URLParser.h:
+
 2016-10-05  Myles C. Maxfield  <mmaxfi...@apple.com>
 
         Put variation fonts work behind a compile-time flag

Modified: trunk/Source/WebCore/platform/URLParser.cpp (206841 => 206842)


--- trunk/Source/WebCore/platform/URLParser.cpp	2016-10-06 00:50:59 UTC (rev 206841)
+++ trunk/Source/WebCore/platform/URLParser.cpp	2016-10-06 02:35:12 UTC (rev 206842)
@@ -2185,7 +2185,7 @@
 }
 
 template<typename CharacterType>
-Optional<uint32_t> URLParser::parseIPv4Number(CodePointIterator<CharacterType>& iterator, bool& didSeeSyntaxViolation)
+Optional<uint32_t> URLParser::parseIPv4Piece(CodePointIterator<CharacterType>& iterator, bool& didSeeSyntaxViolation)
 {
     enum class State : uint8_t {
         UnknownBase,
@@ -2284,7 +2284,7 @@
         }
         if (items.size() >= 4)
             return Nullopt;
-        if (auto item = parseIPv4Number(iterator, didSeeSyntaxViolation))
+        if (auto item = parseIPv4Piece(iterator, didSeeSyntaxViolation))
             items.append(item.value());
         else
             return Nullopt;
@@ -2323,8 +2323,63 @@
         ipv4 += items[counter] * pow256(3 - counter);
     return ipv4;
 }
-    
+
 template<typename CharacterType>
+Optional<uint32_t> URLParser::parseIPv4PieceInsideIPv6(CodePointIterator<CharacterType>& iterator)
+{
+    if (iterator.atEnd())
+        return Nullopt;
+    uint32_t piece = 0;
+    bool leadingZeros = false;
+    size_t digitCount = 0;
+    while (!iterator.atEnd()) {
+        if (!isASCIIDigit(*iterator))
+            return Nullopt;
+        ++digitCount;
+        if (!piece && *iterator == '0') {
+            if (leadingZeros)
+                return Nullopt;
+            leadingZeros = true;
+        }
+        if (!piece && *iterator == '0')
+            leadingZeros = true;
+        piece = piece * 10 + *iterator - '0';
+        if (piece > 255)
+            return Nullopt;
+        advance<CharacterType, ReportSyntaxViolation::No>(iterator);
+        if (iterator.atEnd())
+            break;
+        if (*iterator == '.')
+            break;
+    }
+    if (piece && leadingZeros)
+        return Nullopt;
+    return piece;
+}
+
+template<typename CharacterType>
+Optional<URLParser::IPv4Address> URLParser::parseIPv4AddressInsideIPv6(CodePointIterator<CharacterType> iterator)
+{
+    IPv4Address address = 0;
+    for (size_t i = 0; i < 4; ++i) {
+        if (Optional<uint32_t> piece = parseIPv4PieceInsideIPv6(iterator))
+            address = (address << 8) + piece.value();
+        else
+            return Nullopt;
+        if (i < 3) {
+            if (iterator.atEnd())
+                return Nullopt;
+            if (*iterator != '.')
+                return Nullopt;
+            advance<CharacterType, ReportSyntaxViolation::No>(iterator);
+        } else if (!iterator.atEnd())
+            return Nullopt;
+    }
+    ASSERT(iterator.atEnd());
+    return address;
+}
+
+template<typename CharacterType>
 Optional<URLParser::IPv6Address> URLParser::parseIPv6Host(CodePointIterator<CharacterType> c)
 {
     ASSERT(*c == '[');
@@ -2359,6 +2414,17 @@
             compressPointer = piecePointer;
             continue;
         }
+        if (piecePointer == 6 || (compressPointer && piecePointer < 6)) {
+            if (Optional<IPv4Address> ipv4Address = parseIPv4AddressInsideIPv6(c)) {
+                if (compressPointer && piecePointer == 5)
+                    return Nullopt;
+                syntaxViolation(hostBegin);
+                address[piecePointer++] = ipv4Address.value() >> 16;
+                address[piecePointer++] = ipv4Address.value() & 0xFFFF;
+                c = { };
+                break;
+            }
+        }
         uint16_t value = 0;
         size_t length = 0;
         bool leadingZeros = false;
@@ -2386,40 +2452,9 @@
         advance(c, hostBegin);
     }
     
-    if (!c.atEnd()) {
-        if (piecePointer > 6)
-            return Nullopt;
-        size_t dotsSeen = 0;
-        while (!c.atEnd()) {
-            Optional<uint16_t> value;
-            if (!isASCIIDigit(*c))
-                return Nullopt;
-            while (isASCIIDigit(*c)) {
-                auto number = *c - '0';
-                if (!value)
-                    value = number;
-                else if (!value.value())
-                    return Nullopt;
-                else
-                    value = value.value() * 10 + number;
-                advance(c, hostBegin);
-                if (c.atEnd())
-                    return Nullopt;
-                if (value.value() > 255)
-                    return Nullopt;
-            }
-            if (dotsSeen < 3 && *c != '.')
-                return Nullopt;
-            address[piecePointer] = address[piecePointer] * 0x100 + value.valueOr(0);
-            if (dotsSeen == 1 || dotsSeen == 3)
-                piecePointer++;
-            if (!c.atEnd())
-                advance(c, hostBegin);
-            if (dotsSeen == 3 && !c.atEnd())
-                return Nullopt;
-            dotsSeen++;
-        }
-    }
+    if (!c.atEnd())
+        return Nullopt;
+    
     if (compressPointer) {
         size_t swaps = piecePointer - compressPointer.value();
         piecePointer = 7;

Modified: trunk/Source/WebCore/platform/URLParser.h (206841 => 206842)


--- trunk/Source/WebCore/platform/URLParser.h	2016-10-06 00:50:59 UTC (rev 206841)
+++ trunk/Source/WebCore/platform/URLParser.h	2016-10-06 02:35:12 UTC (rev 206842)
@@ -100,9 +100,11 @@
     using IPv4Address = uint32_t;
     void serializeIPv4(IPv4Address);
     template<typename CharacterType> Optional<IPv4Address> parseIPv4Host(CodePointIterator<CharacterType>);
-    template<typename CharacterType> Optional<uint32_t> parseIPv4Number(CodePointIterator<CharacterType>&, bool& syntaxViolation);
+    template<typename CharacterType> Optional<uint32_t> parseIPv4Piece(CodePointIterator<CharacterType>&, bool& syntaxViolation);
     using IPv6Address = std::array<uint16_t, 8>;
     template<typename CharacterType> Optional<IPv6Address> parseIPv6Host(CodePointIterator<CharacterType>);
+    template<typename CharacterType> Optional<uint32_t> parseIPv4PieceInsideIPv6(CodePointIterator<CharacterType>&);
+    template<typename CharacterType> Optional<IPv4Address> parseIPv4AddressInsideIPv6(CodePointIterator<CharacterType>);
     void serializeIPv6Piece(uint16_t piece);
     void serializeIPv6(IPv6Address);
 

Modified: trunk/Tools/ChangeLog (206841 => 206842)


--- trunk/Tools/ChangeLog	2016-10-06 00:50:59 UTC (rev 206841)
+++ trunk/Tools/ChangeLog	2016-10-06 02:35:12 UTC (rev 206842)
@@ -1,3 +1,13 @@
+2016-10-05  Alex Christensen  <achristen...@webkit.org>
+
+        URLParser should parse IPv4 addresses as the last two pieces of an IPv6 address
+        https://bugs.webkit.org/show_bug.cgi?id=162991
+
+        Reviewed by Saam Barati.
+
+        * TestWebKitAPI/Tests/WebCore/URLParser.cpp:
+        (TestWebKitAPI::TEST_F):
+
 2016-10-05  Tim Horton  <timothy_hor...@apple.com>
 
         Avoid automatically re-taking snapshots for back-forward items that were never loaded into the view

Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp (206841 => 206842)


--- trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp	2016-10-06 00:50:59 UTC (rev 206841)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp	2016-10-06 02:35:12 UTC (rev 206842)
@@ -880,6 +880,81 @@
     checkURLDifferences(utf16String(u"notspecial://H😍ßt"),
         {"notspecial", "", "", "xn--hsst-qc83c", 0, "/", "", "", "notspecial://xn--hsst-qc83c/"},
         {"notspecial", "", "", "xn--hsst-qc83c", 0, "", "", "", "notspecial://xn--hsst-qc83c"}, testTabsValueForSurrogatePairs);
+    checkURLDifferences("http://[ffff:aaaa:cccc:eeee:bbbb:dddd:255.255.255.255]/",
+        {"http", "", "", "[ffff:aaaa:cccc:eeee:bbbb:dddd:ffff:ffff]", 0, "/", "", "", "http://[ffff:aaaa:cccc:eeee:bbbb:dddd:ffff:ffff]/"},
+        {"http", "", "", "[ffff:aaaa:cccc:eeee:bbbb:dddd:255.255.255.255]", 0, "/", "", "", "http://[ffff:aaaa:cccc:eeee:bbbb:dddd:255.255.255.255]/"}, TestTabs::No);
+    checkURLDifferences("http://[::123.234.12.210]/",
+        {"http", "", "", "[::7bea:cd2]", 0, "/", "", "", "http://[::7bea:cd2]/"},
+        {"http", "", "", "[::123.234.12.210]", 0, "/", "", "", "http://[::123.234.12.210]/"});
+    checkURLDifferences("http://[::a:255.255.255.255]/",
+        {"http", "", "", "[::a:ffff:ffff]", 0, "/", "", "", "http://[::a:ffff:ffff]/"},
+        {"http", "", "", "[::a:255.255.255.255]", 0, "/", "", "", "http://[::a:255.255.255.255]/"});
+    checkURLDifferences("http://[::0.00.255.255]/",
+        {"", "", "", "", 0, "", "", "", "http://[::0.00.255.255]/"},
+        {"http", "", "", "[::0.00.255.255]", 0, "/", "", "", "http://[::0.00.255.255]/"});
+    checkURLDifferences("http://[::0.0.255.255]/",
+        {"http", "", "", "[::ffff]", 0, "/", "", "", "http://[::ffff]/"},
+        {"http", "", "", "[::0.0.255.255]", 0, "/", "", "", "http://[::0.0.255.255]/"});
+    checkURLDifferences("http://[::0:1.0.255.255]/",
+        {"http", "", "", "[::100:ffff]", 0, "/", "", "", "http://[::100:ffff]/"},
+        {"http", "", "", "[::0:1.0.255.255]", 0, "/", "", "", "http://[::0:1.0.255.255]/"});
+    checkURLDifferences("http://[::A:1.0.255.255]/",
+        {"http", "", "", "[::a:100:ffff]", 0, "/", "", "", "http://[::a:100:ffff]/"},
+        {"http", "", "", "[::a:1.0.255.255]", 0, "/", "", "", "http://[::a:1.0.255.255]/"});
+    checkURLDifferences("http://[:127.0.0.1]",
+        {"", "", "", "", 0, "", "", "", "http://[:127.0.0.1]"},
+        {"http", "", "", "[:127.0.0.1]", 0, "/", "", "", "http://[:127.0.0.1]/"});
+    checkURLDifferences("http://[127.0.0.1]",
+        {"", "", "", "", 0, "", "", "", "http://[127.0.0.1]"},
+        {"http", "", "", "[127.0.0.1]", 0, "/", "", "", "http://[127.0.0.1]/"});
+    checkURLDifferences("http://[a:b:c:d:e:f:127.0.0.1]",
+        {"http", "", "", "[a:b:c:d:e:f:7f00:1]", 0, "/", "", "", "http://[a:b:c:d:e:f:7f00:1]/"},
+        {"http", "", "", "[a:b:c:d:e:f:127.0.0.1]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.0.1]/"});
+    checkURLDifferences("http://[a:b:c:d:e:f:127.0.0.101]",
+        {"http", "", "", "[a:b:c:d:e:f:7f00:65]", 0, "/", "", "", "http://[a:b:c:d:e:f:7f00:65]/"},
+        {"http", "", "", "[a:b:c:d:e:f:127.0.0.101]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.0.101]/"});
+    checkURLDifferences("http://[::a:b:c:d:e:f:127.0.0.1]",
+        {"", "", "", "", 0, "", "", "", "http://[::a:b:c:d:e:f:127.0.0.1]"},
+        {"http", "", "", "[::a:b:c:d:e:f:127.0.0.1]", 0, "/", "", "", "http://[::a:b:c:d:e:f:127.0.0.1]/"});
+    checkURLDifferences("http://[a:b::c:d:e:f:127.0.0.1]",
+        {"", "", "", "", 0, "", "", "", "http://[a:b::c:d:e:f:127.0.0.1]"},
+        {"http", "", "", "[a:b::c:d:e:f:127.0.0.1]", 0, "/", "", "", "http://[a:b::c:d:e:f:127.0.0.1]/"});
+    checkURLDifferences("http://[a:b:c:d:e:127.0.0.1]",
+        {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:127.0.0.1]"},
+        {"http", "", "", "[a:b:c:d:e:127.0.0.1]", 0, "/", "", "", "http://[a:b:c:d:e:127.0.0.1]/"});
+    checkURLDifferences("http://[a:b:c:d:e:f:127.0.0.0.1]",
+        {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f:127.0.0.0.1]"},
+        {"http", "", "", "[a:b:c:d:e:f:127.0.0.0.1]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.0.0.1]/"});
+    checkURLDifferences("http://[a:b:c:d:e:f:127.0.1]",
+        {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f:127.0.1]"},
+        {"http", "", "", "[a:b:c:d:e:f:127.0.1]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.1]/"});
+    checkURLDifferences("http://[a:b:c:d:e:f:127.0.0.011]", // Chrome treats this as octal, Firefox and the spec fail
+        {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f:127.0.0.011]"},
+        {"http", "", "", "[a:b:c:d:e:f:127.0.0.011]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.0.011]/"});
+    checkURLDifferences("http://[a:b:c:d:e:f:127.0.00.1]",
+        {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f:127.0.00.1]"},
+        {"http", "", "", "[a:b:c:d:e:f:127.0.00.1]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.00.1]/"});
+    checkURLDifferences("http://[a:b:c:d:e:f:127.0.0.1.]",
+        {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f:127.0.0.1.]"},
+        {"http", "", "", "[a:b:c:d:e:f:127.0.0.1.]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.0.1.]/"});
+    checkURLDifferences("http://[a:b:c:d:e:f:127.0..0.1]",
+        {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f:127.0..0.1]"},
+        {"http", "", "", "[a:b:c:d:e:f:127.0..0.1]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0..0.1]/"});
+    checkURLDifferences("http://[a:b:c:d:e:f::127.0.0.1]",
+        {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f::127.0.0.1]"},
+        {"http", "", "", "[a:b:c:d:e:f::127.0.0.1]", 0, "/", "", "", "http://[a:b:c:d:e:f::127.0.0.1]/"});
+    checkURLDifferences("http://[a:b:c:d:e::127.0.0.1]",
+        {"http", "", "", "[a:b:c:d:e:0:7f00:1]", 0, "/", "", "", "http://[a:b:c:d:e:0:7f00:1]/"},
+        {"http", "", "", "[a:b:c:d:e::127.0.0.1]", 0, "/", "", "", "http://[a:b:c:d:e::127.0.0.1]/"});
+    checkURLDifferences("http://[a:b:c:d::e:127.0.0.1]",
+        {"http", "", "", "[a:b:c:d:0:e:7f00:1]", 0, "/", "", "", "http://[a:b:c:d:0:e:7f00:1]/"},
+        {"http", "", "", "[a:b:c:d::e:127.0.0.1]", 0, "/", "", "", "http://[a:b:c:d::e:127.0.0.1]/"});
+    checkURLDifferences("http://[a:b:c:d:e:f::127.0.0.]",
+        {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f::127.0.0.]"},
+        {"http", "", "", "[a:b:c:d:e:f::127.0.0.]", 0, "/", "", "", "http://[a:b:c:d:e:f::127.0.0.]/"});
+    checkURLDifferences("http://[a:b:c:d:e:f::127.0.0.256]",
+        {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f::127.0.0.256]"},
+        {"http", "", "", "[a:b:c:d:e:f::127.0.0.256]", 0, "/", "", "", "http://[a:b:c:d:e:f::127.0.0.256]/"});
 }
 
 TEST_F(URLParserTest, DefaultPort)
@@ -1028,6 +1103,10 @@
     shouldFail("http://[1234::ab~]");
     shouldFail("http://[2001::1");
     shouldFail("http://[1:2:3:4:5:6:7:8~]/");
+    shouldFail("http://[a:b:c:d:e:f:g:127.0.0.1]");
+    shouldFail("http://[a:b:c:d:e:f:g:h:127.0.0.1]");
+    shouldFail("http://[a:b:c:d:e:f:127.0.0.0x11]"); // Chrome treats this as hex, Firefox and the spec fail
+    shouldFail("http://[a:b:c:d:e:f:127.0.-0.1]");
 }
 
 // These are in the spec but not in the web platform tests.
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to