Bug 146842

Summary: Crash in HistoryController::updateForCommit dereferencing a null HistoryItem
Product: WebKit Reporter: Brady Eidson <beidson>
Component: Page LoadingAssignee: Brady Eidson <beidson>
Status: RESOLVED FIXED    
Severity: Normal CC: cdumez, commit-queue, japhet
Priority: P2 Keywords: InRadar
Version: 528+ (Nightly build)   
Hardware: All   
OS: All   
Attachments:
Description Flags
Patch v1 cdumez: review+

Description Brady Eidson 2015-07-10 11:06:40 PDT
We're seeing crashes in HistoryController::updateForCommit dereferencing a null HistoryItem

      38 WebCore: WebCore::HistoryController::updateForCommit() <==
        30 WebCore: WebCore::HistoryController::updateForCommit()
        | 30 WebCore: WebCore::FrameLoader::transitionToCommitted(WebCore::CachedPage*)
        |   30 WebCore: WebCore::FrameLoader::commitProvisionalLoad()
        |     30 WebCore: WebCore::DocumentLoader::commitLoad(char const*, int)
        |       28 WebCore: WebCore::CachedRawResource::notifyClientsDataWasReceived(char const*, unsigned int)
        |       | 28 WebCore: WebCore::CachedRawResource::addDataBuffer(WebCore::SharedBuffer&)
        |       |   28 WebCore: WebCore::SubresourceLoader::didReceiveDataOrBuffer(char const*, int, WTF::PassRefPtr<WebCore::SharedBuffer>, long long, WebCore::DataPayloadType)
        |       |     28 WebCore: WebCore::SubresourceLoader::didReceiveData(char const*, unsigned int, long long, WebCore::DataPayloadType)
        |       |       28 WebKit: WebKit::WebResourceLoader::didReceiveWebResourceLoaderMessage(IPC::Connection&, IPC::MessageDecoder&)


The problem is when setCurrentItem(*m_provisionalItem) executes, but m_provisionalItem is null.

In updateForCommit there's been a long standing "ASSERT(m_provisionalItem)", but it is still definitely null sometimes. For many years, setting the current item to null in release builds has been a thing.

As of http://trac.webkit.org/changeset/179472 we stopped successfully handing the nullptr and started crashing instead.

While we want to get to the bottom of why the provisional item might be null (which is why we have the ASSERT there), we should restore the previous "handles null" behavior to get rid of the crashes.

<rdar://problem/21371589>
Comment 1 Brady Eidson 2015-07-10 11:18:39 PDT
Created attachment 256593 [details]
Patch v1
Comment 2 Chris Dumez 2015-07-10 11:23:35 PDT
Comment on attachment 256593 [details]
Patch v1

View in context: https://bugs.webkit.org/attachment.cgi?id=256593&action=review

> Source/WebCore/loader/FrameLoader.cpp:3184
> +    history().setCurrentItem(&item);

Here it cannot be null.

> Source/WebCore/loader/HistoryController.cpp:474
> +        setCurrentItem(m_provisionalItem.get());

Here, we would hit the assert on the previous line if it were null.

> Source/WebCore/loader/HistoryController.cpp:515
> +        setCurrentItem(m_provisionalItem.get());

Here, we already made sure it isn't null at the beginning of the method.

> Source/WebCore/loader/HistoryController.cpp:564
> +    setCurrentItem(m_provisionalItem.get());

Here, we already made sure it isn't null at the beginning of the method.

> Source/WebCore/loader/HistoryController.cpp:667
> +    setCurrentItem(item.ptr());

Here it cannot be null.
Comment 3 Brady Eidson 2015-07-10 11:26:58 PDT
(In reply to comment #2)
> Comment on attachment 256593 [details]
> Patch v1
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=256593&action=review
> 
> > Source/WebCore/loader/FrameLoader.cpp:3184
> > +    history().setCurrentItem(&item);
> 
> Here it cannot be null.

I know.

> > Source/WebCore/loader/HistoryController.cpp:515
> > +        setCurrentItem(m_provisionalItem.get());
> 
> Here, we already made sure it isn't null at the beginning of the method.

I know.
 
> > Source/WebCore/loader/HistoryController.cpp:564
> > +    setCurrentItem(m_provisionalItem.get());
> 
> Here, we already made sure it isn't null at the beginning of the method.

I know.

> > Source/WebCore/loader/HistoryController.cpp:667
> > +    setCurrentItem(item.ptr());
> 
> Here it cannot be null.

I know.

> > Source/WebCore/loader/HistoryController.cpp:474
> > +        setCurrentItem(m_provisionalItem.get());
> 
> Here, we would hit the assert on the previous line if it were null.

Yes, which is exactly what I described in the problem Description. But in release builds there is no ASSERT and we dereference null.

This is not theoretical - It's definitely happening in release builds a non-trivial amount.
Comment 4 Chris Dumez 2015-07-10 11:34:52 PDT
Comment on attachment 256593 [details]
Patch v1

View in context: https://bugs.webkit.org/attachment.cgi?id=256593&action=review

r=me to get rid of the crash short-term but it may be papering over a real bug :/

>>> Source/WebCore/loader/HistoryController.cpp:474
>>> +        setCurrentItem(m_provisionalItem.get());
>> 
>> Here, we would hit the assert on the previous line if it were null.
> 
> Yes, which is exactly what I described in the problem Description. But in release builds there is no ASSERT and we dereference null.
> 
> This is not theoretical - It's definitely happening in release builds a non-trivial amount.

Then, I think we should add a FIXME comment indicating that our assertion above doesn't always hold true and that it should be investigated why.
Comment 5 Brady Eidson 2015-07-10 11:41:22 PDT
(In reply to comment #4)
> Comment on attachment 256593 [details]
> Patch v1
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=256593&action=review
> 
> r=me to get rid of the crash short-term but it may be papering over a real
> bug :/

There's definitely a real bug, and it's existed since at least 2009 without revealing itself. (That's when the assert was added)

> >>> Source/WebCore/loader/HistoryController.cpp:474
> >>> +        setCurrentItem(m_provisionalItem.get());
> >> 
> >> Here, we would hit the assert on the previous line if it were null.
> > 
> > Yes, which is exactly what I described in the problem Description. But in release builds there is no ASSERT and we dereference null.
> > 
> > This is not theoretical - It's definitely happening in release builds a non-trivial amount.
> 
> Then, I think we should add a FIXME comment indicating that our assertion
> above doesn't always hold true and that it should be investigated why.

K.
Comment 6 Brady Eidson 2015-07-10 12:03:17 PDT
https://trac.webkit.org/changeset/186683