Title: [214704] branches/safari-603-branch/Source
Revision
214704
Author
[email protected]
Date
2017-03-31 17:20:38 -0700 (Fri, 31 Mar 2017)

Log Message

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).

Patch by Brent Fulgham <[email protected]> on 2017-03-31

Modified Paths

Added Paths

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>
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to