Diff
Modified: trunk/Source/WebCore/ChangeLog (142098 => 142099)
--- trunk/Source/WebCore/ChangeLog 2013-02-07 12:57:12 UTC (rev 142098)
+++ trunk/Source/WebCore/ChangeLog 2013-02-07 13:01:02 UTC (rev 142099)
@@ -1,3 +1,53 @@
+2013-02-07 Tony Gentilcore <[email protected]>
+
+ Call XSSAuditor.filterToken() from threaded HTML parser
+ https://bugs.webkit.org/show_bug.cgi?id=107603
+
+ Reviewed by Adam Barth.
+
+ With this patch we now pass 180 of 182 tests in http/tests/security/xssAuditor.
+
+ We do this by creating aan XSSAuditor on the main thread and passing ownership of them to the BackgroundHTMLParser upon its creation.
+
+ Then the background thread calls filterToken() and stores the resulting XSSInfo (if any) on the CompactHTMLToken for the main thread to handle.
+
+ This involved trimming the XSSAuditor to only depend on the TextEncoding instead of the whole TextResourceDecoder.
+
+ No new tests because covered by existing tests.
+
+ * html/parser/BackgroundHTMLParser.cpp:
+ (WebCore::BackgroundHTMLParser::BackgroundHTMLParser):
+ (WebCore::BackgroundHTMLParser::pumpTokenizer):
+ (WebCore::BackgroundHTMLParser::createPartial):
+ * html/parser/BackgroundHTMLParser.h:
+ (WebCore):
+ (WebCore::BackgroundHTMLParser::create):
+ (BackgroundHTMLParser):
+ * html/parser/HTMLDocumentParser.cpp:
+ (WebCore::HTMLDocumentParser::pumpTokenizer):
+ (WebCore::HTMLDocumentParser::startBackgroundParser):
+ * html/parser/HTMLSourceTracker.cpp:
+ (WebCore::HTMLSourceTracker::start):
+ (WebCore::HTMLSourceTracker::end):
+ * html/parser/HTMLSourceTracker.h: Change the HTMLInputStream args to SegmentedString because the background thread only has a BackgroundHTMLInputStream.
+ (HTMLSourceTracker):
+ * html/parser/HTMLViewSourceParser.cpp:
+ (WebCore::HTMLViewSourceParser::pumpTokenizer):
+ * html/parser/XSSAuditor.cpp:
+ (WebCore::fullyDecodeString):
+ (WebCore::XSSAuditor::XSSAuditor):
+ (WebCore::XSSAuditor::init): Copies necessary to make isSafeToSendToAnotherThread() happy.
+ (WebCore::XSSAuditor::decodedSnippetForName):
+ (WebCore::XSSAuditor::decodedSnippetForAttribute):
+ (WebCore::XSSAuditor::decodedSnippetForJavaScript):
+ (WebCore::XSSAuditor::isSafeToSendToAnotherThread): Check that all String and KURL members are safe to send to another thread.
+ (WebCore):
+ * html/parser/XSSAuditor.h:
+ (WebCore):
+ (WebCore::FilterTokenRequest::FilterTokenRequest):
+ (FilterTokenRequest):
+ (XSSAuditor):
+
2013-02-07 ChangSeok Oh <[email protected]>
[GTK][AC] Implement opacity animation with clutter ac backend
Modified: trunk/Source/WebCore/html/parser/BackgroundHTMLParser.cpp (142098 => 142099)
--- trunk/Source/WebCore/html/parser/BackgroundHTMLParser.cpp 2013-02-07 12:57:12 UTC (rev 142098)
+++ trunk/Source/WebCore/html/parser/BackgroundHTMLParser.cpp 2013-02-07 13:01:02 UTC (rev 142099)
@@ -36,6 +36,7 @@
#include "HTMLTokenizer.h"
#include "MathMLNames.h"
#include "SVGNames.h"
+#include "XSSAuditor.h"
#include <wtf/MainThread.h>
#include <wtf/Vector.h>
#include <wtf/text/TextPosition.h>
@@ -71,13 +72,14 @@
return m_backgroundParsers;
}
-BackgroundHTMLParser::BackgroundHTMLParser(const HTMLParserOptions& options, const WeakPtr<HTMLDocumentParser>& parser)
+BackgroundHTMLParser::BackgroundHTMLParser(const HTMLParserOptions& options, const WeakPtr<HTMLDocumentParser>& parser, PassOwnPtr<XSSAuditor> xssAuditor)
: m_inForeignContent(false)
, m_token(adoptPtr(new HTMLToken))
, m_tokenizer(HTMLTokenizer::create(options))
, m_options(options)
, m_parser(parser)
, m_pendingTokens(adoptPtr(new CompactHTMLTokenStream))
+ , m_xssAuditor(xssAuditor)
{
}
@@ -152,9 +154,20 @@
void BackgroundHTMLParser::pumpTokenizer()
{
- while (m_tokenizer->nextToken(m_input.current(), *m_token.get())) {
- // FIXME: Call m_xssAuditor.filterToken(m_token) and put resulting XSSInfo into CompactHTMLToken.
- m_pendingTokens->append(CompactHTMLToken(m_token.get(), TextPosition(m_input.current().currentLine(), m_input.current().currentColumn())));
+ while (true) {
+ m_sourceTracker.start(m_input.current(), m_tokenizer.get(), *m_token);
+ if (!m_tokenizer->nextToken(m_input.current(), *m_token.get()))
+ break;
+ m_sourceTracker.end(m_input.current(), m_tokenizer.get(), *m_token);
+
+ {
+ OwnPtr<XSSInfo> xssInfo = m_xssAuditor->filterToken(FilterTokenRequest(*m_token, m_sourceTracker, m_tokenizer->shouldAllowCDATA()));
+ CompactHTMLToken token(m_token.get(), TextPosition(m_input.current().currentLine(), m_input.current().currentColumn()));
+ if (xssInfo)
+ token.setXSSInfo(xssInfo.release());
+ m_pendingTokens->append(token);
+ }
+
m_token->clear();
if (!simulateTreeBuilder(m_pendingTokens->last()) || m_pendingTokens->size() >= pendingTokenLimit)
@@ -181,10 +194,10 @@
m_pendingTokens = adoptPtr(new CompactHTMLTokenStream);
}
-void BackgroundHTMLParser::createPartial(ParserIdentifier identifier, const HTMLParserOptions& options, const WeakPtr<HTMLDocumentParser>& parser)
+void BackgroundHTMLParser::createPartial(ParserIdentifier identifier, const HTMLParserOptions& options, const WeakPtr<HTMLDocumentParser>& parser, PassOwnPtr<XSSAuditor> xssAuditor)
{
ASSERT(!parserMap().backgroundParsers().get(identifier));
- parserMap().backgroundParsers().set(identifier, BackgroundHTMLParser::create(options, parser));
+ parserMap().backgroundParsers().set(identifier, BackgroundHTMLParser::create(options, parser, xssAuditor));
}
void BackgroundHTMLParser::stopPartial(ParserIdentifier identifier)
Modified: trunk/Source/WebCore/html/parser/BackgroundHTMLParser.h (142098 => 142099)
--- trunk/Source/WebCore/html/parser/BackgroundHTMLParser.h 2013-02-07 12:57:12 UTC (rev 142098)
+++ trunk/Source/WebCore/html/parser/BackgroundHTMLParser.h 2013-02-07 13:01:02 UTC (rev 142099)
@@ -31,14 +31,18 @@
#include "BackgroundHTMLInputStream.h"
#include "CompactHTMLToken.h"
#include "HTMLParserOptions.h"
+#include "HTMLSourceTracker.h"
#include "HTMLToken.h"
#include "HTMLTokenizer.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefPtr.h>
#include <wtf/WeakPtr.h>
namespace WebCore {
typedef const void* ParserIdentifier;
class HTMLDocumentParser;
+class XSSAuditor;
class BackgroundHTMLParser {
WTF_MAKE_FAST_ALLOCATED;
@@ -47,19 +51,19 @@
void resumeFrom(const WeakPtr<HTMLDocumentParser>&, PassOwnPtr<HTMLToken>, PassOwnPtr<HTMLTokenizer>, HTMLInputCheckpoint);
void finish();
- static PassOwnPtr<BackgroundHTMLParser> create(const HTMLParserOptions& options, const WeakPtr<HTMLDocumentParser>& parser)
+ static PassOwnPtr<BackgroundHTMLParser> create(const HTMLParserOptions& options, const WeakPtr<HTMLDocumentParser>& parser, PassOwnPtr<XSSAuditor> xssAuditor)
{
- return adoptPtr(new BackgroundHTMLParser(options, parser));
+ return adoptPtr(new BackgroundHTMLParser(options, parser, xssAuditor));
}
- static void createPartial(ParserIdentifier, const HTMLParserOptions&, const WeakPtr<HTMLDocumentParser>&);
+ static void createPartial(ParserIdentifier, const HTMLParserOptions&, const WeakPtr<HTMLDocumentParser>&, PassOwnPtr<XSSAuditor>);
static void stopPartial(ParserIdentifier);
static void appendPartial(ParserIdentifier, const String& input);
static void resumeFromPartial(ParserIdentifier, const WeakPtr<HTMLDocumentParser>&, PassOwnPtr<HTMLToken>, PassOwnPtr<HTMLTokenizer>, HTMLInputCheckpoint);
static void finishPartial(ParserIdentifier);
private:
- BackgroundHTMLParser(const HTMLParserOptions&, const WeakPtr<HTMLDocumentParser>&);
+ BackgroundHTMLParser(const HTMLParserOptions&, const WeakPtr<HTMLDocumentParser>&, PassOwnPtr<XSSAuditor>);
void markEndOfFile();
void pumpTokenizer();
@@ -69,11 +73,13 @@
bool m_inForeignContent; // FIXME: We need a stack of foreign content markers.
BackgroundHTMLInputStream m_input;
+ HTMLSourceTracker m_sourceTracker;
OwnPtr<HTMLToken> m_token;
OwnPtr<HTMLTokenizer> m_tokenizer;
HTMLParserOptions m_options;
WeakPtr<HTMLDocumentParser> m_parser;
OwnPtr<CompactHTMLTokenStream> m_pendingTokens;
+ OwnPtr<XSSAuditor> m_xssAuditor;
};
class ParserMap {
Modified: trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp (142098 => 142099)
--- trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp 2013-02-07 12:57:12 UTC (rev 142098)
+++ trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp 2013-02-07 13:01:02 UTC (rev 142099)
@@ -30,6 +30,7 @@
#include "CompactHTMLToken.h"
#include "ContentSecurityPolicy.h"
#include "DocumentFragment.h"
+#include "DocumentLoader.h"
#include "Element.h"
#include "Frame.h"
#include "HTMLNames.h"
@@ -368,17 +369,17 @@
while (canTakeNextToken(mode, session) && !session.needsYield) {
if (!isParsingFragment())
- m_sourceTracker.start(m_input, m_tokenizer.get(), token());
+ m_sourceTracker.start(m_input.current(), m_tokenizer.get(), token());
if (!m_tokenizer->nextToken(m_input.current(), token()))
break;
if (!isParsingFragment()) {
- m_sourceTracker.end(m_input, m_tokenizer.get(), token());
+ m_sourceTracker.end(m_input.current(), m_tokenizer.get(), token());
// We do not XSS filter innerHTML, which means we (intentionally) fail
// http/tests/security/xssAuditor/dom-write-innerHTML.html
- if (OwnPtr<XSSInfo> xssInfo = m_xssAuditor.filterToken(FilterTokenRequest(token(), m_sourceTracker, document()->decoder(), m_tokenizer->shouldAllowCDATA())))
+ if (OwnPtr<XSSInfo> xssInfo = m_xssAuditor.filterToken(FilterTokenRequest(token(), m_sourceTracker, m_tokenizer->shouldAllowCDATA())))
m_xssAuditorDelegate.didBlockScript(*xssInfo);
}
@@ -511,9 +512,12 @@
ASSERT(!m_haveBackgroundParser);
m_haveBackgroundParser = true;
+ WeakPtr<HTMLDocumentParser> parser = m_weakFactory.createWeakPtr();
+ OwnPtr<XSSAuditor> xssAuditor = adoptPtr(new XSSAuditor);
+ xssAuditor->init(document());
+ ASSERT(xssAuditor->isSafeToSendToAnotherThread());
ParserIdentifier identifier = ParserMap::identifierForParser(this);
- WeakPtr<HTMLDocumentParser> parser = m_weakFactory.createWeakPtr();
- HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::createPartial, identifier, m_options, parser));
+ HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::createPartial, identifier, m_options, parser, xssAuditor.release()));
}
void HTMLDocumentParser::stopBackgroundParser()
Modified: trunk/Source/WebCore/html/parser/HTMLSourceTracker.cpp (142098 => 142099)
--- trunk/Source/WebCore/html/parser/HTMLSourceTracker.cpp 2013-02-07 12:57:12 UTC (rev 142098)
+++ trunk/Source/WebCore/html/parser/HTMLSourceTracker.cpp 2013-02-07 13:01:02 UTC (rev 142099)
@@ -34,7 +34,7 @@
{
}
-void HTMLSourceTracker::start(const HTMLInputStream& input, HTMLTokenizer* tokenizer, HTMLToken& token)
+void HTMLSourceTracker::start(SegmentedString& currentInput, HTMLTokenizer* tokenizer, HTMLToken& token)
{
if (token.type() == HTMLTokenTypes::Uninitialized) {
m_previousSource.clear();
@@ -43,16 +43,16 @@
} else
m_previousSource.append(m_currentSource);
- m_currentSource = input.current();
+ m_currentSource = currentInput;
token.setBaseOffset(m_currentSource.numberOfCharactersConsumed() - m_previousSource.length());
}
-void HTMLSourceTracker::end(const HTMLInputStream& input, HTMLTokenizer* tokenizer, HTMLToken& token)
+void HTMLSourceTracker::end(SegmentedString& currentInput, HTMLTokenizer* tokenizer, HTMLToken& token)
{
m_cachedSourceForToken = String();
// FIXME: This work should really be done by the HTMLTokenizer.
- token.end(input.current().numberOfCharactersConsumed() - tokenizer->numberOfBufferedCharacters());
+ token.end(currentInput.numberOfCharactersConsumed() - tokenizer->numberOfBufferedCharacters());
}
String HTMLSourceTracker::sourceForToken(const HTMLToken& token)
Modified: trunk/Source/WebCore/html/parser/HTMLSourceTracker.h (142098 => 142099)
--- trunk/Source/WebCore/html/parser/HTMLSourceTracker.h 2013-02-07 12:57:12 UTC (rev 142098)
+++ trunk/Source/WebCore/html/parser/HTMLSourceTracker.h 2013-02-07 13:01:02 UTC (rev 142099)
@@ -26,8 +26,8 @@
#ifndef HTMLSourceTracker_h
#define HTMLSourceTracker_h
-#include "HTMLInputStream.h"
#include "HTMLToken.h"
+#include "SegmentedString.h"
#include <wtf/text/StringBuilder.h>
namespace WebCore {
@@ -42,8 +42,8 @@
// FIXME: Once we move "end" into HTMLTokenizer, rename "start" to
// something that makes it obvious that this method can be called multiple
// times.
- void start(const HTMLInputStream&, HTMLTokenizer*, HTMLToken&);
- void end(const HTMLInputStream&, HTMLTokenizer*, HTMLToken&);
+ void start(SegmentedString&, HTMLTokenizer*, HTMLToken&);
+ void end(SegmentedString&, HTMLTokenizer*, HTMLToken&);
String sourceForToken(const HTMLToken&);
Modified: trunk/Source/WebCore/html/parser/HTMLViewSourceParser.cpp (142098 => 142099)
--- trunk/Source/WebCore/html/parser/HTMLViewSourceParser.cpp 2013-02-07 12:57:12 UTC (rev 142098)
+++ trunk/Source/WebCore/html/parser/HTMLViewSourceParser.cpp 2013-02-07 13:01:02 UTC (rev 142099)
@@ -51,10 +51,10 @@
void HTMLViewSourceParser::pumpTokenizer()
{
while (true) {
- m_sourceTracker.start(m_input, m_tokenizer.get(), m_token);
+ m_sourceTracker.start(m_input.current(), m_tokenizer.get(), m_token);
if (!m_tokenizer->nextToken(m_input.current(), m_token))
break;
- m_sourceTracker.end(m_input, m_tokenizer.get(), m_token);
+ m_sourceTracker.end(m_input.current(), m_tokenizer.get(), m_token);
document()->addSource(sourceForToken(), m_token);
updateTokenizerState();
Modified: trunk/Source/WebCore/html/parser/XSSAuditor.cpp (142098 => 142099)
--- trunk/Source/WebCore/html/parser/XSSAuditor.cpp 2013-02-07 12:57:12 UTC (rev 142098)
+++ trunk/Source/WebCore/html/parser/XSSAuditor.cpp 2013-02-07 13:01:02 UTC (rev 142099)
@@ -160,9 +160,8 @@
return decodeEscapeSequences<URLEscapeSequence>(string, encoding);
}
-static String fullyDecodeString(const String& string, const TextResourceDecoder* decoder)
+static String fullyDecodeString(const String& string, const TextEncoding& encoding)
{
- const TextEncoding& encoding = decoder ? decoder->encoding() : UTF8Encoding();
size_t oldWorkingStringLength;
String workingString = string;
do {
@@ -179,6 +178,7 @@
, m_xssProtection(XSSProtectionEnabled)
, m_state(Uninitialized)
, m_scriptTagNestingLevel(0)
+ , m_encoding(UTF8Encoding())
{
// Although tempting to call init() at this point, the various objects
// we want to reference might not all have been constructed yet.
@@ -202,7 +202,7 @@
if (!m_isEnabled)
return;
- m_documentURL = document->url();
+ m_documentURL = document->url().copy();
// In theory, the Document could have detached from the Frame after the
// XSSAuditor was constructed.
@@ -222,8 +222,10 @@
return;
}
- TextResourceDecoder* decoder = document->decoder();
- m_decodedURL = fullyDecodeString(m_documentURL.string(), decoder);
+ if (document->decoder())
+ m_encoding = document->decoder()->encoding();
+
+ m_decodedURL = fullyDecodeString(m_documentURL.string(), m_encoding);
if (m_decodedURL.find(isRequiredForInjection) == notFound)
m_decodedURL = String();
@@ -254,7 +256,7 @@
if (httpBody && !httpBody->isEmpty()) {
httpBodyAsString = httpBody->flattenToString();
if (!httpBodyAsString.isEmpty()) {
- m_decodedHTTPBody = fullyDecodeString(httpBodyAsString, decoder);
+ m_decodedHTTPBody = fullyDecodeString(httpBodyAsString, m_encoding);
if (m_decodedHTTPBody.find(isRequiredForInjection) == notFound)
m_decodedHTTPBody = String();
if (m_decodedHTTPBody.length() >= miniumLengthForSuffixTree)
@@ -270,7 +272,7 @@
if (!m_reportURL.isEmpty()) {
// May need these for reporting later on.
- m_originalURL = m_documentURL;
+ m_originalURL = m_documentURL.copy();
m_originalHTTPBody = httpBodyAsString;
}
}
@@ -507,7 +509,7 @@
String XSSAuditor::decodedSnippetForName(const FilterTokenRequest& request)
{
// Grab a fixed number of characters equal to the length of the token's name plus one (to account for the "<").
- return fullyDecodeString(request.sourceTracker.sourceForToken(request.token), request.decoder).substring(0, request.token.name().size() + 1);
+ return fullyDecodeString(request.sourceTracker.sourceForToken(request.token), m_encoding).substring(0, request.token.name().size() + 1);
}
String XSSAuditor::decodedSnippetForAttribute(const FilterTokenRequest& request, const HTMLToken::Attribute& attribute, AttributeKind treatment)
@@ -518,7 +520,7 @@
// FIXME: We should grab one character before the name also.
int start = attribute.m_nameRange.m_start - request.token.startIndex();
int end = attribute.m_valueRange.m_end - request.token.startIndex();
- String decodedSnippet = fullyDecodeString(request.sourceTracker.sourceForToken(request.token).substring(start, end - start), request.decoder);
+ String decodedSnippet = fullyDecodeString(request.sourceTracker.sourceForToken(request.token).substring(start, end - start), m_encoding);
decodedSnippet.truncate(kMaximumFragmentLengthTarget);
if (treatment == SrcLikeAttribute) {
int slashCount = 0;
@@ -626,7 +628,7 @@
}
}
- result = fullyDecodeString(string.substring(startPosition, foundPosition - startPosition), request.decoder);
+ result = fullyDecodeString(string.substring(startPosition, foundPosition - startPosition), m_encoding);
startPosition = foundPosition + 1;
}
return result;
@@ -664,4 +666,15 @@
return (m_documentURL.host() == resourceURL.host() && resourceURL.query().isEmpty());
}
+bool XSSAuditor::isSafeToSendToAnotherThread() const
+{
+ return m_documentURL.isSafeToSendToAnotherThread()
+ && m_originalURL.isSafeToSendToAnotherThread()
+ && m_originalHTTPBody.isSafeToSendToAnotherThread()
+ && m_decodedURL.isSafeToSendToAnotherThread()
+ && m_decodedHTTPBody.isSafeToSendToAnotherThread()
+ && m_cachedDecodedSnippet.isSafeToSendToAnotherThread()
+ && m_reportURL.isSafeToSendToAnotherThread();
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/html/parser/XSSAuditor.h (142098 => 142099)
--- trunk/Source/WebCore/html/parser/XSSAuditor.h 2013-02-07 12:57:12 UTC (rev 142098)
+++ trunk/Source/WebCore/html/parser/XSSAuditor.h 2013-02-07 13:01:02 UTC (rev 142099)
@@ -29,6 +29,7 @@
#include "HTMLToken.h"
#include "HTTPParsers.h"
#include "SuffixTree.h"
+#include "TextEncoding.h"
#include <wtf/PassOwnPtr.h>
namespace WebCore {
@@ -36,20 +37,17 @@
class Document;
class HTMLDocumentParser;
class HTMLSourceTracker;
-class TextResourceDecoder;
class XSSInfo;
struct FilterTokenRequest {
- FilterTokenRequest(HTMLToken& token, HTMLSourceTracker& sourceTracker, const TextResourceDecoder* decoder, bool shouldAllowCDATA)
+ FilterTokenRequest(HTMLToken& token, HTMLSourceTracker& sourceTracker, bool shouldAllowCDATA)
: token(token)
, sourceTracker(sourceTracker)
- , decoder(decoder)
, shouldAllowCDATA(shouldAllowCDATA)
{ }
HTMLToken& token;
HTMLSourceTracker& sourceTracker;
- const TextResourceDecoder* decoder;
bool shouldAllowCDATA;
};
@@ -60,6 +58,7 @@
void init(Document*);
PassOwnPtr<XSSInfo> filterToken(const FilterTokenRequest&);
+ bool isSafeToSendToAnotherThread() const;
private:
static const size_t kMaximumFragmentLengthTarget = 100;
@@ -113,6 +112,7 @@
String m_cachedDecodedSnippet;
unsigned m_scriptTagNestingLevel;
KURL m_reportURL;
+ TextEncoding m_encoding;
};
}