Index: Source/WebCore/html/parser/XSSFilter.cpp |
=================================================================== |
--- Source/WebCore/html/parser/XSSFilter.cpp (revision 86259) |
+++ Source/WebCore/html/parser/XSSFilter.cpp (working copy) |
@@ -43,9 +43,7 @@ |
using namespace HTMLNames; |
-namespace { |
- |
-bool isNonCanonicalCharacter(UChar c) |
+static bool isNonCanonicalCharacter(UChar c) |
{ |
// We remove all non-ASCII characters, including non-printable ASCII characters. |
// |
@@ -57,22 +55,22 @@ |
return (c == '\\' || c == '0' || c == '\0' || c >= 127); |
} |
-String canonicalize(const String& string) |
+static String canonicalize(const String& string) |
{ |
return string.removeCharacters(&isNonCanonicalCharacter); |
} |
-bool isRequiredForInjection(UChar c) |
+static bool isRequiredForInjection(UChar c) |
{ |
return (c == '\'' || c == '"' || c == '<' || c == '>'); |
} |
-bool hasName(const HTMLToken& token, const QualifiedName& name) |
+static bool hasName(const HTMLToken& token, const QualifiedName& name) |
{ |
return equalIgnoringNullity(token.name(), static_cast<const String&>(name.localName())); |
} |
-bool findAttributeWithName(const HTMLToken& token, const QualifiedName& name, size_t& indexOfMatchingAttribute) |
+static bool findAttributeWithName(const HTMLToken& token, const QualifiedName& name, size_t& indexOfMatchingAttribute) |
{ |
for (size_t i = 0; i < token.attributes().size(); ++i) { |
if (equalIgnoringNullity(token.attributes().at(i).m_name, name.localName())) { |
@@ -83,7 +81,7 @@ |
return false; |
} |
-bool isNameOfInlineEventHandler(const Vector<UChar, 32>& name) |
+static bool isNameOfInlineEventHandler(const Vector<UChar, 32>& name) |
{ |
const size_t lengthOfShortestInlineEventHandlerName = 5; // To wit: oncut. |
if (name.size() < lengthOfShortestInlineEventHandlerName) |
@@ -91,8 +89,14 @@ |
return name[0] == 'o' && name[1] == 'n'; |
} |
-bool containsJavaScriptURL(const Vector<UChar, 32>& value) |
+static bool isDangerousHTTPEquiv(const String& value) |
{ |
+ String equiv = value.stripWhiteSpace(); |
+ return equalIgnoringCase(equiv, "refresh") || equalIgnoringCase(equiv, "set-cookie"); |
+} |
+ |
+static bool containsJavaScriptURL(const Vector<UChar, 32>& value) |
+{ |
static const char javaScriptScheme[] = "javascript:"; |
static const size_t lengthOfJavaScriptScheme = sizeof(javaScriptScheme) - 1; |
@@ -108,7 +112,7 @@ |
return equalIgnoringCase(value.data() + i, javaScriptScheme, lengthOfJavaScriptScheme); |
} |
-String decodeURL(const String& string, const TextEncoding& encoding) |
+static String decodeURL(const String& string, const TextEncoding& encoding) |
{ |
String workingString = string; |
workingString.replace('+', ' '); |
@@ -121,8 +125,6 @@ |
return canonicalize(decodedString); |
} |
-} |
- |
XSSFilter::XSSFilter(HTMLDocumentParser* parser) |
: m_parser(parser) |
, m_isEnabled(false) |
@@ -420,6 +422,8 @@ |
if (isContainedInRequest(snippetForAttribute(token, attribute))) { |
if (attributeName == srcAttr && isSameOriginResource(String(attribute.m_value.data(), attribute.m_value.size()))) |
return false; |
+ if (attributeName == http_equivAttr && !isDangerousHTTPEquiv(String(attribute.m_value.data(), attribute.m_value.size()))) |
+ return false; |
token.eraseValueOfAttribute(indexOfAttribute); |
if (!replacementValue.isEmpty()) |
token.appendToAttributeValue(indexOfAttribute, replacementValue); |