<rdar://problem/8107855> Prevent a crash in WebCore when removing an
authoraestes@apple.com <aestes@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 23 Jun 2010 20:03:40 +0000 (20:03 +0000)
committeraestes@apple.com <aestes@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 23 Jun 2010 20:03:40 +0000 (20:03 +0000)
object element with an invalid data URL in in a listener to its
beforeload event.
https://bugs.webkit.org/show_bug.cgi?id=41054

Reviewed by Alexey Proskuryakov.

Tests: fast/dom/beforeload/remove-bad-object-in-beforeload-listener.html

* html/HTMLObjectElement.cpp:
(WebCore::HTMLObjectElement::renderFallbackContent): Exit early if the
object element is not in the document.
* rendering/RenderEmbeddedObject.cpp:
(WebCore::RenderEmbeddedObject::updateWidget): If RenderWidget::destroy()
was called during processing of onbeforeload, do not proceed with loading
the object.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@61707 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/fast/dom/beforeload/remove-bad-object-in-beforeload-listener.html [new file with mode: 0644]
LayoutTests/fast/dom/beforeload/resources/print.js [new file with mode: 0644]
WebCore/ChangeLog
WebCore/html/HTMLObjectElement.cpp
WebCore/rendering/RenderEmbeddedObject.cpp

diff --git a/LayoutTests/fast/dom/beforeload/remove-bad-object-in-beforeload-listener.html b/LayoutTests/fast/dom/beforeload/remove-bad-object-in-beforeload-listener.html
new file mode 100644 (file)
index 0000000..f9790aa
--- /dev/null
@@ -0,0 +1,48 @@
+<html>
+<head>
+    <script src="resources/print.js"></script>
+    <script>
+        if (window.layoutTestController) {
+            layoutTestController.dumpAsText();
+            layoutTestController.waitUntilDone();
+        }
+        
+        var count = 0;
+        var maxCount = 10;
+        var timeout = 100;
+
+        document.addEventListener("beforeload", function(event) {
+            event.target.parentElement.removeChild(event.target);
+        }, true);
+    </script>
+</head>
+<body>
+    <p>This page tests that you can correctly remove an object element with an invalid data URL in its beforeload listener without causing a crash.</p>
+    <object data="invalid.png">FAIL</object>
+    <object data="invalid">FAIL</object>
+    <div id="console"></div>
+    <script>
+        function checkObjectRemoval()
+        {
+            if (!document.getElementsByTagName("object").length) {
+                print("PASS", "green");
+                if (window.layoutTestController)
+                    layoutTestController.notifyDone();
+                return;
+            }
+            
+            if (++count > maxCount) {
+                print("FAIL", "red");
+                if (window.layoutTestController)
+                    layoutTestController.notifyDone();
+                return;
+            }
+            
+            setTimeout("checkObjectRemoval()", timeout);
+        }
+        
+        setTimeout("checkObjectRemoval()", timeout);
+    </script>
+</body>
+</html>
+
diff --git a/LayoutTests/fast/dom/beforeload/resources/print.js b/LayoutTests/fast/dom/beforeload/resources/print.js
new file mode 100644 (file)
index 0000000..8b5dfe2
--- /dev/null
@@ -0,0 +1,9 @@
+function print(message, color) 
+{
+    var paragraph = document.createElement("div");
+    paragraph.appendChild(document.createTextNode(message));
+    paragraph.style.fontFamily = "monospace";
+    if (color)
+        paragraph.style.color = color;
+    document.getElementById("console").appendChild(paragraph);
+}
index ecc7f19..32fd77c 100644 (file)
@@ -1,3 +1,22 @@
+2010-06-23  Andy Estes  <aestes@apple.com>
+
+        Reviewed by Alexey Proskuryakov.
+        
+        <rdar://problem/8107855> Prevent a crash in WebCore when removing an
+        object element with an invalid data URL in in a listener to its
+        beforeload event.
+        https://bugs.webkit.org/show_bug.cgi?id=41054
+
+        Tests: fast/dom/beforeload/remove-bad-object-in-beforeload-listener.html
+
+        * html/HTMLObjectElement.cpp:
+        (WebCore::HTMLObjectElement::renderFallbackContent): Exit early if the
+        object element is not in the document.
+        * rendering/RenderEmbeddedObject.cpp:
+        (WebCore::RenderEmbeddedObject::updateWidget): If RenderWidget::destroy()
+        was called during processing of onbeforeload, do not proceed with loading
+        the object.
+
 2010-06-23  Gustavo Noronha Silva  <gustavo.noronha@collabora.co.uk>
 
         Reviewed by Xan Lopez.
index bd9fc1c..45586d1 100644 (file)
@@ -243,6 +243,9 @@ void HTMLObjectElement::renderFallbackContent()
 {
     if (m_useFallbackContent)
         return;
+    
+    if (!inDocument())
+        return;
 
     // Before we give up and use fallback content, check to see if this is a MIME type issue.
     if (m_imageLoader && m_imageLoader->image()) {
index 13dbe04..7ab12a1 100644 (file)
@@ -284,7 +284,16 @@ void RenderEmbeddedObject::updateWidget(bool onlyCreateNonNetscapePlugins)
                 return;
         }
 
-        bool success = objectElement->dispatchBeforeLoadEvent(url) && frame->loader()->subframeLoader()->requestObject(this, url, objectElement->getAttribute(nameAttr), serviceType, paramNames, paramValues);
+        bool beforeLoadAllowedLoad = objectElement->dispatchBeforeLoadEvent(url);
+        
+        // beforeload events can modify the DOM, potentially causing
+        // RenderWidget::destroy() to be called.  Ensure we haven't been
+        // destroyed before continuing.
+        if (!node())
+            return;
+        
+        bool success = beforeLoadAllowedLoad && frame->loader()->subframeLoader()->requestObject(this, url, objectElement->getAttribute(nameAttr), serviceType, paramNames, paramValues);
+    
         if (!success && m_hasFallbackContent)
             objectElement->renderFallbackContent();