heap use-after-free at WebCore::TimerBase::heapPopMin()
authorbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 17 May 2016 01:09:27 +0000 (01:09 +0000)
committerbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 17 May 2016 01:09:27 +0000 (01:09 +0000)
https://bugs.webkit.org/show_bug.cgi?id=157742
<rdar://problem/26236778>

Source/WebCore:

Reviewed by David Kilzer.

Tested by fast/frames/resources/crash-during-iframe-load-stop.html.

* loader/FrameLoader.cpp:
(WebCore::FrameLoader::stopForUserCancel): Protect m_frame from destruction while it is still
being used by the current stack frame.
(WebCore::FrameLoader::frameDetached): Ditto.
(WebCore::FrameLoader::continueFragmentScrollAfterNavigationPolicy): Ditto.

LayoutTests:

Reviewed by Simon Fraser.

* fast/frames/crash-during-iframe-load-stop-expected.txt: Added.
* fast/frames/crash-during-iframe-load-stop.html: Added.
* fast/frames/resources/crash-during-iframe-load-stop-inner.html: Added.
* fast/frames/resources/crash-during-iframe-load-stop.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/fast/frames/crash-during-iframe-load-stop-expected.txt [new file with mode: 0644]
LayoutTests/fast/frames/crash-during-iframe-load-stop.html [new file with mode: 0644]
LayoutTests/fast/frames/resources/crash-during-iframe-load-stop-inner.html [new file with mode: 0644]
LayoutTests/fast/frames/resources/crash-during-iframe-load-stop.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/loader/FrameLoader.cpp

index dc06fa3..35fdd03 100644 (file)
@@ -1,3 +1,16 @@
+2016-05-16  Brent Fulgham  <bfulgham@apple.com>
+
+        heap use-after-free at WebCore::TimerBase::heapPopMin()
+        https://bugs.webkit.org/show_bug.cgi?id=157742
+        <rdar://problem/26236778>
+
+        Reviewed by Simon Fraser.
+
+        * fast/frames/crash-during-iframe-load-stop-expected.txt: Added.
+        * fast/frames/crash-during-iframe-load-stop.html: Added.
+        * fast/frames/resources/crash-during-iframe-load-stop-inner.html: Added.
+        * fast/frames/resources/crash-during-iframe-load-stop.html: Added.
+
 2016-05-16  Saam barati  <sbarati@apple.com>
 
         Hook up ShadowChicken to the debugger to show tail deleted frames
diff --git a/LayoutTests/fast/frames/crash-during-iframe-load-stop-expected.txt b/LayoutTests/fast/frames/crash-during-iframe-load-stop-expected.txt
new file mode 100644 (file)
index 0000000..ac81e60
--- /dev/null
@@ -0,0 +1,3 @@
+This tests that WebKit does not crash when frame loads are interrupted. This test passes if it does not crash.
+
diff --git a/LayoutTests/fast/frames/crash-during-iframe-load-stop.html b/LayoutTests/fast/frames/crash-during-iframe-load-stop.html
new file mode 100644 (file)
index 0000000..b8fc6fe
--- /dev/null
@@ -0,0 +1,38 @@
+<html>
+<head>
+<script>
+    if (window.testRunner) {
+        testRunner.waitUntilDone();
+        testRunner.dumpAsText();
+    }
+
+    var count = 0;
+</script>
+</head>
+<body onload='deleteFrame()'>
+    <script>
+    function deleteFrame()
+    {
+        var frameToRemove = document.getElementById('subframe');
+        document.body.removeChild(frameToRemove);
+    }
+
+    function reloadSubframe()
+    {
+        var iframe = document.createElement('iframe');
+        iframe.id = 'subframe';
+        iframe.src = 'resources/crash-during-iframe-load-stop.html';
+        document.body.appendChild(iframe);
+        setTimeout(function() { deleteFrame(); }, 0);
+    }
+
+    function subFrameFinishedLoading()
+    {
+        if (window.testRunner)
+            testRunner.notifyDone();
+    }
+    </script>
+    <p>This tests that WebKit does not crash when frame loads are interrupted. This test passes if it does not crash.</p>
+    <iframe id="subframe" src='resources/crash-during-iframe-load-stop.html'></iframe>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/fast/frames/resources/crash-during-iframe-load-stop-inner.html b/LayoutTests/fast/frames/resources/crash-during-iframe-load-stop-inner.html
new file mode 100644 (file)
index 0000000..8e9ece1
--- /dev/null
@@ -0,0 +1,6 @@
+<html>
+  <script>
+      window.parent.stop();
+      window.parent.subFrameFinishedLoading();
+  </script>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/fast/frames/resources/crash-during-iframe-load-stop.html b/LayoutTests/fast/frames/resources/crash-during-iframe-load-stop.html
new file mode 100644 (file)
index 0000000..2fd6467
--- /dev/null
@@ -0,0 +1,16 @@
+<html>
+<head>
+    <script>
+    function subFrameFinishedLoading()
+    {
+        window.parent.count = window.parent.count + 1;
+        if (window.parent.count < 10)
+            window.parent.reloadSubframe();
+        else
+            window.parent.subFrameFinishedLoading();
+    }
+    </script>
+</head>
+  <iframe src="crash-during-iframe-load-stop-inner.html"></iframe>
+  <iframe src="data:text/html, <html></html>"></iframe>
+</html>
\ No newline at end of file
index 4764f52..a75a97f 100644 (file)
@@ -1,3 +1,19 @@
+2016-05-16  Brent Fulgham  <bfulgham@apple.com>
+
+        heap use-after-free at WebCore::TimerBase::heapPopMin()
+        https://bugs.webkit.org/show_bug.cgi?id=157742
+        <rdar://problem/26236778>
+
+        Reviewed by David Kilzer.
+
+        Tested by fast/frames/resources/crash-during-iframe-load-stop.html.
+
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::stopForUserCancel): Protect m_frame from destruction while it is still
+        being used by the current stack frame.
+        (WebCore::FrameLoader::frameDetached): Ditto.
+        (WebCore::FrameLoader::continueFragmentScrollAfterNavigationPolicy): Ditto.
+
 2016-05-16  Dean Jackson  <dino@apple.com>
 
         WebCoreJSBuiltinInternals won't compile if some build flags are off
index 6c33d2f..34a441b 100644 (file)
@@ -1632,6 +1632,9 @@ void FrameLoader::stopAllLoaders(ClearProvisionalItemPolicy clearProvisionalItem
 
 void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete)
 {
+    // Calling stopAllLoaders can cause the frame to be deallocated, including the frame loader.
+    Ref<Frame> protectedFrame(m_frame);
+
     stopAllLoaders();
 
 #if PLATFORM(IOS)
@@ -2491,6 +2494,9 @@ void FrameLoader::dispatchOnloadEvents()
 
 void FrameLoader::frameDetached()
 {
+    // Calling stopAllLoaders can cause the frame to be deallocated, including the frame loader.
+    Ref<Frame> protectedFrame(m_frame);
+
     stopAllLoaders();
     m_frame.document()->stopActiveDOMObjects();
     detachFromParent();
@@ -2790,6 +2796,10 @@ void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequ
     if (!shouldContinue)
         return;
 
+    // Calling stopLoading() on the provisional document loader can cause the underlying
+    // frame to be deallocated.
+    Ref<Frame> protectedFrame(m_frame);
+
     // If we have a provisional request for a different document, a fragment scroll should cancel it.
     if (m_provisionalDocumentLoader && !equalIgnoringFragmentIdentifier(m_provisionalDocumentLoader->request().url(), request.url())) {
         m_provisionalDocumentLoader->stopLoading();