Changeset 142099 in webkit
- Timestamp:
- Feb 7, 2013 5:01:02 AM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r142094 r142099 1 2013-02-07 Tony Gentilcore <tonyg@chromium.org> 2 3 Call XSSAuditor.filterToken() from threaded HTML parser 4 https://bugs.webkit.org/show_bug.cgi?id=107603 5 6 Reviewed by Adam Barth. 7 8 With this patch we now pass 180 of 182 tests in http/tests/security/xssAuditor. 9 10 We do this by creating aan XSSAuditor on the main thread and passing ownership of them to the BackgroundHTMLParser upon its creation. 11 12 Then the background thread calls filterToken() and stores the resulting XSSInfo (if any) on the CompactHTMLToken for the main thread to handle. 13 14 This involved trimming the XSSAuditor to only depend on the TextEncoding instead of the whole TextResourceDecoder. 15 16 No new tests because covered by existing tests. 17 18 * html/parser/BackgroundHTMLParser.cpp: 19 (WebCore::BackgroundHTMLParser::BackgroundHTMLParser): 20 (WebCore::BackgroundHTMLParser::pumpTokenizer): 21 (WebCore::BackgroundHTMLParser::createPartial): 22 * html/parser/BackgroundHTMLParser.h: 23 (WebCore): 24 (WebCore::BackgroundHTMLParser::create): 25 (BackgroundHTMLParser): 26 * html/parser/HTMLDocumentParser.cpp: 27 (WebCore::HTMLDocumentParser::pumpTokenizer): 28 (WebCore::HTMLDocumentParser::startBackgroundParser): 29 * html/parser/HTMLSourceTracker.cpp: 30 (WebCore::HTMLSourceTracker::start): 31 (WebCore::HTMLSourceTracker::end): 32 * html/parser/HTMLSourceTracker.h: Change the HTMLInputStream args to SegmentedString because the background thread only has a BackgroundHTMLInputStream. 33 (HTMLSourceTracker): 34 * html/parser/HTMLViewSourceParser.cpp: 35 (WebCore::HTMLViewSourceParser::pumpTokenizer): 36 * html/parser/XSSAuditor.cpp: 37 (WebCore::fullyDecodeString): 38 (WebCore::XSSAuditor::XSSAuditor): 39 (WebCore::XSSAuditor::init): Copies necessary to make isSafeToSendToAnotherThread() happy. 40 (WebCore::XSSAuditor::decodedSnippetForName): 41 (WebCore::XSSAuditor::decodedSnippetForAttribute): 42 (WebCore::XSSAuditor::decodedSnippetForJavaScript): 43 (WebCore::XSSAuditor::isSafeToSendToAnotherThread): Check that all String and KURL members are safe to send to another thread. 44 (WebCore): 45 * html/parser/XSSAuditor.h: 46 (WebCore): 47 (WebCore::FilterTokenRequest::FilterTokenRequest): 48 (FilterTokenRequest): 49 (XSSAuditor): 50 1 51 2013-02-07 ChangSeok Oh <shivamidow@gmail.com> 2 52 -
trunk/Source/WebCore/html/parser/BackgroundHTMLParser.cpp
r142004 r142099 37 37 #include "MathMLNames.h" 38 38 #include "SVGNames.h" 39 #include "XSSAuditor.h" 39 40 #include <wtf/MainThread.h> 40 41 #include <wtf/Vector.h> … … 72 73 } 73 74 74 BackgroundHTMLParser::BackgroundHTMLParser(const HTMLParserOptions& options, const WeakPtr<HTMLDocumentParser>& parser )75 BackgroundHTMLParser::BackgroundHTMLParser(const HTMLParserOptions& options, const WeakPtr<HTMLDocumentParser>& parser, PassOwnPtr<XSSAuditor> xssAuditor) 75 76 : m_inForeignContent(false) 76 77 , m_token(adoptPtr(new HTMLToken)) … … 79 80 , m_parser(parser) 80 81 , m_pendingTokens(adoptPtr(new CompactHTMLTokenStream)) 82 , m_xssAuditor(xssAuditor) 81 83 { 82 84 } … … 153 155 void BackgroundHTMLParser::pumpTokenizer() 154 156 { 155 while (m_tokenizer->nextToken(m_input.current(), *m_token.get())) { 156 // FIXME: Call m_xssAuditor.filterToken(m_token) and put resulting XSSInfo into CompactHTMLToken. 157 m_pendingTokens->append(CompactHTMLToken(m_token.get(), TextPosition(m_input.current().currentLine(), m_input.current().currentColumn()))); 157 while (true) { 158 m_sourceTracker.start(m_input.current(), m_tokenizer.get(), *m_token); 159 if (!m_tokenizer->nextToken(m_input.current(), *m_token.get())) 160 break; 161 m_sourceTracker.end(m_input.current(), m_tokenizer.get(), *m_token); 162 163 { 164 OwnPtr<XSSInfo> xssInfo = m_xssAuditor->filterToken(FilterTokenRequest(*m_token, m_sourceTracker, m_tokenizer->shouldAllowCDATA())); 165 CompactHTMLToken token(m_token.get(), TextPosition(m_input.current().currentLine(), m_input.current().currentColumn())); 166 if (xssInfo) 167 token.setXSSInfo(xssInfo.release()); 168 m_pendingTokens->append(token); 169 } 170 158 171 m_token->clear(); 159 172 … … 182 195 } 183 196 184 void BackgroundHTMLParser::createPartial(ParserIdentifier identifier, const HTMLParserOptions& options, const WeakPtr<HTMLDocumentParser>& parser )197 void BackgroundHTMLParser::createPartial(ParserIdentifier identifier, const HTMLParserOptions& options, const WeakPtr<HTMLDocumentParser>& parser, PassOwnPtr<XSSAuditor> xssAuditor) 185 198 { 186 199 ASSERT(!parserMap().backgroundParsers().get(identifier)); 187 parserMap().backgroundParsers().set(identifier, BackgroundHTMLParser::create(options, parser ));200 parserMap().backgroundParsers().set(identifier, BackgroundHTMLParser::create(options, parser, xssAuditor)); 188 201 } 189 202 -
trunk/Source/WebCore/html/parser/BackgroundHTMLParser.h
r141363 r142099 32 32 #include "CompactHTMLToken.h" 33 33 #include "HTMLParserOptions.h" 34 #include "HTMLSourceTracker.h" 34 35 #include "HTMLToken.h" 35 36 #include "HTMLTokenizer.h" 37 #include <wtf/PassOwnPtr.h> 38 #include <wtf/RefPtr.h> 36 39 #include <wtf/WeakPtr.h> 37 40 … … 40 43 typedef const void* ParserIdentifier; 41 44 class HTMLDocumentParser; 45 class XSSAuditor; 42 46 43 47 class BackgroundHTMLParser { … … 48 52 void finish(); 49 53 50 static PassOwnPtr<BackgroundHTMLParser> create(const HTMLParserOptions& options, const WeakPtr<HTMLDocumentParser>& parser )54 static PassOwnPtr<BackgroundHTMLParser> create(const HTMLParserOptions& options, const WeakPtr<HTMLDocumentParser>& parser, PassOwnPtr<XSSAuditor> xssAuditor) 51 55 { 52 return adoptPtr(new BackgroundHTMLParser(options, parser ));56 return adoptPtr(new BackgroundHTMLParser(options, parser, xssAuditor)); 53 57 } 54 58 55 static void createPartial(ParserIdentifier, const HTMLParserOptions&, const WeakPtr<HTMLDocumentParser>& );59 static void createPartial(ParserIdentifier, const HTMLParserOptions&, const WeakPtr<HTMLDocumentParser>&, PassOwnPtr<XSSAuditor>); 56 60 static void stopPartial(ParserIdentifier); 57 61 static void appendPartial(ParserIdentifier, const String& input); … … 60 64 61 65 private: 62 BackgroundHTMLParser(const HTMLParserOptions&, const WeakPtr<HTMLDocumentParser>& );66 BackgroundHTMLParser(const HTMLParserOptions&, const WeakPtr<HTMLDocumentParser>&, PassOwnPtr<XSSAuditor>); 63 67 64 68 void markEndOfFile(); … … 70 74 bool m_inForeignContent; // FIXME: We need a stack of foreign content markers. 71 75 BackgroundHTMLInputStream m_input; 76 HTMLSourceTracker m_sourceTracker; 72 77 OwnPtr<HTMLToken> m_token; 73 78 OwnPtr<HTMLTokenizer> m_tokenizer; … … 75 80 WeakPtr<HTMLDocumentParser> m_parser; 76 81 OwnPtr<CompactHTMLTokenStream> m_pendingTokens; 82 OwnPtr<XSSAuditor> m_xssAuditor; 77 83 }; 78 84 -
trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp
r142004 r142099 31 31 #include "ContentSecurityPolicy.h" 32 32 #include "DocumentFragment.h" 33 #include "DocumentLoader.h" 33 34 #include "Element.h" 34 35 #include "Frame.h" … … 369 370 while (canTakeNextToken(mode, session) && !session.needsYield) { 370 371 if (!isParsingFragment()) 371 m_sourceTracker.start(m_input , m_tokenizer.get(), token());372 m_sourceTracker.start(m_input.current(), m_tokenizer.get(), token()); 372 373 373 374 if (!m_tokenizer->nextToken(m_input.current(), token())) … … 375 376 376 377 if (!isParsingFragment()) { 377 m_sourceTracker.end(m_input , m_tokenizer.get(), token());378 m_sourceTracker.end(m_input.current(), m_tokenizer.get(), token()); 378 379 379 380 // We do not XSS filter innerHTML, which means we (intentionally) fail 380 381 // http/tests/security/xssAuditor/dom-write-innerHTML.html 381 if (OwnPtr<XSSInfo> xssInfo = m_xssAuditor.filterToken(FilterTokenRequest(token(), m_sourceTracker, document()->decoder(),m_tokenizer->shouldAllowCDATA())))382 if (OwnPtr<XSSInfo> xssInfo = m_xssAuditor.filterToken(FilterTokenRequest(token(), m_sourceTracker, m_tokenizer->shouldAllowCDATA()))) 382 383 m_xssAuditorDelegate.didBlockScript(*xssInfo); 383 384 } … … 512 513 m_haveBackgroundParser = true; 513 514 515 WeakPtr<HTMLDocumentParser> parser = m_weakFactory.createWeakPtr(); 516 OwnPtr<XSSAuditor> xssAuditor = adoptPtr(new XSSAuditor); 517 xssAuditor->init(document()); 518 ASSERT(xssAuditor->isSafeToSendToAnotherThread()); 514 519 ParserIdentifier identifier = ParserMap::identifierForParser(this); 515 WeakPtr<HTMLDocumentParser> parser = m_weakFactory.createWeakPtr(); 516 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::createPartial, identifier, m_options, parser)); 520 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::createPartial, identifier, m_options, parser, xssAuditor.release())); 517 521 } 518 522 -
trunk/Source/WebCore/html/parser/HTMLSourceTracker.cpp
r124679 r142099 35 35 } 36 36 37 void HTMLSourceTracker::start( const HTMLInputStream& input, HTMLTokenizer* tokenizer, HTMLToken& token)37 void HTMLSourceTracker::start(SegmentedString& currentInput, HTMLTokenizer* tokenizer, HTMLToken& token) 38 38 { 39 39 if (token.type() == HTMLTokenTypes::Uninitialized) { … … 44 44 m_previousSource.append(m_currentSource); 45 45 46 m_currentSource = input.current();46 m_currentSource = currentInput; 47 47 token.setBaseOffset(m_currentSource.numberOfCharactersConsumed() - m_previousSource.length()); 48 48 } 49 49 50 void HTMLSourceTracker::end( const HTMLInputStream& input, HTMLTokenizer* tokenizer, HTMLToken& token)50 void HTMLSourceTracker::end(SegmentedString& currentInput, HTMLTokenizer* tokenizer, HTMLToken& token) 51 51 { 52 52 m_cachedSourceForToken = String(); 53 53 54 54 // FIXME: This work should really be done by the HTMLTokenizer. 55 token.end( input.current().numberOfCharactersConsumed() - tokenizer->numberOfBufferedCharacters());55 token.end(currentInput.numberOfCharactersConsumed() - tokenizer->numberOfBufferedCharacters()); 56 56 } 57 57 -
trunk/Source/WebCore/html/parser/HTMLSourceTracker.h
r103999 r142099 27 27 #define HTMLSourceTracker_h 28 28 29 #include "HTMLInputStream.h"30 29 #include "HTMLToken.h" 30 #include "SegmentedString.h" 31 31 #include <wtf/text/StringBuilder.h> 32 32 … … 43 43 // something that makes it obvious that this method can be called multiple 44 44 // times. 45 void start( const HTMLInputStream&, HTMLTokenizer*, HTMLToken&);46 void end( const HTMLInputStream&, HTMLTokenizer*, HTMLToken&);45 void start(SegmentedString&, HTMLTokenizer*, HTMLToken&); 46 void end(SegmentedString&, HTMLTokenizer*, HTMLToken&); 47 47 48 48 String sourceForToken(const HTMLToken&); -
trunk/Source/WebCore/html/parser/HTMLViewSourceParser.cpp
r140036 r142099 52 52 { 53 53 while (true) { 54 m_sourceTracker.start(m_input , m_tokenizer.get(), m_token);54 m_sourceTracker.start(m_input.current(), m_tokenizer.get(), m_token); 55 55 if (!m_tokenizer->nextToken(m_input.current(), m_token)) 56 56 break; 57 m_sourceTracker.end(m_input , m_tokenizer.get(), m_token);57 m_sourceTracker.end(m_input.current(), m_tokenizer.get(), m_token); 58 58 59 59 document()->addSource(sourceForToken(), m_token); -
trunk/Source/WebCore/html/parser/XSSAuditor.cpp
r142004 r142099 161 161 } 162 162 163 static String fullyDecodeString(const String& string, const TextResourceDecoder* decoder) 164 { 165 const TextEncoding& encoding = decoder ? decoder->encoding() : UTF8Encoding(); 163 static String fullyDecodeString(const String& string, const TextEncoding& encoding) 164 { 166 165 size_t oldWorkingStringLength; 167 166 String workingString = string; … … 180 179 , m_state(Uninitialized) 181 180 , m_scriptTagNestingLevel(0) 181 , m_encoding(UTF8Encoding()) 182 182 { 183 183 // Although tempting to call init() at this point, the various objects … … 203 203 return; 204 204 205 m_documentURL = document->url() ;205 m_documentURL = document->url().copy(); 206 206 207 207 // In theory, the Document could have detached from the Frame after the … … 223 223 } 224 224 225 TextResourceDecoder* decoder = document->decoder(); 226 m_decodedURL = fullyDecodeString(m_documentURL.string(), decoder); 225 if (document->decoder()) 226 m_encoding = document->decoder()->encoding(); 227 228 m_decodedURL = fullyDecodeString(m_documentURL.string(), m_encoding); 227 229 if (m_decodedURL.find(isRequiredForInjection) == notFound) 228 230 m_decodedURL = String(); … … 255 257 httpBodyAsString = httpBody->flattenToString(); 256 258 if (!httpBodyAsString.isEmpty()) { 257 m_decodedHTTPBody = fullyDecodeString(httpBodyAsString, decoder);259 m_decodedHTTPBody = fullyDecodeString(httpBodyAsString, m_encoding); 258 260 if (m_decodedHTTPBody.find(isRequiredForInjection) == notFound) 259 261 m_decodedHTTPBody = String(); … … 271 273 if (!m_reportURL.isEmpty()) { 272 274 // May need these for reporting later on. 273 m_originalURL = m_documentURL ;275 m_originalURL = m_documentURL.copy(); 274 276 m_originalHTTPBody = httpBodyAsString; 275 277 } … … 508 510 { 509 511 // Grab a fixed number of characters equal to the length of the token's name plus one (to account for the "<"). 510 return fullyDecodeString(request.sourceTracker.sourceForToken(request.token), request.decoder).substring(0, request.token.name().size() + 1);512 return fullyDecodeString(request.sourceTracker.sourceForToken(request.token), m_encoding).substring(0, request.token.name().size() + 1); 511 513 } 512 514 … … 519 521 int start = attribute.m_nameRange.m_start - request.token.startIndex(); 520 522 int end = attribute.m_valueRange.m_end - request.token.startIndex(); 521 String decodedSnippet = fullyDecodeString(request.sourceTracker.sourceForToken(request.token).substring(start, end - start), request.decoder);523 String decodedSnippet = fullyDecodeString(request.sourceTracker.sourceForToken(request.token).substring(start, end - start), m_encoding); 522 524 decodedSnippet.truncate(kMaximumFragmentLengthTarget); 523 525 if (treatment == SrcLikeAttribute) { … … 627 629 } 628 630 629 result = fullyDecodeString(string.substring(startPosition, foundPosition - startPosition), request.decoder);631 result = fullyDecodeString(string.substring(startPosition, foundPosition - startPosition), m_encoding); 630 632 startPosition = foundPosition + 1; 631 633 } … … 665 667 } 666 668 669 bool XSSAuditor::isSafeToSendToAnotherThread() const 670 { 671 return m_documentURL.isSafeToSendToAnotherThread() 672 && m_originalURL.isSafeToSendToAnotherThread() 673 && m_originalHTTPBody.isSafeToSendToAnotherThread() 674 && m_decodedURL.isSafeToSendToAnotherThread() 675 && m_decodedHTTPBody.isSafeToSendToAnotherThread() 676 && m_cachedDecodedSnippet.isSafeToSendToAnotherThread() 677 && m_reportURL.isSafeToSendToAnotherThread(); 678 } 679 667 680 } // namespace WebCore -
trunk/Source/WebCore/html/parser/XSSAuditor.h
r142004 r142099 30 30 #include "HTTPParsers.h" 31 31 #include "SuffixTree.h" 32 #include "TextEncoding.h" 32 33 #include <wtf/PassOwnPtr.h> 33 34 … … 37 38 class HTMLDocumentParser; 38 39 class HTMLSourceTracker; 39 class TextResourceDecoder;40 40 class XSSInfo; 41 41 42 42 struct FilterTokenRequest { 43 FilterTokenRequest(HTMLToken& token, HTMLSourceTracker& sourceTracker, const TextResourceDecoder* decoder,bool shouldAllowCDATA)43 FilterTokenRequest(HTMLToken& token, HTMLSourceTracker& sourceTracker, bool shouldAllowCDATA) 44 44 : token(token) 45 45 , sourceTracker(sourceTracker) 46 , decoder(decoder)47 46 , shouldAllowCDATA(shouldAllowCDATA) 48 47 { } … … 50 49 HTMLToken& token; 51 50 HTMLSourceTracker& sourceTracker; 52 const TextResourceDecoder* decoder;53 51 bool shouldAllowCDATA; 54 52 }; … … 61 59 void init(Document*); 62 60 PassOwnPtr<XSSInfo> filterToken(const FilterTokenRequest&); 61 bool isSafeToSendToAnotherThread() const; 63 62 64 63 private: … … 114 113 unsigned m_scriptTagNestingLevel; 115 114 KURL m_reportURL; 115 TextEncoding m_encoding; 116 116 }; 117 117
Note: See TracChangeset
for help on using the changeset viewer.