Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(666)

Unified Diff: Source/core/frame/SubresourceIntegrity.cpp

Issue 1126343003: Ignore unknown options to subresource integrity (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/frame/SubresourceIntegrity.cpp
diff --git a/Source/core/frame/SubresourceIntegrity.cpp b/Source/core/frame/SubresourceIntegrity.cpp
index 0832fccf0233a8642aa933f89679ab5b4ef65fde..a911b1fe6f5de2b48b4d2083c8ae45d902f341da 100644
--- a/Source/core/frame/SubresourceIntegrity.cpp
+++ b/Source/core/frame/SubresourceIntegrity.cpp
@@ -40,6 +40,16 @@ static bool isTypeCharacter(UChar c)
return isASCIIAlphanumeric(c) || c == '+' || c == '.' || c == '-';
}
+static bool isOptionNameCharacter(UChar c)
+{
+ return isASCIIAlphanumeric(c) || c == '-';
+}
+
+static bool isOptionValueCharacter(UChar c)
+{
+ return isASCIIAlphanumeric(c) || c == '!' || c == '#' || c == '$' || c == '%' || c == '&' || c == '\'' || c == '*' || c == '+' || c == '-' || c == '.' || c == '^' || c == '_' || c == '`' || c == '|' || c == '~' || c == '/';
+}
+
static void logErrorToConsole(const String& message, Document& document)
{
document.addConsoleMessage(ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel, message));
@@ -203,45 +213,69 @@ bool SubresourceIntegrity::parseDigest(const UChar*& position, const UChar* end,
return true;
}
+bool SubresourceIntegrity::isValidMimeTypeValue(const String& value)
+{
+ Vector<UChar> characters;
+ value.appendTo(characters);
+ const UChar* position = characters.data();
+ const UChar* end = characters.end();
+
+ skipWhile<UChar, isASCIIAlpha>(position, end);
+ if (position == end)
+ return false;
+
+ if (!skipExactly<UChar>(position, end, '/'))
+ return false;
+
+ skipWhile<UChar, isTypeCharacter>(position, end);
+ if (position != end)
+ return false;
+
+ return true;
+}
+
// Before:
//
-// [algorithm]-[hash] OR [algorithm]-[hash]?[options]
-// ^ ^ ^
-// position/end position end
+// [algorithm]-[hash] OR [algorithm]-[hash]?[name]=[value] OR [algorithm]-[hash]?[name]=[value]?[rest of options]
+// ^ ^ ^ ^ ^
+// position/end position end position end
//
// After (if successful: if the method returns false, we make no promises and the caller should exit early):
//
-// [algorithm]-[hash] OR [algorithm]-[hash]?[options]
-// ^ ^
-// position/end position/end
-bool SubresourceIntegrity::parseMimeType(const UChar*& position, const UChar* end, String& type)
+// [algorithm]-[hash] OR [algorithm]-[hash]?[name]=[value] OR [algorithm]-[hash]?[name]=[value]?[rest of options]
Mike West 2015/05/11 03:25:28 This is such a weird syntax.
+// ^ ^ ^ ^
+// position/end position/end position end
+bool SubresourceIntegrity::parseOption(const UChar*& position, const UChar* end, String& name, String& value)
{
- type = emptyString();
+ name = emptyString();
+ value = emptyString();
if (position == end)
return true;
- if (!skipToken<UChar>(position, end, "?ct="))
+ if (!skipExactly<UChar>(position, end, '?'))
return false;
const UChar* begin = position;
- skipWhile<UChar, isASCIIAlpha>(position, end);
+ skipWhile<UChar, isOptionNameCharacter>(position, end);
if (position == end)
return false;
- if (!skipExactly<UChar>(position, end, '/'))
- return false;
+ name = String(begin, position - begin);
- if (position == end)
+ if (!skipExactly<UChar>(position, end, '=') || position == end)
return false;
- skipWhile<UChar, isTypeCharacter>(position, end);
- if (position != end)
- return false;
+ begin = position;
+ skipWhile<UChar, isOptionValueCharacter>(position, end);
- type = String(begin, position - begin);
- return true;
+ value = String(begin, position - begin);
+
+ if (position == end || *position == '?')
Mike West 2015/05/11 03:25:28 Would you mind asserting that `position < end` bef
+ return true;
+
+ return false;
}
SubresourceIntegrity::IntegrityParseResult SubresourceIntegrity::parseIntegrityAttribute(const WTF::String& attribute, WTF::Vector<IntegrityMetadata>& metadataList, Document& document)
@@ -300,14 +334,37 @@ SubresourceIntegrity::IntegrityParseResult SubresourceIntegrity::parseIntegrityA
continue;
}
- if (!parseMimeType(position, currentIntegrityEnd, type)) {
- logErrorToConsole("Error parsing 'integrity' attribute ('" + attribute + "'). The content type could not be parsed.", document);
- error = true;
- skipUntil<UChar, isASCIISpace>(position, end);
- UseCounter::count(document, UseCounter::SRIElementWithUnparsableIntegrityAttribute);
- continue;
+ bool skipToNextIntegrity = false;
+ while (*position == '?') {
+ String name, value;
+ if (!parseOption(position, currentIntegrityEnd, name, value)) {
+ logErrorToConsole("Error parsing 'integrity' attribute ('" + attribute + "'). The options could not be parsed.", document);
+ skipToNextIntegrity = true;
+ error = true;
+ skipUntil<UChar, isASCIISpace>(position, end);
+ UseCounter::count(document, UseCounter::SRIElementWithUnparsableIntegrityAttribute);
+ break;
+ }
+
+ if (name == "ct") {
+ if (!isValidMimeTypeValue(value)) {
+ logErrorToConsole("Error parsing 'integrity' attribute ('" + attribute + "'). The content type could not be parsed.", document);
+ skipToNextIntegrity = true;
+ error = true;
+ skipUntil<UChar, isASCIISpace>(position, end);
+ UseCounter::count(document, UseCounter::SRIElementWithUnparsableIntegrityAttribute);
+ break;
+ }
+
+ type = value;
+ } else {
+ logErrorToConsole("Ignoring unrecogized 'integrity' attribute option '" + name + "' with value '" + value + "'.", document);
+ }
}
+ if (skipToNextIntegrity)
+ continue;
+
IntegrityMetadata integrityMetadata = {
digest,
algorithm,

Powered by Google App Engine
This is Rietveld 408576698