Diff
Modified: branches/safari-603-branch/Source/WebCore/ChangeLog (214703 => 214704)
--- branches/safari-603-branch/Source/WebCore/ChangeLog 2017-04-01 00:11:08 UTC (rev 214703)
+++ branches/safari-603-branch/Source/WebCore/ChangeLog 2017-04-01 00:20:38 UTC (rev 214704)
@@ -1,3 +1,45 @@
+2017-03-31 Brent Fulgham <[email protected]>
+
+ Merge r214378. rdar://problem/31177657
+
+ 2017-03-24 Brent Fulgham <[email protected]>
+
+ Handle recursive calls to ProcessingInstruction::checkStyleSheet
+ https://bugs.webkit.org/show_bug.cgi?id=169982
+ <rdar://problem/31083051>
+
+ Reviewed by Antti Koivisto.
+
+ See if we triggered a recursive load of the stylesheet during the 'beforeload'
+ event handler. If so, reset to a valid state before completing the load.
+
+ We should also check after 'beforeload' that we were not disconnected from (or
+ moved to a new) document.
+
+ I also looked for other cases of this pattern and fixed them, too.
+
+ Tests: fast/dom/beforeload/image-removed-during-before-load.html
+ fast/dom/beforeload/recursive-css-pi-before-load.html
+ fast/dom/beforeload/recursive-link-before-load.html
+ fast/dom/beforeload/recursive-xsl-pi-before-load.html
+
+ * dom/ProcessingInstruction.cpp:
+ (WebCore::ProcessingInstruction::checkStyleSheet): Prevent recursive calls into
+ this function during 'beforeload' handling. Also, safely handle the case where
+ the element was disconnected in the 'beforeload' handler (similar to what
+ we do in HTMLLinkElement).
+ (WebCore::ProcessingInstruction::setCSSStyleSheet): Drive-by Fix: Protect the
+ current document to match what we do in setXSLStyleSheet.
+ * dom/ProcessingInstruction.h:
+ * html/HTMLLinkElement.cpp:
+ (WebCore::HTMLLinkElement::process): Prevent recursive calls into
+ this function during 'beforeload' handling.
+ * html/HTMLLinkElement.h:
+ * loader/ImageLoader.cpp:
+ (WebCore::ImageLoader::dispatchPendingBeforeLoadEvent): safely handle the case where
+ the element was disconnected in the 'beforeload' handler (similar to what
+ we do in HTMLLinkElement).
+
2017-03-30 Jason Marcell <[email protected]>
Merge r214392. rdar://problem/31356105
Modified: branches/safari-603-branch/Source/WebCore/dom/ProcessingInstruction.cpp (214703 => 214704)
--- branches/safari-603-branch/Source/WebCore/dom/ProcessingInstruction.cpp 2017-04-01 00:11:08 UTC (rev 214703)
+++ branches/safari-603-branch/Source/WebCore/dom/ProcessingInstruction.cpp 2017-04-01 00:20:38 UTC (rev 214704)
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2000 Peter Kelly ([email protected])
- * Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2017 Apple Inc. All rights reserved.
* Copyright (C) 2013 Samsung Electronics. All rights reserved.
*
* This library is free software; you can redistribute it and/or
@@ -35,6 +35,7 @@
#include "StyleSheetContents.h"
#include "XMLDocumentParser.h"
#include "XSLStyleSheet.h"
+#include <wtf/SetForScope.h>
namespace WebCore {
@@ -80,6 +81,10 @@
void ProcessingInstruction::checkStyleSheet()
{
+ // Prevent recursive loading of stylesheet.
+ if (m_isHandlingBeforeLoad)
+ return;
+
if (m_target == "xml-stylesheet" && document().frame() && parentNode() == &document()) {
// see http://www.w3.org/TR/xml-stylesheet/
// ### support stylesheet included in a fragment of this (or another) document
@@ -130,12 +135,24 @@
}
String url = ""
+
+ Ref<Document> originalDocument = document();
+
+ {
+ SetForScope<bool> change(m_isHandlingBeforeLoad, true);
if (!dispatchBeforeLoadEvent(url))
return;
+ }
+ bool didEventListenerDisconnectThisElement = !inDocument() || &document() != originalDocument.ptr();
+ if (didEventListenerDisconnectThisElement)
+ return;
+
m_loading = true;
document().styleScope().addPendingSheet();
+ ASSERT_WITH_SECURITY_IMPLICATION(!m_cachedSheet);
+
#if ENABLE(XSLT)
if (m_isXSL) {
auto options = CachedResourceLoader::defaultCachedResourceOptions();
@@ -206,6 +223,7 @@
// We don't need the cross-origin security check here because we are
// getting the sheet text in "strict" mode. This enforces a valid CSS MIME
// type.
+ Ref<Document> protect(document());
parseStyleSheet(sheet->sheetText());
}
Modified: branches/safari-603-branch/Source/WebCore/dom/ProcessingInstruction.h (214703 => 214704)
--- branches/safari-603-branch/Source/WebCore/dom/ProcessingInstruction.h 2017-04-01 00:11:08 UTC (rev 214703)
+++ branches/safari-603-branch/Source/WebCore/dom/ProcessingInstruction.h 2017-04-01 00:20:38 UTC (rev 214704)
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2000 Peter Kelly ([email protected])
- * Copyright (C) 2006 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2017 Apple Inc. All rights reserved.
* Copyright (C) 2013 Samsung Electronics. All rights reserved.
*
* This library is free software; you can redistribute it and/or
@@ -87,6 +87,7 @@
#if ENABLE(XSLT)
bool m_isXSL { false };
#endif
+ bool m_isHandlingBeforeLoad { false };
};
} // namespace WebCore
Modified: branches/safari-603-branch/Source/WebCore/html/HTMLLinkElement.cpp (214703 => 214704)
--- branches/safari-603-branch/Source/WebCore/html/HTMLLinkElement.cpp 2017-04-01 00:11:08 UTC (rev 214703)
+++ branches/safari-603-branch/Source/WebCore/html/HTMLLinkElement.cpp 2017-04-01 00:20:38 UTC (rev 214704)
@@ -2,7 +2,7 @@
* Copyright (C) 1999 Lars Knoll ([email protected])
* (C) 1999 Antti Koivisto ([email protected])
* (C) 2001 Dirk Mueller ([email protected])
- * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2003-2017 Apple Inc. All rights reserved.
* Copyright (C) 2009 Rob Buis ([email protected])
* Copyright (C) 2011 Google Inc. All rights reserved.
*
@@ -56,6 +56,7 @@
#include "StyleScope.h"
#include "StyleSheetContents.h"
#include <wtf/Ref.h>
+#include <wtf/SetForScope.h>
#include <wtf/StdLibExtras.h>
namespace WebCore {
@@ -225,6 +226,10 @@
return;
}
+ // Prevent recursive loading of link.
+ if (m_isHandlingBeforeLoad)
+ return;
+
URL url = ""
if (!m_linkLoader.loadLink(m_relAttribute, url, attributeWithoutSynchronization(asAttr), attributeWithoutSynchronization(crossoriginAttr), document()))
@@ -244,8 +249,11 @@
m_cachedSheet = nullptr;
}
+ {
+ SetForScope<bool> change(m_isHandlingBeforeLoad, true);
if (!shouldLoadLink())
return;
+ }
m_loading = true;
@@ -279,6 +287,8 @@
request.setAsPotentiallyCrossOrigin(crossOrigin(), document());
+ ASSERT_WITH_SECURITY_IMPLICATION(!m_cachedSheet);
+
m_cachedSheet = document().cachedResourceLoader().requestCSSStyleSheet(WTFMove(request));
if (m_cachedSheet)
Modified: branches/safari-603-branch/Source/WebCore/html/HTMLLinkElement.h (214703 => 214704)
--- branches/safari-603-branch/Source/WebCore/html/HTMLLinkElement.h 2017-04-01 00:11:08 UTC (rev 214703)
+++ branches/safari-603-branch/Source/WebCore/html/HTMLLinkElement.h 2017-04-01 00:20:38 UTC (rev 214704)
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1999 Lars Knoll ([email protected])
* (C) 1999 Antti Koivisto ([email protected])
- * Copyright (C) 2003, 2008, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2003-2017 Apple Inc. All rights reserved.
* Copyright (C) 2011 Google Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
@@ -137,6 +137,7 @@
bool m_createdByParser;
bool m_firedLoad;
bool m_loadedResource;
+ bool m_isHandlingBeforeLoad { false };
PendingSheetType m_pendingSheetType;
Modified: branches/safari-603-branch/Source/WebCore/loader/ImageLoader.cpp (214703 => 214704)
--- branches/safari-603-branch/Source/WebCore/loader/ImageLoader.cpp 2017-04-01 00:11:08 UTC (rev 214703)
+++ branches/safari-603-branch/Source/WebCore/loader/ImageLoader.cpp 2017-04-01 00:20:38 UTC (rev 214704)
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1999 Lars Knoll ([email protected])
* (C) 1999 Antti Koivisto ([email protected])
- * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -395,7 +395,12 @@
if (!element().document().hasLivingRenderTree())
return;
m_hasPendingBeforeLoadEvent = false;
+ Ref<Document> originalDocument = element().document();
if (element().dispatchBeforeLoadEvent(m_image->url())) {
+ bool didEventListenerDisconnectThisElement = !element().inDocument() || &element().document() != originalDocument.ptr();
+ if (didEventListenerDisconnectThisElement)
+ return;
+
updateRenderer();
return;
}
Added: branches/safari-603-branch/Source/fast/dom/beforeload/image-removed-during-before-load-expected.txt (0 => 214704)
--- branches/safari-603-branch/Source/fast/dom/beforeload/image-removed-during-before-load-expected.txt (rev 0)
+++ branches/safari-603-branch/Source/fast/dom/beforeload/image-removed-during-before-load-expected.txt 2017-04-01 00:20:38 UTC (rev 214704)
@@ -0,0 +1,5 @@
+This test confirms that image loading properly handles a 'beforeload' events that removes the image from the document. It passes if no debug assertions are fired.
+
+PASS: Hit the beforeload handler
+PASS
+PASS: No assertions hit.
Added: branches/safari-603-branch/Source/fast/dom/beforeload/image-removed-during-before-load.html (0 => 214704)
--- branches/safari-603-branch/Source/fast/dom/beforeload/image-removed-during-before-load.html (rev 0)
+++ branches/safari-603-branch/Source/fast/dom/beforeload/image-removed-during-before-load.html 2017-04-01 00:20:38 UTC (rev 214704)
@@ -0,0 +1,42 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<script src=""
+<script>
+function test()
+{
+ if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+ }
+
+ image = document.createElement("img");
+ image.setAttribute("style", "display:none");
+ image.addEventListener("load", function() {
+ print('PASS', 'green');
+ }, { once: true });
+ image.addEventListener("beforeload", function() {
+ print('PASS: Hit the beforeload handler', 'green');
+ document.body.removeChild(image);
+ image = null;
+ setTimeout(step2, 0);
+ }, { once: true });
+
+ document.body.appendChild(image);
+
+ image.setAttribute("src", "../../images/resources/test-load.jpg");
+}
+
+function step2()
+{
+ print("PASS: No assertions hit.", "green");
+
+ if (window.testRunner)
+ testRunner.notifyDone();
+}
+</script>
+</head>
+<body _onload_="test()">
+<p>This test confirms that image loading properly handles a 'beforeload' events that removes the image from the document. It passes if no debug assertions are fired.</p>
+<div id="console"></div>
+</body>
+</html>
Added: branches/safari-603-branch/Source/fast/dom/beforeload/recursive-css-pi-before-load-expected.txt (0 => 214704)
--- branches/safari-603-branch/Source/fast/dom/beforeload/recursive-css-pi-before-load-expected.txt (rev 0)
+++ branches/safari-603-branch/Source/fast/dom/beforeload/recursive-css-pi-before-load-expected.txt 2017-04-01 00:20:38 UTC (rev 214704)
@@ -0,0 +1,4 @@
+This test confirms that CSS stylesheets are properly handled if loaded during 'beforeload' events. It passes if no debug assertions are fired.
+
+PASS: No assertions hit.
+
Added: branches/safari-603-branch/Source/fast/dom/beforeload/recursive-css-pi-before-load.html (0 => 214704)
--- branches/safari-603-branch/Source/fast/dom/beforeload/recursive-css-pi-before-load.html (rev 0)
+++ branches/safari-603-branch/Source/fast/dom/beforeload/recursive-css-pi-before-load.html 2017-04-01 00:20:38 UTC (rev 214704)
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<meta http-equiv="pragma" content="no-cache"/>
+<meta http-equiv="expires" content="0"/>
+<script src=""
+<script>
+function test()
+{
+ if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+ }
+
+ frame = document.createElement("iframe");
+ frame.setAttribute("src", "resources/content.xhtml");
+ frame.addEventListener("load", function(){
+ setTimeout(step2, 0);
+ }, { once: true });
+
+ document.body.appendChild(frame);
+
+ function step2(){
+ ins = 'href="" type="text/css"';
+ pi = frame.contentDocument.createProcessingInstruction('xml-stylesheet', ins);
+ pi.addEventListener("beforeload", function(){ pi.data = ''; }, { once: true });
+ frame.contentDocument.insertBefore(pi, frame.contentDocument.firstChild);
+
+ frame.contentDocument.removeChild(pi);
+ pi = null;
+
+ print("PASS: No assertions hit.", "green");
+
+ if (window.testRunner)
+ testRunner.notifyDone();
+ }
+}
+</script>
+</head>
+<body _onload_="test()">
+<p>This test confirms that CSS stylesheets are properly handled if loaded during 'beforeload' events. It passes if no debug assertions are fired.</p>
+<div id="console"></div>
+</body>
+</html>
Added: branches/safari-603-branch/Source/fast/dom/beforeload/recursive-link-before-load-expected.txt (0 => 214704)
--- branches/safari-603-branch/Source/fast/dom/beforeload/recursive-link-before-load-expected.txt (rev 0)
+++ branches/safari-603-branch/Source/fast/dom/beforeload/recursive-link-before-load-expected.txt 2017-04-01 00:20:38 UTC (rev 214704)
@@ -0,0 +1,5 @@
+This test confirms that link elements properly handled changes during 'beforeload' events. It passes if no debug assertions are fired.
+
+PASS: Beforeload handled.
+PASS: No assertions hit.
+
Added: branches/safari-603-branch/Source/fast/dom/beforeload/recursive-link-before-load.html (0 => 214704)
--- branches/safari-603-branch/Source/fast/dom/beforeload/recursive-link-before-load.html (rev 0)
+++ branches/safari-603-branch/Source/fast/dom/beforeload/recursive-link-before-load.html 2017-04-01 00:20:38 UTC (rev 214704)
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<meta http-equiv="pragma" content="no-cache"/>
+<meta http-equiv="expires" content="0"/>
+<script src=""
+<script>
+function test()
+{
+ if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+ }
+
+ frame = document.createElement("iframe");
+ frame.setAttribute("src", "resources/content.xhtml");
+ frame.addEventListener("load", function(){
+ setTimeout(step2, 0);
+ }, { once: true });
+
+ document.body.appendChild(frame);
+
+ var link;
+ var head;
+
+ function step2() {
+ head = frame.contentDocument.getElementsByTagName('head')[0];
+
+ link = frame.contentDocument.createElement('link');
+ link.type = 'text/css';
+ link.rel = 'stylesheet';
+
+ link.addEventListener("beforeload", function() {
+ print("PASS: Beforeload handled.", "green");
+ link.href = '';
+ setTimeout(step3, 0);
+ }, { once: true });
+
+ link.href = '';
+
+ head.appendChild(link);
+ }
+
+ function step3() {
+ head.removeChild(link);
+ link = null;
+
+ print("PASS: No assertions hit.", "green");
+
+ if (window.testRunner)
+ testRunner.notifyDone();
+ }
+}
+</script>
+</head>
+<body _onload_="test()">
+<p>This test confirms that link elements properly handled changes during 'beforeload' events. It passes if no debug assertions are fired.</p>
+<div id="console"></div>
+</body>
+</html>
Added: branches/safari-603-branch/Source/fast/dom/beforeload/recursive-xsl-pi-before-load-expected.txt (0 => 214704)
--- branches/safari-603-branch/Source/fast/dom/beforeload/recursive-xsl-pi-before-load-expected.txt (rev 0)
+++ branches/safari-603-branch/Source/fast/dom/beforeload/recursive-xsl-pi-before-load-expected.txt 2017-04-01 00:20:38 UTC (rev 214704)
@@ -0,0 +1,4 @@
+This test confirms that XSL stylesheets are properly handled if loaded during 'beforeload' events. It passes if no debug assertions are fired.
+
+PASS: No assertions hit.
+
Added: branches/safari-603-branch/Source/fast/dom/beforeload/recursive-xsl-pi-before-load.html (0 => 214704)
--- branches/safari-603-branch/Source/fast/dom/beforeload/recursive-xsl-pi-before-load.html (rev 0)
+++ branches/safari-603-branch/Source/fast/dom/beforeload/recursive-xsl-pi-before-load.html 2017-04-01 00:20:38 UTC (rev 214704)
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<meta http-equiv="pragma" content="no-cache"/>
+<meta http-equiv="expires" content="0"/>
+<script src=""
+<script>
+function test()
+{
+ if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+ }
+
+ frame = document.createElement("iframe");
+ frame.setAttribute("src", "resources/content.xhtml");
+ frame.addEventListener("load", function(){
+ setTimeout(step2, 0);
+ }, { once: true });
+
+ document.body.appendChild(frame);
+
+ function step2(){
+ ins = 'href="" type="text/xsl"';
+ pi = frame.contentDocument.createProcessingInstruction('xml-stylesheet', ins);
+ pi.addEventListener("beforeload", function(){ pi.data = ''; }, { once: true });
+ frame.contentDocument.insertBefore(pi, frame.contentDocument.firstChild);
+
+ frame.contentDocument.removeChild(pi);
+ pi = null;
+
+ print("PASS: No assertions hit.", "green");
+
+ if (window.testRunner)
+ testRunner.notifyDone();
+ }
+}
+</script>
+</head>
+<body _onload_="test()">
+<p>This test confirms that XSL stylesheets are properly handled if loaded during 'beforeload' events. It passes if no debug assertions are fired.</p>
+<div id="console"></div>
+</body>
+</html>
Added: branches/safari-603-branch/Source/fast/dom/beforeload/resources/content.xhtml (0 => 214704)
--- branches/safari-603-branch/Source/fast/dom/beforeload/resources/content.xhtml (rev 0)
+++ branches/safari-603-branch/Source/fast/dom/beforeload/resources/content.xhtml 2017-04-01 00:20:38 UTC (rev 214704)
@@ -0,0 +1,8 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+</head>
+<body>
+hi
+</body>
+</html>
Added: branches/safari-603-branch/Source/fast/dom/beforeload/resources/pass.css (0 => 214704)
--- branches/safari-603-branch/Source/fast/dom/beforeload/resources/pass.css (rev 0)
+++ branches/safari-603-branch/Source/fast/dom/beforeload/resources/pass.css 2017-04-01 00:20:38 UTC (rev 214704)
@@ -0,0 +1,5 @@
+.block {
+ width: 100px;
+ height: 100px;
+ background-color: green;
+}
Added: branches/safari-603-branch/Source/fast/dom/beforeload/resources/test.xsl (0 => 214704)
--- branches/safari-603-branch/Source/fast/dom/beforeload/resources/test.xsl (rev 0)
+++ branches/safari-603-branch/Source/fast/dom/beforeload/resources/test.xsl 2017-04-01 00:20:38 UTC (rev 214704)
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ <xsl:output method="html"/>
+ <xsl:template match="/">
+ <html>
+ <head>
+ </head>
+ <body>
+ Test
+ </body>
+ </html>
+ </xsl:template>
+</xsl:stylesheet>