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;