WebPageProxy::reportPageLoadResult can crash on some code paths
authorkrollin@apple.com <krollin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 13 Sep 2018 22:32:33 +0000 (22:32 +0000)
committerkrollin@apple.com <krollin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 13 Sep 2018 22:32:33 +0000 (22:32 +0000)
https://bugs.webkit.org/show_bug.cgi?id=189568

Reviewed by Chris Dumez.

WebPageProxy::reportPageLoadResult (which is called from
WebPageProxy::didFinishLoadForFrame) can sometimes crash when
accessing m_pageLoadStart (a std::optional) in its unloaded state.
Normally, m_pageLoadStart is initialized in
WebPageProxy::didStartProvisionalLoadForFrame, which one would expect
would be called before WebPageProxy::didFinishLoadForFrame. But that
turns out to not always be the case. It's not apparent under what
conditions didStartProvisionalLoadForFrame will not be called, but
it's happening in the wild, leading to crashes now that std::optional
asserts in release builds on bad accesses (see
https://bugs.webkit.org/show_bug.cgi?id=189568).

Fix this by checking m_pageLoadState on entry to reportPageLoadResult.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::didFailProvisionalLoadForFrame):
(WebKit::WebPageProxy::didFinishLoadForFrame):
(WebKit::WebPageProxy::didFailLoadForFrame):
(WebKit::WebPageProxy::reportPageLoadResult):

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

Source/WebKit/ChangeLog
Source/WebKit/UIProcess/WebPageProxy.cpp

index 3cec092..ba6aadb 100644 (file)
@@ -1,3 +1,30 @@
+2018-09-13  Keith Rollin  <krollin@apple.com>
+
+        WebPageProxy::reportPageLoadResult can crash on some code paths
+        https://bugs.webkit.org/show_bug.cgi?id=189568
+
+        Reviewed by Chris Dumez.
+
+        WebPageProxy::reportPageLoadResult (which is called from
+        WebPageProxy::didFinishLoadForFrame) can sometimes crash when
+        accessing m_pageLoadStart (a std::optional) in its unloaded state.
+        Normally, m_pageLoadStart is initialized in
+        WebPageProxy::didStartProvisionalLoadForFrame, which one would expect
+        would be called before WebPageProxy::didFinishLoadForFrame. But that
+        turns out to not always be the case. It's not apparent under what
+        conditions didStartProvisionalLoadForFrame will not be called, but
+        it's happening in the wild, leading to crashes now that std::optional
+        asserts in release builds on bad accesses (see
+        https://bugs.webkit.org/show_bug.cgi?id=189568).
+
+        Fix this by checking m_pageLoadState on entry to reportPageLoadResult.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::didFailProvisionalLoadForFrame):
+        (WebKit::WebPageProxy::didFinishLoadForFrame):
+        (WebKit::WebPageProxy::didFailLoadForFrame):
+        (WebKit::WebPageProxy::reportPageLoadResult):
+
 2018-09-13  Chris Dumez  <cdumez@apple.com>
 
         ProcessSwap.BackWithoutSuspendedPage API test hits assertion under WebPageProxy::didCreateMainFrame()
index 29195c6..0c81724 100644 (file)
@@ -888,8 +888,7 @@ void WebPageProxy::close()
 
     m_isClosed = true;
 
-    if (m_pageLoadStart)
-        reportPageLoadResult(ResourceError { ResourceError::Type::Cancellation });
+    reportPageLoadResult(ResourceError { ResourceError::Type::Cancellation });
 
     if (m_activePopupMenu)
         m_activePopupMenu->cancelTracking();
@@ -3463,8 +3462,7 @@ void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t na
     m_pageLoadState.clearPendingAPIRequestURL(transaction);
 
     if (frame->isMainFrame()) {
-        if (m_pageLoadStart)
-            reportPageLoadResult(ResourceError { ResourceError::Type::Cancellation });
+        reportPageLoadResult(ResourceError { ResourceError::Type::Cancellation });
         m_pageLoadStart = MonotonicTime::now();
         m_pageLoadState.didStartProvisionalLoad(transaction, url, unreachableURL);
         pageClient().didStartProvisionalLoadForMainFrame();
@@ -7911,7 +7909,8 @@ void WebPageProxy::reportPageLoadResult(const ResourceError& error)
         { CompletionCondition::Timeout, Seconds::infinity(), DiagnosticLoggingKeys::timedOutKey() }
         });
 
-    ASSERT(m_pageLoadStart);
+    if (!m_pageLoadStart)
+        return;
 
     auto pageLoadTime = MonotonicTime::now() - *m_pageLoadStart;
     m_pageLoadStart = std::nullopt;