Source/WTF/ChangeLog

 12013-02-04 Tony Gentilcore <tonyg@chromium.org>
 2
 3 Call XSSAuditor's didBlockScript() for the threaded HTML parser
 4 https://bugs.webkit.org/show_bug.cgi?id=108726
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 This patch adds isSafeToSendToAnotherThread() methods to CString, String, ParsedURL and URLString.
 9 These methods check to ensure there are 0 or 1 references.
 10
 11 * wtf/text/CString.cpp:
 12 (WTF::CString::isSafeToSendToAnotherThread): Added.
 13 (WTF):
 14 * wtf/text/CString.h:
 15 (CString):
 16 * wtf/text/WTFString.cpp:
 17 (WTF::String::isSafeToSendToAnotherThread): Added.
 18 (WTF):
 19 * wtf/text/WTFString.h:
 20 (String):
 21 * wtf/url/api/ParsedURL.h:
 22 (WTF::ParsedURL::isSafeToSendToAnotherThread): Added.
 23 * wtf/url/api/URLString.h:
 24 (WTF::URLString::isSafeToSendToAnotherThread): Added.
 25
1262013-02-04 David Kilzer <ddkilzer@apple.com>
227
328 Sort WTF Xcode project file

Source/WebCore/ChangeLog

 12013-02-04 Tony Gentilcore <tonyg@chromium.org>
 2
 3 Call XSSAuditor's didBlockScript() for the threaded HTML parser
 4 https://bugs.webkit.org/show_bug.cgi?id=108726
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 This patch causes us to call didBlockScript() on the main thread if the CompactHTML token has XSSInfo.
 9 To do so, we:
 10 1. Rename DidBlockScriptRequest to XSSInfo.
 11 2. Add an OwnPtr<XSSInfo> field to CompactHTMLToken.
 12 3. Add an isSafeToSendToAnotherThread() method to String and KURL.
 13
 14 We don't yet populate didBlockScriptRequest on the background thread, but this should just work once we do.
 15
 16 No new tests because no new functionality.
 17
 18 * html/parser/BackgroundHTMLParser.cpp:
 19 (WebCore::BackgroundHTMLParser::pumpTokenizer): Update comment for rename.
 20 * html/parser/CompactHTMLToken.cpp:
 21 (SameSizeAsCompactHTMLToken):
 22 (WebCore::CompactHTMLToken::CompactHTMLToken): Add a copy constructor used by Vector.
 23 (WebCore::CompactHTMLToken::isSafeToSendToAnotherThread): Include new m_xssInfo field in safety check.
 24 (WebCore):
 25 (WebCore::CompactHTMLToken::xssInfo): Added.
 26 (WebCore::CompactHTMLToken::setXSSInfo): Added.
 27 * html/parser/CompactHTMLToken.h: Add an OwnPtr<XSSInfo> field to CompactHTMLToken.
 28 (WebCore):
 29 (CompactHTMLToken):
 30 (WTF): Add VectorTraits necessary for copying Vector fields objects that contain an OwnPtr.
 31 * html/parser/HTMLDocumentParser.cpp:
 32 (WebCore::HTMLDocumentParser::processParsedChunkFromBackgroundParser): Add new didBlockScript() call.
 33 (WebCore::HTMLDocumentParser::pumpTokenizer):
 34 * html/parser/XSSAuditor.cpp: Renaming.
 35 (WebCore::XSSAuditor::filterToken):
 36 * html/parser/XSSAuditor.h: Renaming.
 37 (WebCore):
 38 (XSSAuditor):
 39 * html/parser/XSSAuditorDelegate.cpp:
 40 (WebCore::XSSInfo::isSafeToSendToAnotherThread):
 41 (WebCore):
 42 (WebCore::XSSAuditorDelegate::didBlockScript):
 43 * html/parser/XSSAuditorDelegate.h:
 44 (WebCore::XSSInfo::create):
 45 (XSSInfo):
 46 (WebCore::XSSInfo::XSSInfo):
 47 (XSSAuditorDelegate):
 48 * platform/KURL.cpp:
 49 (WebCore::KURL::isSafeToSendToAnotherThread): Added.
 50 (WebCore):
 51 * platform/KURL.h:
 52 (KURL):
 53 * platform/KURLGoogle.cpp:
 54 (WebCore):
 55 (WebCore::KURLGooglePrivate::isSafeToSendToAnotherThread): Added.
 56 * platform/KURLGooglePrivate.h:
 57 (KURLGooglePrivate):
 58 * platform/KURLWTFURLImpl.h:
 59 (WebCore::KURLWTFURLImpl::isSafeToSendToAnotherThread): Added.
 60
1612013-02-04 Dominik Röttsches <dominik.rottsches@intel.com>
262
363 [Skia] Argument to HarfBuzzShaper::offsetForPosition unnecessarily truncated

Source/WTF/wtf/text/CString.cpp

@@void CString::copyBufferIfNeeded()
9999 memcpy(m_buffer->mutableData(), buffer->data(), length + 1);
100100}
101101
 102bool CString::isSafeToSendToAnotherThread() const
 103{
 104 return !m_buffer || m_buffer->hasOneRef();
 105}
 106
102107bool operator==(const CString& a, const CString& b)
103108{
104109 if (a.isNull() != b.isNull())

Source/WTF/wtf/text/CString.h

@@public:
7272 }
7373
7474 bool isNull() const { return !m_buffer; }
 75 bool isSafeToSendToAnotherThread() const;
7576
7677 CStringBuffer* buffer() const { return m_buffer.get(); }
7778

Source/WTF/wtf/text/WTFString.cpp

@@String String::isolatedCopy() const
661661 return m_impl->isolatedCopy();
662662}
663663
 664bool String::isSafeToSendToAnotherThread() const
 665{
 666 if (!impl())
 667 return true;
 668 if (impl()->hasOneRef())
 669 return true;
 670 if (isEmpty())
 671 return true;
 672 return false;
 673}
 674
664675void String::split(const String& separator, bool allowEmptyEntries, Vector<String>& result) const
665676{
666677 result.clear();

Source/WTF/wtf/text/WTFString.h

@@public:
394394 bool percentage(int& percentage) const;
395395
396396 WTF_EXPORT_STRING_API String isolatedCopy() const;
 397 bool isSafeToSendToAnotherThread() const;
397398
398399 // Prevent Strings from being implicitly convertable to bool as it will be ambiguous on any platform that
399400 // allows implicit conversion to another pointer type (e.g., Mac allows implicit conversion to NSString*).

Source/WTF/wtf/url/api/ParsedURL.h

@@public:
4949 WTF_EXPORT_PRIVATE explicit ParsedURL(const ParsedURL& base, const String& relative, URLQueryCharsetConverter*);
5050
5151 WTF_EXPORT_PRIVATE ParsedURL isolatedCopy() const;
 52 bool isSafeToSendToAnotherThread() const { return m_spec.isSafeToSendToAnotherThread(); }
5253
5354 bool isValid() const { return !m_spec.string().isNull(); }
5455

Source/WTF/wtf/url/api/URLString.h

@@public:
3939 URLString() { }
4040
4141 const String& string() const { return m_string;}
 42 bool isSafeToSendToAnotherThread() const { return m_string.isSafeToSendToAnotherThread(); }
4243
4344#ifndef NDEBUG
4445 WTF_EXPORT_PRIVATE void print() const;

Source/WebCore/html/parser/BackgroundHTMLParser.cpp

@@bool BackgroundHTMLParser::simulateTreeBuilder(const CompactHTMLToken& token)
153153void BackgroundHTMLParser::pumpTokenizer()
154154{
155155 while (m_tokenizer->nextToken(m_input.current(), *m_token.get())) {
156  // FIXME: Call m_xssAuditor.filterToken(m_token) and put resulting DidBlockScriptRequest into CompactHTMLToken.
 156 // FIXME: Call m_xssAuditor.filterToken(m_token) and put resulting XSSInfo into CompactHTMLToken.
157157 m_pendingTokens->append(CompactHTMLToken(m_token.get(), TextPosition(m_input.current().currentLine(), m_input.current().currentColumn())));
158158 m_token->clear();
159159

Source/WebCore/html/parser/CompactHTMLToken.cpp

3030#include "CompactHTMLToken.h"
3131
3232#include "HTMLToken.h"
 33#include "XSSAuditorDelegate.h"
3334
3435namespace WebCore {
3536

@@struct SameSizeAsCompactHTMLToken {
3839 String name;
3940 Vector<CompactAttribute> vector;
4041 TextPosition textPosition;
 42 OwnPtr<XSSInfo> xssInfo;
4143};
4244
4345COMPILE_ASSERT(sizeof(CompactHTMLToken) == sizeof(SameSizeAsCompactHTMLToken), CompactHTMLToken_should_stay_small);

@@CompactHTMLToken::CompactHTMLToken(const HTMLToken* token, const TextPosition& t
8688 }
8789}
8890
89 static bool isStringSafeToSendToAnotherThread(const String& string)
 91CompactHTMLToken::CompactHTMLToken(const CompactHTMLToken& other)
 92 : m_type(other.type())
 93 , m_isAll8BitData(other.isAll8BitData())
 94 , m_doctypeForcesQuirks(other.doctypeForcesQuirks())
 95 , m_textPosition(other.textPosition())
9096{
91  StringImpl* impl = string.impl();
92  if (!impl)
93  return true;
94  if (impl->hasOneRef())
95  return true;
96  if (string.isEmpty())
97  return true;
98  return false;
 97 if (other.xssInfo())
 98 m_xssInfo = adoptPtr(new XSSInfo(*other.xssInfo()));
9999}
100100
101101bool CompactHTMLToken::isSafeToSendToAnotherThread() const
102102{
103103 for (Vector<CompactAttribute>::const_iterator it = m_attributes.begin(); it != m_attributes.end(); ++it) {
104  if (!isStringSafeToSendToAnotherThread(it->name()))
 104 if (!it->name().isSafeToSendToAnotherThread())
105105 return false;
106  if (!isStringSafeToSendToAnotherThread(it->value()))
 106 if (!it->value().isSafeToSendToAnotherThread())
107107 return false;
108108 }
109  return isStringSafeToSendToAnotherThread(m_data);
 109 if (m_xssInfo && !m_xssInfo->isSafeToSendToAnotherThread())
 110 return false;
 111 return m_data.isSafeToSendToAnotherThread();
 112}
 113
 114XSSInfo* CompactHTMLToken::xssInfo() const
 115{
 116 return m_xssInfo.get();
 117}
 118
 119void CompactHTMLToken::setXSSInfo(PassOwnPtr<XSSInfo> xssInfo)
 120{
 121 m_xssInfo = xssInfo;
110122}
111123
112124}

Source/WebCore/html/parser/CompactHTMLToken.h

2929#if ENABLE(THREADED_HTML_PARSER)
3030
3131#include "HTMLTokenTypes.h"
 32#include <wtf/OwnPtr.h>
 33#include <wtf/PassOwnPtr.h>
3234#include <wtf/RefCounted.h>
3335#include <wtf/RefPtr.h>
3436#include <wtf/Vector.h>

3840namespace WebCore {
3941
4042class HTMLToken;
 43class XSSInfo;
4144
4245class CompactAttribute {
4346public:

@@private:
5861class CompactHTMLToken {
5962public:
6063 CompactHTMLToken(const HTMLToken*, const TextPosition&);
 64 CompactHTMLToken(const CompactHTMLToken&);
6165
6266 bool isSafeToSendToAnotherThread() const;
6367

@@public:
7377 const String& publicIdentifier() const { return m_attributes[0].name(); }
7478 const String& systemIdentifier() const { return m_attributes[0].value(); }
7579 bool doctypeForcesQuirks() const { return m_doctypeForcesQuirks; }
 80 XSSInfo* xssInfo() const;
 81 void setXSSInfo(PassOwnPtr<XSSInfo>);
7682
7783private:
7884 unsigned m_type : 4;

@@private:
8389 String m_data; // "name", "characters", or "data" depending on m_type
8490 Vector<CompactAttribute> m_attributes;
8591 TextPosition m_textPosition;
 92 OwnPtr<XSSInfo> m_xssInfo;
8693};
8794
8895typedef Vector<CompactHTMLToken> CompactHTMLTokenStream;
8996
9097}
9198
 99namespace WTF {
 100// This is required for a struct with OwnPtr. We know CompactHTMLToken is simple enough that
 101// initializing to 0 and moving with memcpy (and then not destructing the original) will work.
 102template<> struct VectorTraits<WebCore::CompactHTMLToken> : SimpleClassVectorTraits { };
 103}
 104
92105#endif // ENABLE(THREADED_HTML_PARSER)
93106
94107#endif

Source/WebCore/html/parser/HTMLDocumentParser.cpp

@@void HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Parse
302302{
303303 ASSERT(shouldUseThreading());
304304
305  // didReceiveTokensFromBackgroundParser can cause this parser to be detached from the Document,
 305 // This method can cause this parser to be detached from the Document,
306306 // but we need to ensure it isn't deleted yet.
307307 RefPtr<HTMLDocumentParser> protect(this);
308308

@@void HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Parse
316316 for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin(); it != tokens->end(); ++it) {
317317 ASSERT(!isWaitingForScripts());
318318
319  // FIXME: Call m_xssAuditorDelegate.didBlockScript() with DidBlockScriptRequest from the CompactHTMLToken.
320319 m_textPosition = it->textPosition();
 320
 321 if (XSSInfo* xssInfo = it->xssInfo())
 322 m_xssAuditorDelegate.didBlockScript(*xssInfo);
321323 constructTreeFromCompactHTMLToken(*it);
322324
323325 if (isStopped())

@@void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode)
378380
379381 // We do not XSS filter innerHTML, which means we (intentionally) fail
380382 // http/tests/security/xssAuditor/dom-write-innerHTML.html
381  OwnPtr<DidBlockScriptRequest> request = m_xssAuditor.filterToken(token());
382  if (request)
383  m_xssAuditorDelegate.didBlockScript(request.release());
 383 if (OwnPtr<XSSInfo> xssInfo = m_xssAuditor.filterToken(token()))
 384 m_xssAuditorDelegate.didBlockScript(*xssInfo);
384385 }
385386
386387 constructTreeFromHTMLToken(token());

Source/WebCore/html/parser/XSSAuditor.cpp

@@void XSSAuditor::init(Document* document)
272272 }
273273}
274274
275 PassOwnPtr<DidBlockScriptRequest> XSSAuditor::filterToken(HTMLToken& token)
 275PassOwnPtr<XSSInfo> XSSAuditor::filterToken(HTMLToken& token)
276276{
277277 ASSERT(m_state == Initialized);
278278 if (!m_isEnabled || m_xssProtection == XSSProtectionDisabled)

@@PassOwnPtr<DidBlockScriptRequest> XSSAuditor::filterToken(HTMLToken& token)
290290
291291 if (didBlockScript) {
292292 bool didBlockEntirePage = (m_xssProtection == XSSProtectionBlockEnabled);
293  OwnPtr<DidBlockScriptRequest> request = DidBlockScriptRequest::create(m_reportURL, m_originalURL, m_originalHTTPBody, didBlockEntirePage);
 293 OwnPtr<XSSInfo> xssInfo = XSSInfo::create(m_reportURL, m_originalURL, m_originalHTTPBody, didBlockEntirePage);
294294 if (!m_reportURL.isEmpty()) {
295295 m_reportURL = KURL();
296296 m_originalURL = String();
297297 m_originalHTTPBody = String();
298298 }
299  return request.release();
 299 return xssInfo.release();
300300 }
301301 return nullptr;
302302}

Source/WebCore/html/parser/XSSAuditor.h

3333
3434namespace WebCore {
3535
36 class DidBlockScriptRequest;
3736class Document;
3837class HTMLDocumentParser;
 38class XSSInfo;
3939
4040class XSSAuditor {
4141 WTF_MAKE_NONCOPYABLE(XSSAuditor);

@@public:
4343 explicit XSSAuditor(HTMLDocumentParser*);
4444
4545 void init(Document*);
46  PassOwnPtr<DidBlockScriptRequest> filterToken(HTMLToken&);
 46 PassOwnPtr<XSSInfo> filterToken(HTMLToken&);
4747
4848private:
4949 static const size_t kMaximumFragmentLengthTarget = 100;

Source/WebCore/html/parser/XSSAuditorDelegate.cpp

3232#include "FormData.h"
3333#include "Frame.h"
3434#include "FrameLoaderClient.h"
 35#include "HTMLParserIdioms.h"
3536#include "InspectorValues.h"
3637#include "PingLoader.h"
3738#include "SecurityOrigin.h"
3839
3940namespace WebCore {
4041
 42bool XSSInfo::isSafeToSendToAnotherThread() const
 43{
 44 return m_reportURL.isSafeToSendToAnotherThread()
 45 && m_originalURL.isSafeToSendToAnotherThread()
 46 && m_originalHTTPBody.isSafeToSendToAnotherThread();
 47}
 48
4149XSSAuditorDelegate::XSSAuditorDelegate(Document* document)
4250 : m_document(document)
4351 , m_didNotifyClient(false)

@@XSSAuditorDelegate::XSSAuditorDelegate(Document* document)
4654 ASSERT(m_document);
4755}
4856
49 void XSSAuditorDelegate::didBlockScript(PassOwnPtr<DidBlockScriptRequest> request)
 57void XSSAuditorDelegate::didBlockScript(const XSSInfo& xssInfo)
5058{
5159 ASSERT(isMainThread());
5260

@@void XSSAuditorDelegate::didBlockScript(PassOwnPtr<DidBlockScriptRequest> reques
5462 DEFINE_STATIC_LOCAL(String, consoleMessage, (ASCIILiteral("Refused to execute a JavaScript script. Source code of script found within request.\n")));
5563 m_document->addConsoleMessage(JSMessageSource, ErrorMessageLevel, consoleMessage);
5664
57  if (request->m_didBlockEntirePage)
 65 if (xssInfo.m_didBlockEntirePage)
5866 m_document->frame()->loader()->stopAllLoaders();
5967
6068 if (!m_didNotifyClient) {
61  m_document->frame()->loader()->client()->didDetectXSS(m_document->url(), request->m_didBlockEntirePage);
 69 m_document->frame()->loader()->client()->didDetectXSS(m_document->url(), xssInfo.m_didBlockEntirePage);
6270 m_didNotifyClient = true;
6371 }
6472
65  if (!request->m_reportURL.isEmpty()) {
 73 if (!xssInfo.m_reportURL.isEmpty()) {
6674 RefPtr<InspectorObject> reportDetails = InspectorObject::create();
67  reportDetails->setString("request-url", request->m_originalURL);
68  reportDetails->setString("request-body", request->m_originalHTTPBody);
 75 reportDetails->setString("request-url", xssInfo.m_originalURL);
 76 reportDetails->setString("request-body", xssInfo.m_originalHTTPBody);
6977
7078 RefPtr<InspectorObject> reportObject = InspectorObject::create();
7179 reportObject->setObject("xss-report", reportDetails.release());
7280
7381 RefPtr<FormData> report = FormData::create(reportObject->toJSONString().utf8().data());
74  PingLoader::sendViolationReport(m_document->frame(), request->m_reportURL, report);
 82 PingLoader::sendViolationReport(m_document->frame(), xssInfo.m_reportURL, report);
7583 }
7684
77  if (request->m_didBlockEntirePage)
 85 if (xssInfo.m_didBlockEntirePage)
7886 m_document->frame()->navigationScheduler()->scheduleLocationChange(m_document->securityOrigin(), blankURL(), String());
7987}
8088

Source/WebCore/html/parser/XSSAuditorDelegate.h

@@namespace WebCore {
3434
3535class Document;
3636
37 class DidBlockScriptRequest {
 37class XSSInfo {
3838public:
39  static PassOwnPtr<DidBlockScriptRequest> create(const KURL& reportURL, const String& originalURL, const String& originalHTTPBody, bool didBlockEntirePage)
 39 static PassOwnPtr<XSSInfo> create(const KURL& reportURL, const String& originalURL, const String& originalHTTPBody, bool didBlockEntirePage)
4040 {
41  return adoptPtr(new DidBlockScriptRequest(reportURL, originalURL, originalHTTPBody, didBlockEntirePage));
 41 return adoptPtr(new XSSInfo(reportURL, originalURL, originalHTTPBody, didBlockEntirePage));
4242 }
4343
 44 bool isSafeToSendToAnotherThread() const;
 45
4446 KURL m_reportURL;
4547 String m_originalURL;
4648 String m_originalHTTPBody;
4749 bool m_didBlockEntirePage;
4850
4951private:
50  DidBlockScriptRequest(const KURL& reportURL, const String& originalURL, const String& originalHTTPBody, bool didBlockEntirePage)
 52 XSSInfo(const KURL& reportURL, const String& originalURL, const String& originalHTTPBody, bool didBlockEntirePage)
5153 : m_reportURL(reportURL)
5254 , m_originalURL(originalURL)
5355 , m_originalHTTPBody(originalHTTPBody)

@@class XSSAuditorDelegate {
6062public:
6163 explicit XSSAuditorDelegate(Document*);
6264
63  void didBlockScript(PassOwnPtr<DidBlockScriptRequest>);
 65 void didBlockScript(const XSSInfo&);
6466
6567private:
6668 Document* m_document;

Source/WebCore/platform/KURL.cpp

@@void KURL::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
19351935#endif
19361936}
19371937
 1938bool KURL::isSafeToSendToAnotherThread() const
 1939{
 1940#if USE(GOOGLEURL)
 1941 return m_url.isSafeToSendToAnotherThread();
 1942#elif USE(WTFURL)
 1943 return m_urlImpl.isSafeToSendToAnotherThread();
 1944#else // !USE(GOOGLEURL)
 1945 return m_string.isSafeToSendToAnotherThread();
 1946#endif
 1947}
 1948
19381949}

Source/WebCore/platform/KURL.h

@@public:
227227#endif
228228
229229 void reportMemoryUsage(MemoryObjectInfo*) const;
 230 bool isSafeToSendToAnotherThread() const;
230231
231232private:
232233 void invalidate();

Source/WebCore/platform/KURLGoogle.cpp

@@void KURLGooglePrivate::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) co
399399 info.addMember(m_innerURL, "innerURL");
400400 info.addMember(m_parsed, "parsed");
401401}
 402
 403bool KURLGooglePrivate::isSafeToSendToAnotherThread() const
 404{
 405 return m_string.isSafeToSendToAnotherThread()
 406 && m_utf8.isSafeToSendToAnotherThread()
 407 && (!m_innerURL || m_innerURL->isSafeToSendToAnotherThread());
 408}
 409
402410// KURL ------------------------------------------------------------------------
403411
404412// Initializes with a string representing an absolute URL. No encoding

Source/WebCore/platform/KURLGooglePrivate.h

@@namespace WebCore {
101101 KURL* innerURL() const { return m_innerURL.get(); }
102102
103103 void reportMemoryUsage(MemoryObjectInfo*) const;
 104 bool isSafeToSendToAnotherThread() const;
104105
105106 private:
106107 void initInnerURL();

Source/WebCore/platform/KURLWTFURLImpl.h

@@public:
4949 info.addMember(m_parsedURL, "parsedURL");
5050 info.addMember(m_invalidUrlString, "invalidUrlString");
5151 }
 52 bool isSafeToSendToAnotherThread() const
 53 {
 54 return m_invalidUrlString.isSafeToSendToAnotherThread()
 55 && m_parsedURL.isSafeToSendToAnotherThread();
 56 }
5257 PassRefPtr<KURLWTFURLImpl> copy() const;
5358};
5459