Title: [209857] trunk
Revision
209857
Author
achristen...@apple.com
Date
2016-12-15 00:19:47 -0800 (Thu, 15 Dec 2016)

Log Message

REGRESSION (r208902) Null pointer dereference in wkIsPublicSuffix
https://bugs.webkit.org/show_bug.cgi?id=165885
<rdar://problem/29476917>

Reviewed by Darin Adler.

Source/WebCore:

wkIsPublicSuffix crashes if you give it a nil NSString*.
This was possible before IDN2008 adoption, but it's more common now
because domains like "r4---asdf.example.com" fail in uidna_nameToASCII but not in uidna_IDNToASCII.
decodeHostName can return a nil NSString.  We can't use it unchecked, so instead we use an algorithm that allows
for decoding failures while still finding top privately controlled domains correctly.

Tested by new API tests which crash before this change and verify the behavior matches behavior before r208902.

* platform/mac/PublicSuffixMac.mm:
(WebCore::isPublicSuffix):
(WebCore::topPrivatelyControlledDomain):

Tools:

* TestWebKitAPI/Tests/WebCore/URLParser.cpp:
(TestWebKitAPI::utf16String): Deleted.
* TestWebKitAPI/Tests/mac/PublicSuffix.mm:
(TestWebKitAPI::TEST_F):
* TestWebKitAPI/WTFStringUtilities.h:
(utf16String):
Moved from URLParser to share with other tests.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (209856 => 209857)


--- trunk/Source/WebCore/ChangeLog	2016-12-15 08:17:17 UTC (rev 209856)
+++ trunk/Source/WebCore/ChangeLog	2016-12-15 08:19:47 UTC (rev 209857)
@@ -1,5 +1,25 @@
 2016-12-15  Alex Christensen  <achristen...@webkit.org>
 
+        REGRESSION (r208902) Null pointer dereference in wkIsPublicSuffix
+        https://bugs.webkit.org/show_bug.cgi?id=165885
+        <rdar://problem/29476917>
+
+        Reviewed by Darin Adler.
+
+        wkIsPublicSuffix crashes if you give it a nil NSString*.
+        This was possible before IDN2008 adoption, but it's more common now
+        because domains like "r4---asdf.example.com" fail in uidna_nameToASCII but not in uidna_IDNToASCII.
+        decodeHostName can return a nil NSString.  We can't use it unchecked, so instead we use an algorithm that allows
+        for decoding failures while still finding top privately controlled domains correctly.
+
+        Tested by new API tests which crash before this change and verify the behavior matches behavior before r208902.
+
+        * platform/mac/PublicSuffixMac.mm:
+        (WebCore::isPublicSuffix):
+        (WebCore::topPrivatelyControlledDomain):
+
+2016-12-15  Alex Christensen  <achristen...@webkit.org>
+
         Fix Windows WebGL build after r209832
 
         * CMakeLists.txt:

Modified: trunk/Source/WebCore/platform/mac/PublicSuffixMac.mm (209856 => 209857)


--- trunk/Source/WebCore/platform/mac/PublicSuffixMac.mm	2016-12-15 08:17:17 UTC (rev 209856)
+++ trunk/Source/WebCore/platform/mac/PublicSuffixMac.mm	2016-12-15 08:19:47 UTC (rev 209857)
@@ -39,39 +39,21 @@
 
 bool isPublicSuffix(const String& domain)
 {
-    return wkIsPublicSuffix(decodeHostName(domain));
+    NSString *host = decodeHostName(domain);
+    return host && wkIsPublicSuffix(host);
 }
 
 String topPrivatelyControlledDomain(const String& domain)
 {
-    if (domain.isNull() || domain.isEmpty())
-        return String();
-
-    NSString *host = decodeHostName(domain);
-
-    if ([host _web_looksLikeIPAddress])
+    if ([domain _web_looksLikeIPAddress])
         return domain;
 
-    // Match the longest possible suffix.
-    bool hasTopLevelDomain = false;
-    NSCharacterSet *dot = [[NSCharacterSet characterSetWithCharactersInString:@"."] retain];
-    NSRange nextDot = NSMakeRange(0, [host length]);
-    for (NSRange previousDot = [host rangeOfCharacterFromSet:dot]; previousDot.location != NSNotFound; nextDot = previousDot, previousDot = [host rangeOfCharacterFromSet:dot options:0 range:NSMakeRange(previousDot.location + previousDot.length, [host length] - (previousDot.location + previousDot.length))]) {
-        NSString *substring = [host substringFromIndex:previousDot.location + previousDot.length];
-        if (wkIsPublicSuffix(substring)) {
-            hasTopLevelDomain = true;
-            break;
-        }
+    size_t separatorPosition;
+    for (unsigned labelStart = 0; (separatorPosition = domain.find('.', labelStart)) != notFound; labelStart = separatorPosition + 1) {
+        if (isPublicSuffix(domain.substring(separatorPosition + 1)))
+            return domain.substring(labelStart);
     }
-
-    [dot release];
-    if (!hasTopLevelDomain)
-        return String();
-
-    if (!nextDot.location)
-        return domain;
-
-    return encodeHostName([host substringFromIndex:nextDot.location + nextDot.length]);
+    return String();
 }
 
 }

Modified: trunk/Tools/ChangeLog (209856 => 209857)


--- trunk/Tools/ChangeLog	2016-12-15 08:17:17 UTC (rev 209856)
+++ trunk/Tools/ChangeLog	2016-12-15 08:19:47 UTC (rev 209857)
@@ -1,3 +1,19 @@
+2016-12-15  Alex Christensen  <achristen...@webkit.org>
+
+        REGRESSION (r208902) Null pointer dereference in wkIsPublicSuffix
+        https://bugs.webkit.org/show_bug.cgi?id=165885
+        <rdar://problem/29476917>
+
+        Reviewed by Darin Adler.
+
+        * TestWebKitAPI/Tests/WebCore/URLParser.cpp:
+        (TestWebKitAPI::utf16String): Deleted.
+        * TestWebKitAPI/Tests/mac/PublicSuffix.mm:
+        (TestWebKitAPI::TEST_F):
+        * TestWebKitAPI/WTFStringUtilities.h:
+        (utf16String):
+        Moved from URLParser to share with other tests.
+
 2016-12-14  Ryosuke Niwa  <rn...@webkit.org>
 
         iOS: An element with tabindex is not focusable unless there is no mouse event handler

Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp (209856 => 209857)


--- trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp	2016-12-15 08:17:17 UTC (rev 209856)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp	2016-12-15 08:19:47 UTC (rev 209857)
@@ -24,6 +24,7 @@
  */
 
 #include "config.h"
+#include "WTFStringUtilities.h"
 #include <WebCore/URLParser.h>
 #include <wtf/MainThread.h>
 #include <wtf/text/StringBuilder.h>
@@ -325,16 +326,6 @@
     }
 }
 
-template<size_t length>
-static String utf16String(const char16_t (&url)[length])
-{
-    StringBuilder builder;
-    builder.reserveCapacity(length - 1);
-    for (size_t i = 0; i < length - 1; ++i)
-        builder.append(static_cast<UChar>(url[i]));
-    return builder.toString();
-}
-
 TEST_F(URLParserTest, Basic)
 {
     checkURL("http://user:p...@webkit.org:123/path?query#fragment", {"http", "user", "pass", "webkit.org", 123, "/path", "query", "fragment", "http://user:p...@webkit.org:123/path?query#fragment"});

Modified: trunk/Tools/TestWebKitAPI/Tests/mac/PublicSuffix.mm (209856 => 209857)


--- trunk/Tools/TestWebKitAPI/Tests/mac/PublicSuffix.mm	2016-12-15 08:17:17 UTC (rev 209856)
+++ trunk/Tools/TestWebKitAPI/Tests/mac/PublicSuffix.mm	2016-12-15 08:19:47 UTC (rev 209857)
@@ -44,6 +44,8 @@
     }
 };
 
+const char16_t bidirectionalDomain[28] = u"bidirectional\u0786\u07AE\u0782\u07B0\u0795\u07A9\u0793\u07A6\u0783\u07AA.com";
+
 TEST_F(PublicSuffix, IsPublicSuffix)
 {
     EXPECT_TRUE(isPublicSuffix("com"));
@@ -55,10 +57,17 @@
     EXPECT_FALSE(isPublicSuffix("bl.uk"));
     EXPECT_FALSE(isPublicSuffix("test.co.uk"));
     EXPECT_TRUE(isPublicSuffix("xn--zf0ao64a.tw"));
+    EXPECT_FALSE(isPublicSuffix("r4---asdf.test.com"));
+    EXPECT_FALSE(isPublicSuffix(utf16String(bidirectionalDomain)));
+    EXPECT_TRUE(isPublicSuffix(utf16String(u"\u6803\u6728.jp")));
 }
 
 TEST_F(PublicSuffix, TopPrivatelyControlledDomain)
 {
+    EXPECT_EQ(utf16String(u"\u6803\u6728.jp"), topPrivatelyControlledDomain(utf16String(u"\u6803\u6728.jp")));
+    EXPECT_EQ(String(utf16String(u"example.\u6803\u6728.jp")), topPrivatelyControlledDomain(utf16String(u"example.\u6803\u6728.jp")));
+    EXPECT_EQ(String(), topPrivatelyControlledDomain(String()));
+    EXPECT_EQ(String(), topPrivatelyControlledDomain(""));
     EXPECT_EQ(String("test.com"), topPrivatelyControlledDomain("test.com"));
     EXPECT_EQ(String("test.com"), topPrivatelyControlledDomain("com.test.com"));
     EXPECT_EQ(String("test.com"), topPrivatelyControlledDomain("subdomain.test.com"));
@@ -72,6 +81,11 @@
     EXPECT_EQ(String("127.0.0.1"), topPrivatelyControlledDomain("127.0.0.1"));
     EXPECT_EQ(String(), topPrivatelyControlledDomain("1"));
     EXPECT_EQ(String(), topPrivatelyControlledDomain("com"));
+    EXPECT_EQ(String("test.com"), topPrivatelyControlledDomain("r4---asdf.test.com"));
+    EXPECT_EQ(String("r4---asdf.com"), topPrivatelyControlledDomain("r4---asdf.com"));
+    EXPECT_EQ(String(), topPrivatelyControlledDomain("r4---asdf"));
+    EXPECT_EQ(utf16String(bidirectionalDomain), utf16String(bidirectionalDomain));
+    
 }
 
 }

Modified: trunk/Tools/TestWebKitAPI/WTFStringUtilities.h (209856 => 209857)


--- trunk/Tools/TestWebKitAPI/WTFStringUtilities.h	2016-12-15 08:17:17 UTC (rev 209856)
+++ trunk/Tools/TestWebKitAPI/WTFStringUtilities.h	2016-12-15 08:19:47 UTC (rev 209857)
@@ -28,8 +28,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef WTFStringUtilities_h
-#define WTFStringUtilities_h
+#pragma once
 
 #include <wtf/Assertions.h>
 #include <wtf/text/CString.h>
@@ -45,4 +44,12 @@
 
 }
 
-#endif // WTFStringUtilities_h
+template<size_t length>
+static String utf16String(const char16_t (&url)[length])
+{
+    StringBuilder builder;
+    builder.reserveCapacity(length - 1);
+    for (size_t i = 0; i < length - 1; ++i)
+        builder.append(static_cast<UChar>(url[i]));
+    return builder.toString();
+}
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to