Title: [263581] trunk/Source/WebCore
Revision
263581
Author
[email protected]
Date
2020-06-26 13:58:02 -0700 (Fri, 26 Jun 2020)

Log Message

Convert ContentSecurityPolicy related parsers over to using StringParsingBuffer
https://bugs.webkit.org/show_bug.cgi?id=213631

Reviewed by Darin Adler.

- Adopt StringParsingBuffer across CSP code.
- Remove UTF-16 upconversions in ContentSecurityPolicy, ContentSecurityPolicyDirectiveList,
  ContentSecurityPolicyMediaListDirective and ContentSecurityPolicySourceList.

* html/parser/ParsingUtilities.h:
(WebCore::isNotASCIISpace):
(WebCore::skipExactly):
(WebCore::characterPredicate):
(WebCore::skipUntil):
(WebCore::skipExactlyIgnoringASCIICase):
Add overloads for each helper that take a StringParsingBuffer.

* loader/ResourceCryptographicDigest.cpp:
(WebCore::parseHashAlgorithmAdvancingPosition):
Convert to use an Optional return value rather than outparameter + bool.

(WebCore::parseCryptographicDigestImpl):
(WebCore::parseCryptographicDigest):
(WebCore::parseEncodedCryptographicDigestImpl):
(WebCore::parseEncodedCryptographicDigest):
* loader/ResourceCryptographicDigest.h:
Use StringParsingBuffer rather than raw pointers for parsing.

* loader/SubresourceIntegrity.cpp:
(WebCore::splitOnSpaces):
(WebCore::parseIntegrityMetadata):
Use StringParsingBuffer and readCharactersForParsing rather than raw pointers for parsing.

* page/csp/ContentSecurityPolicy.cpp:
(WebCore::ContentSecurityPolicy::didReceiveHeader):
Use StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
StringView::upconvertedCharacters().

* page/csp/ContentSecurityPolicyDirectiveList.cpp:
(WebCore::isDirectiveNameCharacter):
(WebCore::isDirectiveValueCharacter):
(WebCore::ContentSecurityPolicyDirectiveList::parse):
(WebCore::ContentSecurityPolicyDirectiveList::parseDirective):
(WebCore::ContentSecurityPolicyDirectiveList::parseReportURI):
(WebCore::ContentSecurityPolicyDirectiveList::setCSPDirective):
(WebCore::ContentSecurityPolicyDirectiveList::applySandboxPolicy):
(WebCore::ContentSecurityPolicyDirectiveList::setUpgradeInsecureRequests):
(WebCore::ContentSecurityPolicyDirectiveList::setBlockAllMixedContentEnabled):
(WebCore::ContentSecurityPolicyDirectiveList::addDirective):
* page/csp/ContentSecurityPolicyDirectiveList.h:
Use StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
StringView::upconvertedCharacters(). Also switch to using Optional for return values
rather than outparameter + bool. To make things read more cleanly, package up name
and value pair into a new ParsedDirective struct that can be passed around more easily.

* page/csp/ContentSecurityPolicyMediaListDirective.cpp:
(WebCore::isMediaTypeCharacter):
(WebCore::ContentSecurityPolicyMediaListDirective::parse):
Use StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
StringView::upconvertedCharacters().

* page/csp/ContentSecurityPolicySourceList.cpp:
(WebCore::isSourceCharacter):
(WebCore::isHostCharacter):
(WebCore::isPathComponentCharacter):
(WebCore::isSchemeContinuationCharacter):
(WebCore::isNotColonOrSlash):
(WebCore::isSourceListNone):
(WebCore::ContentSecurityPolicySourceList::parse):
(WebCore::ContentSecurityPolicySourceList::parseSource):
(WebCore::ContentSecurityPolicySourceList::parseScheme):
(WebCore::ContentSecurityPolicySourceList::parseHost):
(WebCore::ContentSecurityPolicySourceList::parsePath):
(WebCore::ContentSecurityPolicySourceList::parsePort):
(WebCore::isNonceCharacter):
(WebCore::ContentSecurityPolicySourceList::parseNonceSource):
(WebCore::ContentSecurityPolicySourceList::parseHashSource):
* page/csp/ContentSecurityPolicySourceList.h:
Use StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
StringView::upconvertedCharacters(). Also switch to using Optional for return values
rather than outparameter + bool. To make things read more cleanly, package up source
return values into structs that can be more easily returned / passed around.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (263580 => 263581)


--- trunk/Source/WebCore/ChangeLog	2020-06-26 20:52:54 UTC (rev 263580)
+++ trunk/Source/WebCore/ChangeLog	2020-06-26 20:58:02 UTC (rev 263581)
@@ -1,3 +1,88 @@
+2020-06-26  Sam Weinig  <[email protected]>
+
+        Convert ContentSecurityPolicy related parsers over to using StringParsingBuffer
+        https://bugs.webkit.org/show_bug.cgi?id=213631
+
+        Reviewed by Darin Adler.
+
+        - Adopt StringParsingBuffer across CSP code.
+        - Remove UTF-16 upconversions in ContentSecurityPolicy, ContentSecurityPolicyDirectiveList,
+          ContentSecurityPolicyMediaListDirective and ContentSecurityPolicySourceList.
+
+        * html/parser/ParsingUtilities.h:
+        (WebCore::isNotASCIISpace):
+        (WebCore::skipExactly):
+        (WebCore::characterPredicate):
+        (WebCore::skipUntil):
+        (WebCore::skipExactlyIgnoringASCIICase):
+        Add overloads for each helper that take a StringParsingBuffer.
+
+        * loader/ResourceCryptographicDigest.cpp:
+        (WebCore::parseHashAlgorithmAdvancingPosition):
+        Convert to use an Optional return value rather than outparameter + bool.
+
+        (WebCore::parseCryptographicDigestImpl):
+        (WebCore::parseCryptographicDigest):
+        (WebCore::parseEncodedCryptographicDigestImpl):
+        (WebCore::parseEncodedCryptographicDigest):
+        * loader/ResourceCryptographicDigest.h:
+        Use StringParsingBuffer rather than raw pointers for parsing.
+ 
+        * loader/SubresourceIntegrity.cpp:
+        (WebCore::splitOnSpaces):
+        (WebCore::parseIntegrityMetadata):
+        Use StringParsingBuffer and readCharactersForParsing rather than raw pointers for parsing.
+
+        * page/csp/ContentSecurityPolicy.cpp:
+        (WebCore::ContentSecurityPolicy::didReceiveHeader):
+        Use StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
+        StringView::upconvertedCharacters().
+
+        * page/csp/ContentSecurityPolicyDirectiveList.cpp:
+        (WebCore::isDirectiveNameCharacter):
+        (WebCore::isDirectiveValueCharacter):
+        (WebCore::ContentSecurityPolicyDirectiveList::parse):
+        (WebCore::ContentSecurityPolicyDirectiveList::parseDirective):
+        (WebCore::ContentSecurityPolicyDirectiveList::parseReportURI):
+        (WebCore::ContentSecurityPolicyDirectiveList::setCSPDirective):
+        (WebCore::ContentSecurityPolicyDirectiveList::applySandboxPolicy):
+        (WebCore::ContentSecurityPolicyDirectiveList::setUpgradeInsecureRequests):
+        (WebCore::ContentSecurityPolicyDirectiveList::setBlockAllMixedContentEnabled):
+        (WebCore::ContentSecurityPolicyDirectiveList::addDirective):
+        * page/csp/ContentSecurityPolicyDirectiveList.h:
+        Use StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
+        StringView::upconvertedCharacters(). Also switch to using Optional for return values
+        rather than outparameter + bool. To make things read more cleanly, package up name
+        and value pair into a new ParsedDirective struct that can be passed around more easily.
+
+        * page/csp/ContentSecurityPolicyMediaListDirective.cpp:
+        (WebCore::isMediaTypeCharacter): 
+        (WebCore::ContentSecurityPolicyMediaListDirective::parse):
+        Use StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
+        StringView::upconvertedCharacters().
+
+        * page/csp/ContentSecurityPolicySourceList.cpp:
+        (WebCore::isSourceCharacter):
+        (WebCore::isHostCharacter):
+        (WebCore::isPathComponentCharacter):
+        (WebCore::isSchemeContinuationCharacter):
+        (WebCore::isNotColonOrSlash):
+        (WebCore::isSourceListNone):
+        (WebCore::ContentSecurityPolicySourceList::parse):
+        (WebCore::ContentSecurityPolicySourceList::parseSource):
+        (WebCore::ContentSecurityPolicySourceList::parseScheme):
+        (WebCore::ContentSecurityPolicySourceList::parseHost):
+        (WebCore::ContentSecurityPolicySourceList::parsePath):
+        (WebCore::ContentSecurityPolicySourceList::parsePort):
+        (WebCore::isNonceCharacter):
+        (WebCore::ContentSecurityPolicySourceList::parseNonceSource):
+        (WebCore::ContentSecurityPolicySourceList::parseHashSource):
+        * page/csp/ContentSecurityPolicySourceList.h:
+        Use StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
+        StringView::upconvertedCharacters(). Also switch to using Optional for return values
+        rather than outparameter + bool. To make things read more cleanly, package up source
+        return values into structs that can be more easily returned / passed around.
+
 2020-06-26  Simon Fraser  <[email protected]>
 
         Content sometimes missing in nested scrollers with border-radius

Modified: trunk/Source/WebCore/html/parser/ParsingUtilities.h (263580 => 263581)


--- trunk/Source/WebCore/html/parser/ParsingUtilities.h	2020-06-26 20:52:54 UTC (rev 263580)
+++ trunk/Source/WebCore/html/parser/ParsingUtilities.h	2020-06-26 20:58:02 UTC (rev 263581)
@@ -34,13 +34,12 @@
 
 namespace WebCore {
 
-inline bool isNotASCIISpace(UChar c)
+template<typename CharacterType> inline bool isNotASCIISpace(CharacterType c)
 {
     return !isASCIISpace(c);
 }
     
-template<typename CharType>
-bool skipExactly(const CharType*& position, const CharType* end, CharType delimiter)
+template<typename CharacterType, typename DelimiterType> bool skipExactly(const CharacterType*& position, const CharacterType* end, DelimiterType delimiter)
 {
     if (position < end && *position == delimiter) {
         ++position;
@@ -49,9 +48,17 @@
     return false;
 }
 
-template<typename CharType, bool characterPredicate(CharType)>
-bool skipExactly(const CharType*& position, const CharType* end)
+template<typename CharacterType, typename DelimiterType> bool skipExactly(StringParsingBuffer<CharacterType>& buffer, DelimiterType delimiter)
 {
+    if (buffer.hasCharactersRemaining() && *buffer == delimiter) {
+        ++buffer;
+        return true;
+    }
+    return false;
+}
+
+template<typename CharacterType, bool characterPredicate(CharacterType)> bool skipExactly(const CharacterType*& position, const CharacterType* end)
+{
     if (position < end && characterPredicate(*position)) {
         ++position;
         return true;
@@ -59,44 +66,80 @@
     return false;
 }
 
-template<typename CharType>
-void skipUntil(const CharType*& position, const CharType* end, CharType delimiter)
+template<typename CharacterType, bool characterPredicate(CharacterType)> bool skipExactly(StringParsingBuffer<CharacterType>& buffer)
 {
+    if (buffer.hasCharactersRemaining() && characterPredicate(*buffer)) {
+        ++buffer;
+        return true;
+    }
+    return false;
+}
+
+template<typename CharacterType, typename DelimiterType> void skipUntil(const CharacterType*& position, const CharacterType* end, DelimiterType delimiter)
+{
     while (position < end && *position != delimiter)
         ++position;
 }
 
-template<typename CharType, bool characterPredicate(CharType)>
-void skipUntil(const CharType*& position, const CharType* end)
+template<typename CharacterType, typename DelimiterType>
+void skipUntil(StringParsingBuffer<CharacterType>& buffer, DelimiterType delimiter)
 {
+    while (buffer.hasCharactersRemaining() && *buffer != delimiter)
+        ++buffer;
+}
+
+template<typename CharacterType, bool characterPredicate(CharacterType)> void skipUntil(const CharacterType*& position, const CharacterType* end)
+{
     while (position < end && !characterPredicate(*position))
         ++position;
 }
 
-template<typename CharType, bool characterPredicate(CharType)>
-void skipWhile(const CharType*& position, const CharType* end)
+template<typename CharacterType, bool characterPredicate(CharacterType)> void skipUntil(StringParsingBuffer<CharacterType>& buffer)
 {
+    while (buffer.hasCharactersRemaining() && !characterPredicate(*buffer))
+        ++buffer;
+}
+
+template<typename CharacterType, bool characterPredicate(CharacterType)> void skipWhile(const CharacterType*& position, const CharacterType* end)
+{
     while (position < end && characterPredicate(*position))
         ++position;
 }
 
-template<typename CharType, bool characterPredicate(CharType)>
-void reverseSkipWhile(const CharType*& position, const CharType* start)
+template<typename CharacterType, bool characterPredicate(CharacterType)> void skipWhile(StringParsingBuffer<CharacterType>& buffer)
 {
+    while (buffer.hasCharactersRemaining() && characterPredicate(*buffer))
+        ++buffer;
+}
+
+template<typename CharacterType, bool characterPredicate(CharacterType)> void reverseSkipWhile(const CharacterType*& position, const CharacterType* start)
+{
     while (position >= start && characterPredicate(*position))
         --position;
 }
 
-template<typename CharacterType, unsigned lowercaseLettersLength>
-bool skipExactlyIgnoringASCIICase(const CharacterType*& position, const CharacterType* end, const char (&lowercaseLetters)[lowercaseLettersLength])
+template<typename CharacterType, unsigned lowercaseLettersArraySize> bool skipExactlyIgnoringASCIICase(const CharacterType*& position, const CharacterType* end, const char (&lowercaseLetters)[lowercaseLettersArraySize])
 {
+    constexpr auto lowercaseLettersLength = lowercaseLettersArraySize - 1;
+    
     if (position + lowercaseLettersLength > end)
         return false;
+    if (!WTF::equalLettersIgnoringASCIICase(position, lowercaseLettersLength, lowercaseLetters))
+        return false;
+    position += lowercaseLettersLength;
+    return true;
+}
 
-    bool result = WTF::equalLettersIgnoringASCIICase(position, lowercaseLettersLength - 1, lowercaseLetters);
-    if (result)
-        position += (lowercaseLettersLength - 1);
-    return result;
+template<typename CharacterType, unsigned lowercaseLettersArraySize> bool skipExactlyIgnoringASCIICase(StringParsingBuffer<CharacterType>& buffer, const char (&lowercaseLetters)[lowercaseLettersArraySize])
+{
+    constexpr auto lowercaseLettersLength = lowercaseLettersArraySize - 1;
+
+    if (buffer.lengthRemaining() < lowercaseLettersLength)
+        return false;
+    if (!WTF::equalLettersIgnoringASCIICase(buffer.position(), lowercaseLettersLength, lowercaseLetters))
+        return false;
+    buffer += lowercaseLettersLength;
+    return true;
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/loader/ResourceCryptographicDigest.cpp (263580 => 263581)


--- trunk/Source/WebCore/loader/ResourceCryptographicDigest.cpp	2020-06-26 20:52:54 UTC (rev 263580)
+++ trunk/Source/WebCore/loader/ResourceCryptographicDigest.cpp	2020-06-26 20:58:02 UTC (rev 263581)
@@ -30,104 +30,96 @@
 #include <pal/crypto/CryptoDigest.h>
 #include <wtf/Optional.h>
 #include <wtf/text/Base64.h>
+#include <wtf/text/StringParsingBuffer.h>
 
 namespace WebCore {
 
-template<typename CharacterType>
-static bool parseHashAlgorithmAdvancingPosition(const CharacterType*& position, const CharacterType* end, ResourceCryptographicDigest::Algorithm& algorithm)
+template<typename CharacterType> static Optional<ResourceCryptographicDigest::Algorithm> parseHashAlgorithmAdvancingPosition(StringParsingBuffer<CharacterType>& buffer)
 {
     // FIXME: This would be much cleaner with a lookup table of pairs of label / algorithm enum values, but I can't
     // figure out how to keep the labels compiletime strings for skipExactlyIgnoringASCIICase.
 
-    if (skipExactlyIgnoringASCIICase(position, end, "sha256")) {
-        algorithm = ResourceCryptographicDigest::Algorithm::SHA256;
-        return true;
-    }
-    if (skipExactlyIgnoringASCIICase(position, end, "sha384")) {
-        algorithm = ResourceCryptographicDigest::Algorithm::SHA384;
-        return true;
-    }
-    if (skipExactlyIgnoringASCIICase(position, end, "sha512")) {
-        algorithm = ResourceCryptographicDigest::Algorithm::SHA512;
-        return true;
-    }
+    if (skipExactlyIgnoringASCIICase(buffer, "sha256"))
+        return ResourceCryptographicDigest::Algorithm::SHA256;
+    if (skipExactlyIgnoringASCIICase(buffer, "sha384"))
+        return ResourceCryptographicDigest::Algorithm::SHA384;
+    if (skipExactlyIgnoringASCIICase(buffer, "sha512"))
+        return ResourceCryptographicDigest::Algorithm::SHA512;
 
-    return false;
+    return WTF::nullopt;
 }
 
-template<typename CharacterType>
-static Optional<ResourceCryptographicDigest> parseCryptographicDigestImpl(const CharacterType*& position, const CharacterType* end)
+template<typename CharacterType> static Optional<ResourceCryptographicDigest> parseCryptographicDigestImpl(StringParsingBuffer<CharacterType>& buffer)
 {
-    if (position == end)
+    if (buffer.atEnd())
         return WTF::nullopt;
 
-    ResourceCryptographicDigest::Algorithm algorithm;
-    if (!parseHashAlgorithmAdvancingPosition(position, end, algorithm))
+    auto algorithm = parseHashAlgorithmAdvancingPosition(buffer);
+    if (!algorithm)
         return WTF::nullopt;
 
-    if (!skipExactly<CharacterType>(position, end, '-'))
+    if (!skipExactly(buffer, '-'))
         return WTF::nullopt;
 
-    const CharacterType* beginHashValue = position;
-    skipWhile<CharacterType, isBase64OrBase64URLCharacter>(position, end);
-    skipExactly<CharacterType>(position, end, '=');
-    skipExactly<CharacterType>(position, end, '=');
+    auto beginHashValue = buffer.position();
+    skipWhile<CharacterType, isBase64OrBase64URLCharacter>(buffer);
+    skipExactly(buffer, '=');
+    skipExactly(buffer, '=');
 
-    if (position == beginHashValue)
+    if (buffer.position() == beginHashValue)
         return WTF::nullopt;
 
     Vector<uint8_t> digest;
-    StringView hashValue(beginHashValue, position - beginHashValue);
+    StringView hashValue(beginHashValue, buffer.position() - beginHashValue);
     if (!base64Decode(hashValue, digest, Base64ValidatePadding)) {
         if (!base64URLDecode(hashValue, digest))
             return WTF::nullopt;
     }
 
-    return ResourceCryptographicDigest { algorithm, WTFMove(digest) };
+    return ResourceCryptographicDigest { *algorithm, WTFMove(digest) };
 }
 
-Optional<ResourceCryptographicDigest> parseCryptographicDigest(const UChar*& begin, const UChar* end)
+Optional<ResourceCryptographicDigest> parseCryptographicDigest(StringParsingBuffer<UChar>& buffer)
 {
-    return parseCryptographicDigestImpl(begin, end);
+    return parseCryptographicDigestImpl(buffer);
 }
 
-Optional<ResourceCryptographicDigest> parseCryptographicDigest(const LChar*& begin, const LChar* end)
+Optional<ResourceCryptographicDigest> parseCryptographicDigest(StringParsingBuffer<LChar>& buffer)
 {
-    return parseCryptographicDigestImpl(begin, end);
+    return parseCryptographicDigestImpl(buffer);
 }
 
-template<typename CharacterType>
-static Optional<EncodedResourceCryptographicDigest> parseEncodedCryptographicDigestImpl(const CharacterType*& position, const CharacterType* end)
+template<typename CharacterType> static Optional<EncodedResourceCryptographicDigest> parseEncodedCryptographicDigestImpl(StringParsingBuffer<CharacterType>& buffer)
 {
-    if (position == end)
+    if (buffer.atEnd())
         return WTF::nullopt;
 
-    EncodedResourceCryptographicDigest::Algorithm algorithm;
-    if (!parseHashAlgorithmAdvancingPosition(position, end, algorithm))
+    auto algorithm = parseHashAlgorithmAdvancingPosition(buffer);
+    if (!algorithm)
         return WTF::nullopt;
 
-    if (!skipExactly<CharacterType>(position, end, '-'))
+    if (!skipExactly(buffer, '-'))
         return WTF::nullopt;
 
-    const CharacterType* beginHashValue = position;
-    skipWhile<CharacterType, isBase64OrBase64URLCharacter>(position, end);
-    skipExactly<CharacterType>(position, end, '=');
-    skipExactly<CharacterType>(position, end, '=');
+    auto beginHashValue = buffer.position();
+    skipWhile<CharacterType, isBase64OrBase64URLCharacter>(buffer);
+    skipExactly(buffer, '=');
+    skipExactly(buffer, '=');
 
-    if (position == beginHashValue)
+    if (buffer.position() == beginHashValue)
         return WTF::nullopt;
 
-    return EncodedResourceCryptographicDigest { algorithm, String(beginHashValue, position - beginHashValue) };
+    return EncodedResourceCryptographicDigest { *algorithm, String(beginHashValue, buffer.position() - beginHashValue) };
 }
 
-Optional<EncodedResourceCryptographicDigest> parseEncodedCryptographicDigest(const UChar*& begin, const UChar* end)
+Optional<EncodedResourceCryptographicDigest> parseEncodedCryptographicDigest(StringParsingBuffer<UChar>& buffer)
 {
-    return parseEncodedCryptographicDigestImpl(begin, end);
+    return parseEncodedCryptographicDigestImpl(buffer);
 }
 
-Optional<EncodedResourceCryptographicDigest> parseEncodedCryptographicDigest(const LChar*& begin, const LChar* end)
+Optional<EncodedResourceCryptographicDigest> parseEncodedCryptographicDigest(StringParsingBuffer<LChar>& buffer)
 {
-    return parseEncodedCryptographicDigestImpl(begin, end);
+    return parseEncodedCryptographicDigestImpl(buffer);
 }
 
 Optional<ResourceCryptographicDigest> decodeEncodedResourceCryptographicDigest(const EncodedResourceCryptographicDigest& encodedDigest)

Modified: trunk/Source/WebCore/loader/ResourceCryptographicDigest.h (263580 => 263581)


--- trunk/Source/WebCore/loader/ResourceCryptographicDigest.h	2020-06-26 20:52:54 UTC (rev 263580)
+++ trunk/Source/WebCore/loader/ResourceCryptographicDigest.h	2020-06-26 20:58:02 UTC (rev 263581)
@@ -66,11 +66,11 @@
     String digest;
 };
 
-Optional<ResourceCryptographicDigest> parseCryptographicDigest(const UChar*& begin, const UChar* end);
-Optional<ResourceCryptographicDigest> parseCryptographicDigest(const LChar*& begin, const LChar* end);
+Optional<ResourceCryptographicDigest> parseCryptographicDigest(StringParsingBuffer<UChar>&);
+Optional<ResourceCryptographicDigest> parseCryptographicDigest(StringParsingBuffer<LChar>&);
 
-Optional<EncodedResourceCryptographicDigest> parseEncodedCryptographicDigest(const UChar*& begin, const UChar* end);
-Optional<EncodedResourceCryptographicDigest> parseEncodedCryptographicDigest(const LChar*& begin, const LChar* end);
+Optional<EncodedResourceCryptographicDigest> parseEncodedCryptographicDigest(StringParsingBuffer<UChar>&);
+Optional<EncodedResourceCryptographicDigest> parseEncodedCryptographicDigest(StringParsingBuffer<LChar>&);
 
 Optional<ResourceCryptographicDigest> decodeEncodedResourceCryptographicDigest(const EncodedResourceCryptographicDigest&);
 

Modified: trunk/Source/WebCore/loader/SubresourceIntegrity.cpp (263580 => 263581)


--- trunk/Source/WebCore/loader/SubresourceIntegrity.cpp	2020-06-26 20:52:54 UTC (rev 263580)
+++ trunk/Source/WebCore/loader/SubresourceIntegrity.cpp	2020-06-26 20:58:02 UTC (rev 263581)
@@ -31,6 +31,7 @@
 #include "ParsingUtilities.h"
 #include "ResourceCryptographicDigest.h"
 #include "SharedBuffer.h"
+#include <wtf/text/StringParsingBuffer.h>
 
 namespace WebCore {
 
@@ -50,7 +51,7 @@
     {
     }
 
-    bool operator()(const CharacterType*& position, const CharacterType* end)
+    bool operator()(StringParsingBuffer<CharacterType>& buffer)
     {
         // Initialize hashes to be something other WTF::nullopt, to indicate
         // that at least one token was seen, and thus setting the empty flag
@@ -58,7 +59,7 @@
         if (!m_digests)
             m_digests = Vector<EncodedResourceCryptographicDigest> { };
 
-        auto digest = parseEncodedCryptographicDigest(position, end);
+        auto digest = parseEncodedCryptographicDigest(buffer);
         if (!digest)
             return false;
 
@@ -65,12 +66,12 @@
         // The spec allows for options following the digest, but so far, no
         // specific options have been specified. Thus, we just parse and ignore
         // them. Their syntax is a '?' follow by any number of VCHARs.
-        if (skipExactly<CharacterType>(position, end, '?'))
-            skipWhile<CharacterType, isVCHAR>(position, end);
+        if (skipExactly(buffer, '?'))
+            skipWhile<CharacterType, isVCHAR>(buffer);
 
         // After the base64 value and options, the current character pointed to by position
         // should either be the end or a space.
-        if (position != end && !isHTMLSpace(*position))
+        if (!buffer.atEnd() && !isHTMLSpace(*buffer))
             return false;
 
         m_digests->append(WTFMove(*digest));
@@ -84,17 +85,14 @@
 }
 
 template <typename CharacterType, typename Functor>
-static inline void splitOnSpaces(const CharacterType* begin, const CharacterType* end, Functor&& functor)
+static inline void splitOnSpaces(StringParsingBuffer<CharacterType> buffer, Functor&& functor)
 {
-    const CharacterType* position = begin;
+    skipWhile<CharacterType, isHTMLSpace>(buffer);
 
-    skipWhile<CharacterType, isHTMLSpace>(position, end);
-
-    while (position < end) {
-        if (!functor(position, end))
-            skipWhile<CharacterType, isNotHTMLSpace>(position, end);
-
-        skipWhile<CharacterType, isHTMLSpace>(position, end);
+    while (buffer.hasCharactersRemaining()) {
+        if (!functor(buffer))
+            skipWhile<CharacterType, isNotHTMLSpace>(buffer);
+        skipWhile<CharacterType, isHTMLSpace>(buffer);
     }
 }
 
@@ -105,11 +103,10 @@
 
     Optional<Vector<EncodedResourceCryptographicDigest>> result;
     
-    const StringImpl& stringImpl = *integrityMetadata.impl();
-    if (stringImpl.is8Bit())
-        splitOnSpaces(stringImpl.characters8(), stringImpl.characters8() + stringImpl.length(), IntegrityMetadataParser<LChar> { result });
-    else
-        splitOnSpaces(stringImpl.characters16(), stringImpl.characters16() + stringImpl.length(), IntegrityMetadataParser<UChar> { result });
+    readCharactersForParsing(integrityMetadata, [&result] (auto buffer) {
+        using CharacterType = typename decltype(buffer)::CharacterType;
+        splitOnSpaces(buffer, IntegrityMetadataParser<CharacterType> { result });
+    });
 
     return result;
 }

Modified: trunk/Source/WebCore/page/csp/ContentSecurityPolicy.cpp (263580 => 263581)


--- trunk/Source/WebCore/page/csp/ContentSecurityPolicy.cpp	2020-06-26 20:52:54 UTC (rev 263580)
+++ trunk/Source/WebCore/page/csp/ContentSecurityPolicy.cpp	2020-06-26 20:58:02 UTC (rev 263581)
@@ -58,6 +58,7 @@
 #include <wtf/JSONValues.h>
 #include <wtf/SetForScope.h>
 #include <wtf/text/StringBuilder.h>
+#include <wtf/text/StringParsingBuffer.h>
 #include <wtf/text/TextPosition.h>
 
 
@@ -212,22 +213,23 @@
     // RFC2616, section 4.2 specifies that headers appearing multiple times can
     // be combined with a comma. Walk the header string, and parse each comma
     // separated chunk as a separate header.
-    auto characters = StringView(header).upconvertedCharacters();
-    const UChar* begin = characters;
-    const UChar* position = begin;
-    const UChar* end = begin + header.length();
-    while (position < end) {
-        skipUntil<UChar>(position, end, ',');
+    readCharactersForParsing(header, [&](auto buffer) {
+        auto begin = buffer.position();
+    
+        while (buffer.hasCharactersRemaining()) {
+            skipUntil(buffer, ',');
 
-        // header1,header2 OR header1
-        //        ^                  ^
-        m_policies.append(ContentSecurityPolicyDirectiveList::create(*this, String(begin, position - begin), type, policyFrom));
+            // header1,header2 OR header1
+            //        ^                  ^
+            m_policies.append(ContentSecurityPolicyDirectiveList::create(*this, String(begin, buffer.position() - begin), type, policyFrom));
 
-        // Skip the comma, and begin the next header from the current position.
-        ASSERT(position == end || *position == ',');
-        skipExactly<UChar>(position, end, ',');
-        begin = position;
-    }
+            // Skip the comma, and begin the next header from the current position.
+            ASSERT(buffer.atEnd() || *buffer == ',');
+            skipExactly(buffer, ',');
+            begin = buffer.position();
+        }
+    });
+    
 
     if (m_scriptExecutionContext)
         applyPolicyToScriptExecutionContext();

Modified: trunk/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.cpp (263580 => 263581)


--- trunk/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.cpp	2020-06-26 20:52:54 UTC (rev 263580)
+++ trunk/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.cpp	2020-06-26 20:58:02 UTC (rev 263581)
@@ -32,15 +32,16 @@
 #include "Frame.h"
 #include "ParsingUtilities.h"
 #include "SecurityContext.h"
+#include <wtf/text/StringParsingBuffer.h>
 
 namespace WebCore {
 
-static bool isDirectiveNameCharacter(UChar c)
+template<typename CharacterType> static bool isDirectiveNameCharacter(CharacterType c)
 {
     return isASCIIAlphanumeric(c) || c == '-';
 }
 
-static bool isDirectiveValueCharacter(UChar c)
+template<typename CharacterType> static bool isDirectiveValueCharacter(CharacterType c)
 {
     return isASCIISpace(c) || (c >= 0x21 && c <= 0x7e); // Whitespace + VCHAR
 }
@@ -333,38 +334,35 @@
     if (policy.isEmpty())
         return;
 
-    auto characters = StringView(policy).upconvertedCharacters();
-    const UChar* position = characters;
-    const UChar* end = position + policy.length();
+    readCharactersForParsing(policy, [&](auto buffer) {
+        while (buffer.hasCharactersRemaining()) {
+            auto directiveBegin = buffer.position();
+            skipUntil(buffer, ';');
 
-    while (position < end) {
-        const UChar* directiveBegin = position;
-        skipUntil<UChar>(position, end, ';');
-
-        String name, value;
-        if (parseDirective(directiveBegin, position, name, value)) {
-            ASSERT(!name.isEmpty());
-            if (policyFrom == ContentSecurityPolicy::PolicyFrom::Inherited) {
-                if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::upgradeInsecureRequests))
-                    continue;
-            } else if (policyFrom == ContentSecurityPolicy::PolicyFrom::HTTPEquivMeta) {
-                if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::sandbox)
-                    || equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::reportURI)
-                    || equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::frameAncestors)) {
-                    m_policy.reportInvalidDirectiveInHTTPEquivMeta(name);
-                    continue;
+            if (auto directive = parseDirective(StringParsingBuffer { directiveBegin, buffer.position() })) {
+                ASSERT(!directive->name.isEmpty());
+                if (policyFrom == ContentSecurityPolicy::PolicyFrom::Inherited) {
+                    if (equalIgnoringASCIICase(directive->name, ContentSecurityPolicyDirectiveNames::upgradeInsecureRequests))
+                        continue;
+                } else if (policyFrom == ContentSecurityPolicy::PolicyFrom::HTTPEquivMeta) {
+                    if (equalIgnoringASCIICase(directive->name, ContentSecurityPolicyDirectiveNames::sandbox)
+                        || equalIgnoringASCIICase(directive->name, ContentSecurityPolicyDirectiveNames::reportURI)
+                        || equalIgnoringASCIICase(directive->name, ContentSecurityPolicyDirectiveNames::frameAncestors)) {
+                        m_policy.reportInvalidDirectiveInHTTPEquivMeta(directive->name);
+                        continue;
+                    }
+                } else if (policyFrom == ContentSecurityPolicy::PolicyFrom::InheritedForPluginDocument) {
+                    if (!equalIgnoringASCIICase(directive->name, ContentSecurityPolicyDirectiveNames::pluginTypes)
+                        && !equalIgnoringASCIICase(directive->name, ContentSecurityPolicyDirectiveNames::reportURI))
+                        continue;
                 }
-            } else if (policyFrom == ContentSecurityPolicy::PolicyFrom::InheritedForPluginDocument) {
-                if (!equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::pluginTypes)
-                    && !equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::reportURI))
-                    continue;
+                addDirective(WTFMove(*directive));
             }
-            addDirective(name, value);
+
+            ASSERT(buffer.atEnd() || *buffer == ';');
+            skipExactly(buffer, ';');
         }
-
-        ASSERT(position == end || *position == ';');
-        skipExactly<UChar>(position, end, ';');
-    }
+    });
 }
 
 // directive         = *WSP [ directive-name [ WSP directive-value ] ]
@@ -371,115 +369,112 @@
 // directive-name    = 1*( ALPHA / DIGIT / "-" )
 // directive-value   = *( WSP / <VCHAR except ";"> )
 //
-bool ContentSecurityPolicyDirectiveList::parseDirective(const UChar* begin, const UChar* end, String& name, String& value)
+template<typename CharacterType> auto ContentSecurityPolicyDirectiveList::parseDirective(StringParsingBuffer<CharacterType> buffer) -> Optional<ParsedDirective>
 {
-    ASSERT(name.isEmpty());
-    ASSERT(value.isEmpty());
+    skipWhile<CharacterType, isASCIISpace>(buffer);
 
-    const UChar* position = begin;
-    skipWhile<UChar, isASCIISpace>(position, end);
-
     // Empty directive (e.g. ";;;"). Exit early.
-    if (position == end)
-        return false;
+    if (buffer.atEnd())
+        return WTF::nullopt;
 
-    const UChar* nameBegin = position;
-    skipWhile<UChar, isDirectiveNameCharacter>(position, end);
+    auto nameBegin = buffer.position();
+    skipWhile<CharacterType, isDirectiveNameCharacter>(buffer);
 
     // The directive-name must be non-empty.
-    if (nameBegin == position) {
-        skipWhile<UChar, isNotASCIISpace>(position, end);
-        m_policy.reportUnsupportedDirective(String(nameBegin, position - nameBegin));
-        return false;
+    if (nameBegin == buffer.position()) {
+        skipWhile<CharacterType, isNotASCIISpace>(buffer);
+        m_policy.reportUnsupportedDirective(String(nameBegin, buffer.position() - nameBegin));
+        return WTF::nullopt;
     }
 
-    name = String(nameBegin, position - nameBegin);
+    auto name = String(nameBegin, buffer.position() - nameBegin);
 
-    if (position == end)
-        return true;
+    if (buffer.atEnd())
+        return ParsedDirective { WTFMove(name), { } };
 
-    if (!skipExactly<UChar, isASCIISpace>(position, end)) {
-        skipWhile<UChar, isNotASCIISpace>(position, end);
-        m_policy.reportUnsupportedDirective(String(nameBegin, position - nameBegin));
-        return false;
+    if (!skipExactly<CharacterType, isASCIISpace>(buffer)) {
+        skipWhile<CharacterType, isNotASCIISpace>(buffer);
+        m_policy.reportUnsupportedDirective(String(nameBegin, buffer.position() - nameBegin));
+        return WTF::nullopt;
     }
 
-    skipWhile<UChar, isASCIISpace>(position, end);
+    skipWhile<CharacterType, isASCIISpace>(buffer);
 
-    const UChar* valueBegin = position;
-    skipWhile<UChar, isDirectiveValueCharacter>(position, end);
+    auto valueBegin = buffer.position();
+    skipWhile<CharacterType, isDirectiveValueCharacter>(buffer);
 
-    if (position != end) {
-        m_policy.reportInvalidDirectiveValueCharacter(name, String(valueBegin, end - valueBegin));
-        return false;
+    if (!buffer.atEnd()) {
+        m_policy.reportInvalidDirectiveValueCharacter(name, String(valueBegin, buffer.end() - valueBegin));
+        return WTF::nullopt;
     }
 
     // The directive-value may be empty.
-    if (valueBegin == position)
-        return true;
+    if (valueBegin == buffer.position())
+        return ParsedDirective { WTFMove(name), { } };
 
-    value = String(valueBegin, position - valueBegin);
-    return true;
+    auto value = String(valueBegin, buffer.position() - valueBegin);
+    return ParsedDirective { WTFMove(name), WTFMove(value) };
 }
 
-void ContentSecurityPolicyDirectiveList::parseReportURI(const String& name, const String& value)
+void ContentSecurityPolicyDirectiveList::parseReportURI(ParsedDirective&& directive)
 {
     if (!m_reportURIs.isEmpty()) {
-        m_policy.reportDuplicateDirective(name);
+        m_policy.reportDuplicateDirective(directive.name);
         return;
     }
 
-    auto characters = StringView(value).upconvertedCharacters();
-    const UChar* position = characters;
-    const UChar* end = position + value.length();
+    readCharactersForParsing(directive.value, [&](auto buffer) {
+        using CharacterType = typename decltype(buffer)::CharacterType;
 
-    while (position < end) {
-        skipWhile<UChar, isASCIISpace>(position, end);
+        auto begin = buffer.position();
+        while (buffer.hasCharactersRemaining()) {
+            skipWhile<CharacterType, isASCIISpace>(buffer);
 
-        const UChar* urlBegin = position;
-        skipWhile<UChar, isNotASCIISpace>(position, end);
+            auto urlBegin = buffer.position();
+            skipWhile<CharacterType, isNotASCIISpace>(buffer);
 
-        if (urlBegin < position)
-            m_reportURIs.append(value.substring(urlBegin - characters, position - urlBegin));
-    }
+            if (urlBegin < buffer.position())
+                m_reportURIs.append(directive.value.substring(urlBegin - begin, buffer.position() - urlBegin));
+        }
+    });
 }
 
 
 template<class CSPDirectiveType>
-void ContentSecurityPolicyDirectiveList::setCSPDirective(const String& name, const String& value, std::unique_ptr<CSPDirectiveType>& directive)
+void ContentSecurityPolicyDirectiveList::setCSPDirective(ParsedDirective&& directive, std::unique_ptr<CSPDirectiveType>& existingDirective)
 {
-    if (directive) {
-        m_policy.reportDuplicateDirective(name);
+    if (existingDirective) {
+        m_policy.reportDuplicateDirective(directive.name);
         return;
     }
-    directive = makeUnique<CSPDirectiveType>(*this, name, value);
+    existingDirective = makeUnique<CSPDirectiveType>(*this, WTFMove(directive.name), WTFMove(directive.value));
 }
 
-void ContentSecurityPolicyDirectiveList::applySandboxPolicy(const String& name, const String& sandboxPolicy)
+void ContentSecurityPolicyDirectiveList::applySandboxPolicy(ParsedDirective&& directive)
 {
     if (m_reportOnly) {
-        m_policy.reportInvalidDirectiveInReportOnlyMode(name);
+        m_policy.reportInvalidDirectiveInReportOnlyMode(directive.name);
         return;
     }
     if (m_haveSandboxPolicy) {
-        m_policy.reportDuplicateDirective(name);
+        m_policy.reportDuplicateDirective(directive.name);
         return;
     }
     m_haveSandboxPolicy = true;
     String invalidTokens;
-    m_policy.enforceSandboxFlags(SecurityContext::parseSandboxPolicy(sandboxPolicy, invalidTokens));
+    m_policy.enforceSandboxFlags(SecurityContext::parseSandboxPolicy(WTFMove(directive.value), invalidTokens));
     if (!invalidTokens.isNull())
         m_policy.reportInvalidSandboxFlags(invalidTokens);
 }
 
-void ContentSecurityPolicyDirectiveList::setUpgradeInsecureRequests(const String& name)
+void ContentSecurityPolicyDirectiveList::setUpgradeInsecureRequests(ParsedDirective&& directive)
 {
     if (m_reportOnly) {
-        m_policy.reportInvalidDirectiveInReportOnlyMode(name);
+        m_policy.reportInvalidDirectiveInReportOnlyMode(WTFMove(directive.name));
         return;
     }
     if (m_upgradeInsecureRequests) {
-        m_policy.reportDuplicateDirective(name);
+        m_policy.reportDuplicateDirective(WTFMove(directive.name));
         return;
     }
     m_upgradeInsecureRequests = true;
@@ -486,71 +481,71 @@
     m_policy.setUpgradeInsecureRequests(true);
 }
 
-void ContentSecurityPolicyDirectiveList::setBlockAllMixedContentEnabled(const String& name)
+void ContentSecurityPolicyDirectiveList::setBlockAllMixedContentEnabled(ParsedDirective&& directive)
 {
     if (m_hasBlockAllMixedContentDirective) {
-        m_policy.reportDuplicateDirective(name);
+        m_policy.reportDuplicateDirective(WTFMove(directive.name));
         return;
     }
     m_hasBlockAllMixedContentDirective = true;
 }
 
-void ContentSecurityPolicyDirectiveList::addDirective(const String& name, const String& value)
+void ContentSecurityPolicyDirectiveList::addDirective(ParsedDirective&& directive)
 {
-    ASSERT(!name.isEmpty());
+    ASSERT(!directive.name.isEmpty());
 
-    if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::defaultSrc)) {
-        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_defaultSrc);
+    if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::defaultSrc)) {
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(WTFMove(directive), m_defaultSrc);
         m_policy.addHashAlgorithmsForInlineScripts(m_defaultSrc->hashAlgorithmsUsed());
         m_policy.addHashAlgorithmsForInlineStylesheets(m_defaultSrc->hashAlgorithmsUsed());
-    } else if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::scriptSrc)) {
-        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_scriptSrc);
+    } else if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::scriptSrc)) {
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(WTFMove(directive), m_scriptSrc);
         m_policy.addHashAlgorithmsForInlineScripts(m_scriptSrc->hashAlgorithmsUsed());
-    } else if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::styleSrc)) {
-        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_styleSrc);
+    } else if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::styleSrc)) {
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(WTFMove(directive), m_styleSrc);
         m_policy.addHashAlgorithmsForInlineStylesheets(m_styleSrc->hashAlgorithmsUsed());
-    } else if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::objectSrc))
-        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_objectSrc);
-    else if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::frameSrc)) {
+    } else if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::objectSrc))
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(WTFMove(directive), m_objectSrc);
+    else if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::frameSrc)) {
         // FIXME: Log to console "The frame-src directive is deprecated. Use the child-src directive instead."
         // See <https://bugs.webkit.org/show_bug.cgi?id=155773>.
-        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_frameSrc);
-    } else if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::imgSrc))
-        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_imgSrc);
-    else if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::fontSrc))
-        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_fontSrc);
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(WTFMove(directive), m_frameSrc);
+    } else if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::imgSrc))
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(WTFMove(directive), m_imgSrc);
+    else if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::fontSrc))
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(WTFMove(directive), m_fontSrc);
 #if ENABLE(APPLICATION_MANIFEST)
-    else if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::manifestSrc))
-        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_manifestSrc);
+    else if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::manifestSrc))
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(WTFMove(directive), m_manifestSrc);
 #endif
-    else if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::mediaSrc))
-        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_mediaSrc);
-    else if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::connectSrc))
-        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_connectSrc);
-    else if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::childSrc))
-        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_childSrc);
-    else if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::formAction))
-        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_formAction);
-    else if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::baseURI))
-        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_baseURI);
-    else if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::frameAncestors)) {
+    else if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::mediaSrc))
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(WTFMove(directive), m_mediaSrc);
+    else if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::connectSrc))
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(WTFMove(directive), m_connectSrc);
+    else if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::childSrc))
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(WTFMove(directive), m_childSrc);
+    else if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::formAction))
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(WTFMove(directive), m_formAction);
+    else if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::baseURI))
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(WTFMove(directive), m_baseURI);
+    else if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::frameAncestors)) {
         if (m_reportOnly) {
-            m_policy.reportInvalidDirectiveInReportOnlyMode(name);
+            m_policy.reportInvalidDirectiveInReportOnlyMode(directive.name);
             return;
         }
-        setCSPDirective<ContentSecurityPolicySourceListDirective>(name, value, m_frameAncestors);
-    } else if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::pluginTypes))
-        setCSPDirective<ContentSecurityPolicyMediaListDirective>(name, value, m_pluginTypes);
-    else if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::sandbox))
-        applySandboxPolicy(name, value);
-    else if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::reportURI))
-        parseReportURI(name, value);
-    else if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::upgradeInsecureRequests))
-        setUpgradeInsecureRequests(name);
-    else if (equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::blockAllMixedContent))
-        setBlockAllMixedContentEnabled(name);
+        setCSPDirective<ContentSecurityPolicySourceListDirective>(WTFMove(directive), m_frameAncestors);
+    } else if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::pluginTypes))
+        setCSPDirective<ContentSecurityPolicyMediaListDirective>(WTFMove(directive), m_pluginTypes);
+    else if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::sandbox))
+        applySandboxPolicy(WTFMove(directive));
+    else if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::reportURI))
+        parseReportURI(WTFMove(directive));
+    else if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::upgradeInsecureRequests))
+        setUpgradeInsecureRequests(WTFMove(directive));
+    else if (equalIgnoringASCIICase(directive.name, ContentSecurityPolicyDirectiveNames::blockAllMixedContent))
+        setBlockAllMixedContentEnabled(WTFMove(directive));
     else
-        m_policy.reportUnsupportedDirective(name);
+        m_policy.reportUnsupportedDirective(WTFMove(directive.name));
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.h (263580 => 263581)


--- trunk/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.h	2020-06-26 20:52:54 UTC (rev 263580)
+++ trunk/Source/WebCore/page/csp/ContentSecurityPolicyDirectiveList.h	2020-06-26 20:58:02 UTC (rev 263581)
@@ -89,16 +89,19 @@
 private:
     void parse(const String&, ContentSecurityPolicy::PolicyFrom);
 
-    bool parseDirective(const UChar* begin, const UChar* end, String& name, String& value);
-    void parseReportURI(const String& name, const String& value);
-    void parsePluginTypes(const String& name, const String& value);
-    void addDirective(const String& name, const String& value);
-    void applySandboxPolicy(const String& name, const String& sandboxPolicy);
-    void setUpgradeInsecureRequests(const String& name);
-    void setBlockAllMixedContentEnabled(const String& name);
+    struct ParsedDirective {
+        String name;
+        String value;
+    };
+    template<typename CharacterType> Optional<ParsedDirective> parseDirective(StringParsingBuffer<CharacterType>);
+    void parseReportURI(ParsedDirective&&);
+    void addDirective(ParsedDirective&&);
+    void applySandboxPolicy(ParsedDirective&&);
+    void setUpgradeInsecureRequests(ParsedDirective&&);
+    void setBlockAllMixedContentEnabled(ParsedDirective&&);
 
     template <class CSPDirectiveType>
-    void setCSPDirective(const String& name, const String& value, std::unique_ptr<CSPDirectiveType>&);
+    void setCSPDirective(ParsedDirective&&, std::unique_ptr<CSPDirectiveType>&);
 
     ContentSecurityPolicySourceListDirective* operativeDirective(ContentSecurityPolicySourceListDirective*) const;
 

Modified: trunk/Source/WebCore/page/csp/ContentSecurityPolicyMediaListDirective.cpp (263580 => 263581)


--- trunk/Source/WebCore/page/csp/ContentSecurityPolicyMediaListDirective.cpp	2020-06-26 20:52:54 UTC (rev 263580)
+++ trunk/Source/WebCore/page/csp/ContentSecurityPolicyMediaListDirective.cpp	2020-06-26 20:58:02 UTC (rev 263581)
@@ -31,10 +31,11 @@
 #include "ContentSecurityPolicyDirectiveList.h"
 #include "ParsingUtilities.h"
 #include <wtf/text/StringHash.h>
+#include <wtf/text/StringParsingBuffer.h>
 
 namespace WebCore {
 
-static bool isMediaTypeCharacter(UChar c)
+template<typename CharacterType> static bool isMediaTypeCharacter(CharacterType c)
 {
     return !isASCIISpace(c) && c != '/';
 }
@@ -52,11 +53,6 @@
 
 void ContentSecurityPolicyMediaListDirective::parse(const String& value)
 {
-    auto characters = StringView(value).upconvertedCharacters();
-    const UChar* begin = characters;
-    const UChar* position = begin;
-    const UChar* end = begin + value.length();
-
     // 'plugin-types ____;' OR 'plugin-types;'
     if (value.isEmpty()) {
         directiveList().policy().reportInvalidPluginTypes(value);
@@ -63,51 +59,55 @@
         return;
     }
 
-    while (position < end) {
-        // _____ OR _____mime1/mime1
-        // ^        ^
-        skipWhile<UChar, isASCIISpace>(position, end);
-        if (position == end)
-            return;
+    readCharactersForParsing(value, [&](auto buffer) {
+        using CharacterType = typename decltype(buffer)::CharacterType;
 
-        // mime1/mime1 mime2/mime2
-        // ^
-        begin = position;
-        if (!skipExactly<UChar, isMediaTypeCharacter>(position, end)) {
-            skipWhile<UChar, isNotASCIISpace>(position, end);
-            directiveList().policy().reportInvalidPluginTypes(String(begin, position - begin));
-            continue;
-        }
-        skipWhile<UChar, isMediaTypeCharacter>(position, end);
+        while (buffer.hasCharactersRemaining()) {
+            // _____ OR _____mime1/mime1
+            // ^        ^
+            skipWhile<CharacterType, isASCIISpace>(buffer);
+            if (buffer.atEnd())
+                return;
 
-        // mime1/mime1 mime2/mime2
-        //      ^
-        if (!skipExactly<UChar>(position, end, '/')) {
-            skipWhile<UChar, isNotASCIISpace>(position, end);
-            directiveList().policy().reportInvalidPluginTypes(String(begin, position - begin));
-            continue;
-        }
+            // mime1/mime1 mime2/mime2
+            // ^
+            auto begin = buffer.position();
+            if (!skipExactly<CharacterType, isMediaTypeCharacter>(buffer)) {
+                skipWhile<CharacterType, isNotASCIISpace>(buffer);
+                directiveList().policy().reportInvalidPluginTypes(String(begin, buffer.position() - begin));
+                continue;
+            }
+            skipWhile<CharacterType, isMediaTypeCharacter>(buffer);
 
-        // mime1/mime1 mime2/mime2
-        //       ^
-        if (!skipExactly<UChar, isMediaTypeCharacter>(position, end)) {
-            skipWhile<UChar, isNotASCIISpace>(position, end);
-            directiveList().policy().reportInvalidPluginTypes(String(begin, position - begin));
-            continue;
-        }
-        skipWhile<UChar, isMediaTypeCharacter>(position, end);
+            // mime1/mime1 mime2/mime2
+            //      ^
+            if (!skipExactly(buffer, '/')) {
+                skipWhile<CharacterType, isNotASCIISpace>(buffer);
+                directiveList().policy().reportInvalidPluginTypes(String(begin, buffer.position() - begin));
+                continue;
+            }
 
-        // mime1/mime1 mime2/mime2 OR mime1/mime1  OR mime1/mime1/error
-        //            ^                          ^               ^
-        if (position < end && isNotASCIISpace(*position)) {
-            skipWhile<UChar, isNotASCIISpace>(position, end);
-            directiveList().policy().reportInvalidPluginTypes(String(begin, position - begin));
-            continue;
+            // mime1/mime1 mime2/mime2
+            //       ^
+            if (!skipExactly<CharacterType, isMediaTypeCharacter>(buffer)) {
+                skipWhile<CharacterType, isNotASCIISpace>(buffer);
+                directiveList().policy().reportInvalidPluginTypes(String(begin, buffer.position() - begin));
+                continue;
+            }
+            skipWhile<CharacterType, isMediaTypeCharacter>(buffer);
+
+            // mime1/mime1 mime2/mime2 OR mime1/mime1  OR mime1/mime1/error
+            //            ^                          ^               ^
+            if (buffer.hasCharactersRemaining() && isNotASCIISpace(*buffer)) {
+                skipWhile<CharacterType, isNotASCIISpace>(buffer);
+                directiveList().policy().reportInvalidPluginTypes(String(begin, buffer.position() - begin));
+                continue;
+            }
+            m_pluginTypes.add(String(begin, buffer.position() - begin));
+
+            ASSERT(buffer.atEnd() || isASCIISpace(*buffer));
         }
-        m_pluginTypes.add(String(begin, position - begin));
-
-        ASSERT(position == end || isASCIISpace(*position));
-    }
+    });
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/page/csp/ContentSecurityPolicySourceList.cpp (263580 => 263581)


--- trunk/Source/WebCore/page/csp/ContentSecurityPolicySourceList.cpp	2020-06-26 20:52:54 UTC (rev 263580)
+++ trunk/Source/WebCore/page/csp/ContentSecurityPolicySourceList.cpp	2020-06-26 20:58:02 UTC (rev 263581)
@@ -35,6 +35,7 @@
 #include <wtf/NeverDestroyed.h>
 #include <wtf/URL.h>
 #include <wtf/text/Base64.h>
+#include <wtf/text/StringParsingBuffer.h>
 
 namespace WebCore {
 
@@ -56,48 +57,41 @@
         || equalIgnoringASCIICase(name, ContentSecurityPolicyDirectiveNames::styleSrc);
 }
 
-static bool isSourceCharacter(UChar c)
+template<typename CharacterType> static bool isSourceCharacter(CharacterType c)
 {
     return !isASCIISpace(c);
 }
 
-static bool isHostCharacter(UChar c)
+template<typename CharacterType> static bool isHostCharacter(CharacterType c)
 {
     return isASCIIAlphanumeric(c) || c == '-';
 }
 
-static bool isPathComponentCharacter(UChar c)
+template<typename CharacterType> static bool isPathComponentCharacter(CharacterType c)
 {
     return c != '?' && c != '#';
 }
 
-static bool isSchemeContinuationCharacter(UChar c)
+template<typename CharacterType> static bool isSchemeContinuationCharacter(CharacterType c)
 {
     return isASCIIAlphanumeric(c) || c == '+' || c == '-' || c == '.';
 }
 
-static bool isNotColonOrSlash(UChar c)
+template<typename CharacterType> static bool isNotColonOrSlash(CharacterType c)
 {
     return c != ':' && c != '/';
 }
 
-static bool isSourceListNone(const String& value)
+template<typename CharacterType> static bool isSourceListNone(StringParsingBuffer<CharacterType> buffer)
 {
-    auto characters = StringView(value).upconvertedCharacters();
-    const UChar* begin = characters;
-    const UChar* end = characters + value.length();
-    skipWhile<UChar, isASCIISpace>(begin, end);
+    skipWhile<CharacterType, isASCIISpace>(buffer);
 
-    const UChar* position = begin;
-    skipWhile<UChar, isSourceCharacter>(position, end);
-    if (!equalLettersIgnoringASCIICase(begin, position - begin, "'none'"))
+    if (!skipExactlyIgnoringASCIICase(buffer, "'none'"))
         return false;
 
-    skipWhile<UChar, isASCIISpace>(position, end);
-    if (position != end)
-        return false;
-    
-    return true;
+    skipWhile<CharacterType, isASCIISpace>(buffer);
+
+    return buffer.atEnd();
 }
 
 ContentSecurityPolicySourceList::ContentSecurityPolicySourceList(const ContentSecurityPolicy& policy, const String& directiveName)
@@ -108,12 +102,14 @@
 
 void ContentSecurityPolicySourceList::parse(const String& value)
 {
-    if (isSourceListNone(value)) {
-        m_isNone = true;
-        return;
-    }
-    auto characters = StringView(value).upconvertedCharacters();
-    parse(characters, characters + value.length());
+    readCharactersForParsing(value, [&](auto buffer) {
+        if (isSourceListNone(buffer)) {
+            m_isNone = true;
+            return;
+        }
+
+        parse(buffer);
+    });
 }
 
 bool ContentSecurityPolicySourceList::isProtocolAllowedByStar(const URL& url) const
@@ -160,42 +156,37 @@
 // source-list       = *WSP [ source *( 1*WSP source ) *WSP ]
 //                   / *WSP "'none'" *WSP
 //
-void ContentSecurityPolicySourceList::parse(const UChar* begin, const UChar* end)
+template<typename CharacterType> void ContentSecurityPolicySourceList::parse(StringParsingBuffer<CharacterType> buffer)
 {
-    const UChar* position = begin;
-
-    while (position < end) {
-        skipWhile<UChar, isASCIISpace>(position, end);
-        if (position == end)
+    while (buffer.hasCharactersRemaining()) {
+        skipWhile<CharacterType, isASCIISpace>(buffer);
+        if (buffer.atEnd())
             return;
 
-        const UChar* beginSource = position;
-        skipWhile<UChar, isSourceCharacter>(position, end);
+        auto beginSource = buffer.position();
+        skipWhile<CharacterType, isSourceCharacter>(buffer);
 
-        String scheme, host, path;
-        Optional<uint16_t> port;
-        bool hostHasWildcard = false;
-        bool portHasWildcard = false;
+        auto sourceBuffer = StringParsingBuffer { beginSource, buffer.position() };
 
-        if (parseNonceSource(beginSource, position))
+        if (parseNonceSource(sourceBuffer))
             continue;
 
-        if (parseHashSource(beginSource, position))
+        if (parseHashSource(sourceBuffer))
             continue;
 
-        if (parseSource(beginSource, position, scheme, host, port, path, hostHasWildcard, portHasWildcard)) {
+        if (auto source = parseSource(sourceBuffer)) {
             // Wildcard hosts and keyword sources ('self', 'unsafe-inline',
             // etc.) aren't stored in m_list, but as attributes on the source
             // list itself.
-            if (scheme.isEmpty() && host.isEmpty())
+            if (source->scheme.isEmpty() && source->host.value.isEmpty())
                 continue;
-            if (isCSPDirectiveName(host))
-                m_policy.reportDirectiveAsSourceExpression(m_directiveName, host);
-            m_list.append(ContentSecurityPolicySource(m_policy, scheme, host, port, path, hostHasWildcard, portHasWildcard));
+            if (isCSPDirectiveName(source->host.value))
+                m_policy.reportDirectiveAsSourceExpression(m_directiveName, source->host.value);
+            m_list.append(ContentSecurityPolicySource(m_policy, source->scheme, source->host.value, source->port.value, source->path, source->host.hasWildcard, source->port.hasWildcard));
         } else
-            m_policy.reportInvalidSourceExpression(m_directiveName, String(beginSource, position - beginSource));
+            m_policy.reportInvalidSourceExpression(m_directiveName, String(beginSource, buffer.position() - beginSource));
 
-        ASSERT(position == end || isASCIISpace(*position));
+        ASSERT(buffer.atEnd() || isASCIISpace(*buffer));
     }
     
     m_list.shrinkToFit();
@@ -205,132 +196,162 @@
 //                   / ( [ scheme "://" ] host [ port ] [ path ] )
 //                   / "'self'"
 //
-bool ContentSecurityPolicySourceList::parseSource(const UChar* begin, const UChar* end, String& scheme, String& host, Optional<uint16_t>& port, String& path, bool& hostHasWildcard, bool& portHasWildcard)
+template<typename CharacterType> Optional<ContentSecurityPolicySourceList::Source> ContentSecurityPolicySourceList::parseSource(StringParsingBuffer<CharacterType> buffer)
 {
-    if (begin == end)
-        return false;
+    if (buffer.atEnd())
+        return WTF::nullopt;
 
-    if (equalLettersIgnoringASCIICase(begin, end - begin, "'none'"))
-        return false;
+    if (skipExactlyIgnoringASCIICase(buffer, "'none'"))
+        return WTF::nullopt;
 
-    if (end - begin == 1 && *begin == '*') {
+    Source source;
+
+    if (buffer.lengthRemaining() == 1 && *buffer == '*') {
         m_allowStar = true;
-        return true;
+        return source;
     }
 
-    if (equalLettersIgnoringASCIICase(begin, end - begin, "'self'")) {
+    if (skipExactlyIgnoringASCIICase(buffer, "'self'")) {
         m_allowSelf = true;
-        return true;
+        return source;
     }
 
-    if (equalLettersIgnoringASCIICase(begin, end - begin, "'unsafe-inline'")) {
+    if (skipExactlyIgnoringASCIICase(buffer, "'unsafe-inline'")) {
         m_allowInline = true;
-        return true;
+        return source;
     }
 
-    if (equalLettersIgnoringASCIICase(begin, end - begin, "'unsafe-eval'")) {
+    if (skipExactlyIgnoringASCIICase(buffer, "'unsafe-eval'")) {
         m_allowEval = true;
-        return true;
+        return source;
     }
 
-    const UChar* position = begin;
-    const UChar* beginHost = begin;
-    const UChar* beginPath = end;
-    const UChar* beginPort = nullptr;
+    auto begin = buffer.position();
+    auto beginHost = begin;
+    auto beginPath = buffer.end();
+    const CharacterType* beginPort = nullptr;
 
-    skipWhile<UChar, isNotColonOrSlash>(position, end);
+    skipWhile<CharacterType, isNotColonOrSlash>(buffer);
 
-    if (position == end) {
+    if (buffer.atEnd()) {
         // host
         //     ^
-        return parseHost(beginHost, position, host, hostHasWildcard);
+        auto host = parseHost(StringParsingBuffer { beginHost, buffer.position() });
+        if (!host)
+            return WTF::nullopt;
+
+        source.host = WTFMove(*host);
+        return source;
     }
 
-    if (position < end && *position == '/') {
+    if (buffer.hasCharactersRemaining() && *buffer == '/') {
         // host/path || host/ || /
         //     ^            ^    ^
-        return parseHost(beginHost, position, host, hostHasWildcard) && parsePath(position, end, path);
+        auto host = parseHost(StringParsingBuffer { beginHost, buffer.position() });
+        if (!host)
+            return WTF::nullopt;
+
+        auto path = parsePath(buffer);
+        if (!path)
+            return WTF::nullopt;
+
+        source.host = WTFMove(*host);
+        source.path = WTFMove(*path);
+        return source;
     }
 
-    if (position < end && *position == ':') {
-        if (end - position == 1) {
+    if (buffer.hasCharactersRemaining() && *buffer == ':') {
+        if (buffer.lengthRemaining() == 1) {
             // scheme:
             //       ^
-            return parseScheme(begin, position, scheme);
+            auto scheme = parseScheme(StringParsingBuffer { begin, buffer.position() });
+            if (!scheme)
+                return WTF::nullopt;
+
+            source.scheme = WTFMove(*scheme);
+            return source;
         }
 
-        if (position[1] == '/') {
+        if (buffer[1] == '/') {
             // scheme://host || scheme://
             //       ^                ^
-            if (!parseScheme(begin, position, scheme)
-                || !skipExactly<UChar>(position, end, ':')
-                || !skipExactly<UChar>(position, end, '/')
-                || !skipExactly<UChar>(position, end, '/'))
-                return false;
-            if (position == end)
-                return false;
-            beginHost = position;
-            skipWhile<UChar, isNotColonOrSlash>(position, end);
+            auto scheme = parseScheme(StringParsingBuffer { begin, buffer.position() });
+            if (!scheme
+                || !skipExactly(buffer, ':')
+                || !skipExactly(buffer, '/')
+                || !skipExactly(buffer, '/'))
+                return WTF::nullopt;
+            if (buffer.atEnd())
+                return WTF::nullopt;
+
+            source.scheme = WTFMove(*scheme);
+
+            beginHost = buffer.position();
+            skipWhile<CharacterType, isNotColonOrSlash>(buffer);
         }
 
-        if (position < end && *position == ':') {
+        if (buffer.hasCharactersRemaining() && *buffer == ':') {
             // host:port || scheme://host:port
             //     ^                     ^
-            beginPort = position;
-            skipUntil<UChar>(position, end, '/');
+            beginPort = buffer.position();
+            skipUntil(buffer, '/');
         }
     }
 
-    if (position < end && *position == '/') {
+    if (buffer.hasCharactersRemaining() && *buffer == '/') {
         // scheme://host/path || scheme://host:port/path
         //              ^                          ^
-        if (position == beginHost)
-            return false;
+        if (buffer.position() == beginHost)
+            return WTF::nullopt;
 
-        beginPath = position;
+        beginPath = buffer.position();
     }
 
-    if (!parseHost(beginHost, beginPort ? beginPort : beginPath, host, hostHasWildcard))
-        return false;
+    auto host = parseHost(StringParsingBuffer { beginHost, beginPort ? beginPort : beginPath });
+    if (!host)
+        return WTF::nullopt;
 
-    if (!beginPort)
-        port = WTF::nullopt;
-    else {
-        if (!parsePort(beginPort, beginPath, port, portHasWildcard))
-            return false;
+    if (beginPort) {
+        auto port = parsePort(StringParsingBuffer { beginPort, beginPath });
+        if (!port)
+            return WTF::nullopt;
+
+        source.port = WTFMove(*port);
     }
 
-    if (beginPath != end) {
-        if (!parsePath(beginPath, end, path))
-            return false;
+    if (beginPath != buffer.end()) {
+        auto path = parsePath(StringParsingBuffer { beginPath, buffer.end() });
+        if (!path)
+            return WTF::nullopt;
+
+        source.path = WTFMove(*path);
     }
 
-    return true;
+    source.host = WTFMove(*host);
+    return source;
 }
 
 //                     ; <scheme> production from RFC 3986
 // scheme      = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
 //
-bool ContentSecurityPolicySourceList::parseScheme(const UChar* begin, const UChar* end, String& scheme)
+template<typename CharacterType> Optional<String> ContentSecurityPolicySourceList::parseScheme(StringParsingBuffer<CharacterType> buffer)
 {
-    ASSERT(begin <= end);
-    ASSERT(scheme.isEmpty());
+    ASSERT(buffer.position() <= buffer.end());
 
-    if (begin == end)
-        return false;
+    if (buffer.atEnd())
+        return WTF::nullopt;
 
-    const UChar* position = begin;
+    auto begin = buffer.position();
 
-    if (!skipExactly<UChar, isASCIIAlpha>(position, end))
-        return false;
+    if (!skipExactly<CharacterType, isASCIIAlpha>(buffer))
+        return WTF::nullopt;
 
-    skipWhile<UChar, isSchemeContinuationCharacter>(position, end);
+    skipWhile<CharacterType, isSchemeContinuationCharacter>(buffer);
 
-    if (position != end)
-        return false;
+    if (!buffer.atEnd())
+        return WTF::nullopt;
 
-    scheme = String(begin, end - begin);
-    return true;
+    return String(begin, buffer.position() - begin);
 }
 
 // host              = [ "*." ] 1*host-char *( "." 1*host-char )
@@ -337,101 +358,97 @@
 //                   / "*"
 // host-char         = ALPHA / DIGIT / "-"
 //
-bool ContentSecurityPolicySourceList::parseHost(const UChar* begin, const UChar* end, String& host, bool& hostHasWildcard)
+template<typename CharacterType> Optional<ContentSecurityPolicySourceList::Host> ContentSecurityPolicySourceList::parseHost(StringParsingBuffer<CharacterType> buffer)
 {
-    ASSERT(begin <= end);
-    ASSERT(host.isEmpty());
-    ASSERT(!hostHasWildcard);
+    ASSERT(buffer.position() <= buffer.end());
 
-    if (begin == end)
-        return false;
+    if (buffer.atEnd())
+        return WTF::nullopt;
 
-    const UChar* position = begin;
+    Host host;
 
-    if (skipExactly<UChar>(position, end, '*')) {
-        hostHasWildcard = true;
+    if (skipExactly(buffer, '*')) {
+        host.hasWildcard = true;
 
-        if (position == end)
-            return true;
+        if (buffer.atEnd())
+            return host;
 
-        if (!skipExactly<UChar>(position, end, '.'))
-            return false;
+        if (!skipExactly(buffer, '.'))
+            return WTF::nullopt;
     }
 
-    const UChar* hostBegin = position;
+    auto hostBegin = buffer.position();
 
-    while (position < end) {
-        if (!skipExactly<UChar, isHostCharacter>(position, end))
-            return false;
+    while (buffer.hasCharactersRemaining()) {
+        if (!skipExactly<CharacterType, isHostCharacter>(buffer))
+            return WTF::nullopt;
 
-        skipWhile<UChar, isHostCharacter>(position, end);
+        skipWhile<CharacterType, isHostCharacter>(buffer);
 
-        if (position < end && !skipExactly<UChar>(position, end, '.'))
-            return false;
+        if (buffer.hasCharactersRemaining() && !skipExactly(buffer, '.'))
+            return WTF::nullopt;
     }
 
-    ASSERT(position == end);
-    host = String(hostBegin, end - hostBegin);
-    return true;
+    ASSERT(buffer.atEnd());
+    host.value = String(hostBegin, buffer.position() - hostBegin);
+    return host;
 }
 
-bool ContentSecurityPolicySourceList::parsePath(const UChar* begin, const UChar* end, String& path)
+template<typename CharacterType> Optional<String> ContentSecurityPolicySourceList::parsePath(StringParsingBuffer<CharacterType> buffer)
 {
-    ASSERT(begin <= end);
-    ASSERT(path.isEmpty());
+    ASSERT(buffer.position() <= buffer.end());
     
-    const UChar* position = begin;
-    skipWhile<UChar, isPathComponentCharacter>(position, end);
+    auto begin = buffer.position();
+    skipWhile<CharacterType, isPathComponentCharacter>(buffer);
     // path/to/file.js?query=string || path/to/file.js#anchor
     //                ^                               ^
-    if (position < end)
-        m_policy.reportInvalidPathCharacter(m_directiveName, String(begin, end - begin), *position);
-    
-    path = decodeURLEscapeSequences(String(begin, position - begin));
-    
-    ASSERT(position <= end);
-    ASSERT(position == end || (*position == '#' || *position == '?'));
-    return true;
+    if (buffer.hasCharactersRemaining())
+        m_policy.reportInvalidPathCharacter(m_directiveName, String(begin, buffer.end() - begin), *buffer);
+
+    ASSERT(buffer.position() <= buffer.end());
+    ASSERT(buffer.atEnd() || (*buffer == '#' || *buffer == '?'));
+
+    return decodeURLEscapeSequences(StringView(begin, buffer.position() - begin));
 }
 
 // port              = ":" ( 1*DIGIT / "*" )
 //
-bool ContentSecurityPolicySourceList::parsePort(const UChar* begin, const UChar* end, Optional<uint16_t>& port, bool& portHasWildcard)
+template<typename CharacterType> Optional<ContentSecurityPolicySourceList::Port> ContentSecurityPolicySourceList::parsePort(StringParsingBuffer<CharacterType> buffer)
 {
-    ASSERT(begin <= end);
-    ASSERT(!port);
-    ASSERT(!portHasWildcard);
+    ASSERT(buffer.position() <= buffer.end());
     
-    if (!skipExactly<UChar>(begin, end, ':'))
+    if (!skipExactly(buffer, ':'))
         ASSERT_NOT_REACHED();
     
-    if (begin == end)
-        return false;
+    if (buffer.atEnd())
+        return WTF::nullopt;
     
-    if (end - begin == 1 && *begin == '*') {
-        port = WTF::nullopt;
-        portHasWildcard = true;
-        return true;
+    if (buffer.lengthRemaining() == 1 && *buffer == '*') {
+        Port port;
+        port.hasWildcard = true;
+        return port;
     }
     
-    const UChar* position = begin;
-    skipWhile<UChar, isASCIIDigit>(position, end);
+    auto begin = buffer.position();
+    skipWhile<CharacterType, isASCIIDigit>(buffer);
     
-    if (position != end)
-        return false;
+    if (!buffer.atEnd())
+        return WTF::nullopt;
     
     bool ok;
-    int portInt = charactersToIntStrict(begin, end - begin, &ok);
-    if (portInt < 0 || portInt > std::numeric_limits<uint16_t>::max())
-        return false;
-    port = portInt;
-    return ok;
+    int portInt = charactersToIntStrict(begin, buffer.position() - begin, &ok);
+    if (!ok || portInt < 0 || portInt > std::numeric_limits<uint16_t>::max())
+        return WTF::nullopt;
+
+    Port port;
+    port.value = portInt;
+    return port;
 }
 
 // Match Blink's behavior of allowing an equal sign to appear anywhere in the value of the nonce
 // even though this does not match the behavior of Content Security Policy Level 3 spec.,
 // <https://w3c.github.io/webappsec-csp/> (29 February 2016).
-static bool isNonceCharacter(UChar c)
+template<typename CharacterType> static bool isNonceCharacter(CharacterType c)
 {
     return isBase64OrBase64URLCharacter(c) || c == '=';
 }
@@ -438,17 +455,16 @@
 
 // nonce-source    = "'nonce-" nonce-value "'"
 // nonce-value     = base64-value
-bool ContentSecurityPolicySourceList::parseNonceSource(const UChar* begin, const UChar* end)
+template<typename CharacterType> bool ContentSecurityPolicySourceList::parseNonceSource(StringParsingBuffer<CharacterType> buffer)
 {
-    const unsigned noncePrefixLength = 7;
-    if (!StringView(begin, end - begin).startsWithIgnoringASCIICase("'nonce-"))
+    if (!skipExactlyIgnoringASCIICase(buffer, "'nonce-"))
         return false;
-    const UChar* position = begin + noncePrefixLength;
-    const UChar* beginNonceValue = position;
-    skipWhile<UChar, isNonceCharacter>(position, end);
-    if (position >= end || position == beginNonceValue || *position != '\'')
+
+    auto beginNonceValue = buffer.position();
+    skipWhile<CharacterType, isNonceCharacter>(buffer);
+    if (buffer.atEnd() || buffer.position() == beginNonceValue || *buffer != '\'')
         return false;
-    m_nonces.add(String(beginNonceValue, position - beginNonceValue));
+    m_nonces.add(String(beginNonceValue, buffer.position() - beginNonceValue));
     return true;
 }
 
@@ -455,20 +471,19 @@
 // hash-source    = "'" hash-algorithm "-" base64-value "'"
 // hash-algorithm = "sha256" / "sha384" / "sha512"
 // base64-value  = 1*( ALPHA / DIGIT / "+" / "/" / "-" / "_" )*2( "=" )
-bool ContentSecurityPolicySourceList::parseHashSource(const UChar* begin, const UChar* end)
+template<typename CharacterType> bool ContentSecurityPolicySourceList::parseHashSource(StringParsingBuffer<CharacterType> buffer)
 {
-    if (begin == end)
+    if (buffer.atEnd())
         return false;
 
-    const UChar* position = begin;
-    if (!skipExactly<UChar>(position, end, '\''))
+    if (!skipExactly(buffer, '\''))
         return false;
 
-    auto digest = parseCryptographicDigest(position, end);
+    auto digest = parseCryptographicDigest(buffer);
     if (!digest)
         return false;
 
-    if (position >= end || *position != '\'')
+    if (buffer.atEnd() || *buffer != '\'')
         return false;
 
     if (digest->value.size() > ContentSecurityPolicyHash::maximumDigestLength)

Modified: trunk/Source/WebCore/page/csp/ContentSecurityPolicySourceList.h (263580 => 263581)


--- trunk/Source/WebCore/page/csp/ContentSecurityPolicySourceList.h	2020-06-26 20:52:54 UTC (rev 263580)
+++ trunk/Source/WebCore/page/csp/ContentSecurityPolicySourceList.h	2020-06-26 20:58:02 UTC (rev 263581)
@@ -55,19 +55,31 @@
     bool isNone() const { return m_isNone; }
 
 private:
-    void parse(const UChar* begin, const UChar* end);
+    struct Host {
+        String value;
+        bool hasWildcard { false };
+    };
+    struct Port {
+        Optional<uint16_t> value;
+        bool hasWildcard { false };
+    };
+    struct Source {
+        String scheme;
+        Host host;
+        Port port;
+        String path;
+    };
 
-    bool parseSource(const UChar* begin, const UChar* end, String& scheme, String& host, Optional<uint16_t>& port, String& path, bool& hostHasWildcard, bool& portHasWildcard);
-    bool parseScheme(const UChar* begin, const UChar* end, String& scheme);
-    bool parseHost(const UChar* begin, const UChar* end, String& host, bool& hostHasWildcard);
-    bool parsePort(const UChar* begin, const UChar* end, Optional<uint16_t>& port, bool& portHasWildcard);
-    bool parsePath(const UChar* begin, const UChar* end, String& path);
-
-    bool parseNonceSource(const UChar* begin, const UChar* end);
-
     bool isProtocolAllowedByStar(const URL&) const;
 
-    bool parseHashSource(const UChar* begin, const UChar* end);
+    template<typename CharacterType> void parse(StringParsingBuffer<CharacterType>);
+    template<typename CharacterType> Optional<Source> parseSource(StringParsingBuffer<CharacterType>);
+    template<typename CharacterType> Optional<String> parseScheme(StringParsingBuffer<CharacterType>);
+    template<typename CharacterType> Optional<Host> parseHost(StringParsingBuffer<CharacterType>);
+    template<typename CharacterType> Optional<Port> parsePort(StringParsingBuffer<CharacterType>);
+    template<typename CharacterType> Optional<String> parsePath(StringParsingBuffer<CharacterType>);
+    template<typename CharacterType> bool parseNonceSource(StringParsingBuffer<CharacterType>);
+    template<typename CharacterType> bool parseHashSource(StringParsingBuffer<CharacterType>);
 
     const ContentSecurityPolicy& m_policy;
     Vector<ContentSecurityPolicySource> m_list;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to