Bug 174874 - RenderImageResourceStyleImage::image() should return the nullImage() if the image is not available
Summary: RenderImageResourceStyleImage::image() should return the nullImage() if the i...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Images (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Said Abou-Hallawa
URL:
Keywords: InRadar
Depends on:
Blocks: 175114
  Show dependency treegraph
 
Reported: 2017-07-26 14:32 PDT by Said Abou-Hallawa
Modified: 2017-08-10 14:56 PDT (History)
10 users (show)

See Also:


Attachments
Patch (2.77 KB, patch)
2017-07-26 14:36 PDT, Said Abou-Hallawa
no flags Details | Formatted Diff | Diff
Archive of layout-test-results from ews123 for ios-simulator-wk2 (12.56 MB, application/zip)
2017-07-26 16:00 PDT, Build Bot
no flags Details
Patch (2.80 KB, patch)
2017-07-27 19:04 PDT, Said Abou-Hallawa
no flags Details | Formatted Diff | Diff
Test case (will crash) (442 bytes, text/html)
2017-07-28 22:42 PDT, Said Abou-Hallawa
no flags Details
Patch (10.72 KB, patch)
2017-07-28 23:42 PDT, Said Abou-Hallawa
no flags Details | Formatted Diff | Diff
Patch (10.48 KB, patch)
2017-07-28 23:44 PDT, Said Abou-Hallawa
no flags Details | Formatted Diff | Diff
Patch (11.34 KB, patch)
2017-07-29 12:16 PDT, Said Abou-Hallawa
no flags Details | Formatted Diff | Diff
Patch (5.93 KB, patch)
2017-08-01 15:18 PDT, Said Abou-Hallawa
no flags Details | Formatted Diff | Diff
leak_results (199.11 KB, text/plain)
2017-08-02 21:02 PDT, Said Abou-Hallawa
no flags Details
Patch (6.89 KB, patch)
2017-08-02 21:30 PDT, Said Abou-Hallawa
no flags Details | Formatted Diff | Diff
Patch (6.79 KB, patch)
2017-08-04 00:19 PDT, Said Abou-Hallawa
no flags Details | Formatted Diff | Diff
Patch (6.78 KB, patch)
2017-08-04 13:02 PDT, Said Abou-Hallawa
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Said Abou-Hallawa 2017-07-26 14:32:13 PDT
Like the base class virtual method RenderImageResource::image(), RenderImageResourceStyleImage::image() should return the nullImage() if the image is not available.

This is to prevent a crash we saw recently because of calling image()->stopAnimation() in RenderImageResourceStyleImage::shutdown(). The crash was happening because RenderImageResourceStyleImage::image() can return a null Image pointer . m_styleImage->image() can return a null pointer via StyleCachedImage::image() or StyleGeneratedImage::image().
Comment 1 Said Abou-Hallawa 2017-07-26 14:36:54 PDT
Created attachment 316483 [details]
Patch
Comment 2 Said Abou-Hallawa 2017-07-26 14:38:23 PDT
<rdar://problem/33530130>
Comment 3 Build Bot 2017-07-26 16:00:45 PDT
Comment on attachment 316483 [details]
Patch

Attachment 316483 [details] did not pass ios-sim-ews (ios-simulator-wk2):
Output: http://webkit-queues.webkit.org/results/4192746

New failing tests:
imported/w3c/IndexedDB-private-browsing/idbfactory_open12.html
Comment 4 Build Bot 2017-07-26 16:00:47 PDT
Created attachment 316494 [details]
Archive of layout-test-results from ews123 for ios-simulator-wk2

The attached test failures were seen while running run-webkit-tests on the ios-sim-ews.
Bot: ews123  Port: ios-simulator-wk2  Platform: Mac OS X 10.12.5
Comment 5 Jon Lee 2017-07-27 16:19:48 PDT
Comment on attachment 316483 [details]
Patch

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

Is this testable?

> Source/WebCore/ChangeLog:5
> +

Please add Radar.

> Source/WebCore/ChangeLog:14
> +        of r208511 in this function. Add a call to image()->stopAnimation() without

you mean 219205?
Comment 6 Said Abou-Hallawa 2017-07-27 17:40:21 PDT
Comment on attachment 316483 [details]
Patch

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

>> Source/WebCore/ChangeLog:14
>> +        of r208511 in this function. Add a call to image()->stopAnimation() without
> 
> you mean 219205?

No. I meant r208511 because I am talking about RenderImageResourceStyleImage::shutdown() which was like this before r208511:

void RenderImageResourceStyleImage::shutdown()
{
    ASSERT(m_renderer);
    m_styleImage->removeClient(m_renderer);
    m_cachedImage = nullptr;
}

And with this patch it is going to look like this:

void RenderImageResourceStyleImage::shutdown()
{
    ASSERT(m_renderer);
    image()->stopAnimation();
    m_styleImage->removeClient(m_renderer);
    m_cachedImage = nullptr;
}

But in r219205, I changed RenderImageResourceStyleImage::image() from 

RefPtr<Image> RenderImageResourceStyleImage::image(const IntSize& size) const
{
    // Generated content may trigger calls to image() while we're still pending, don't assert but gracefully exit.
    if (m_styleImage->isPending())
        return nullptr;
    return m_styleImage->image(m_renderer, size);
}

to be

RefPtr<Image> RenderImageResourceStyleImage::image(const IntSize& size) const
{
    // Generated content may trigger calls to image() while we're still pending, don't assert but gracefully exit.
    return !m_styleImage->isPending() ? m_styleImage->image(m_renderer, size) : &Image::nullImage();
}

I was trying to get it to be similar to the base class virtual function RenderImageResource::image() which returns the nullImage() if the image not available. But I did not do quite right because m_styleImage->image() can still return a null pointer. So in this patch I am trying to ensure RenderImageResourceStyleImage::image() returns either a valid Image pointer or the nullImage() if the image is not available.
Comment 7 Said Abou-Hallawa 2017-07-27 19:04:58 PDT
Created attachment 316599 [details]
Patch
Comment 8 Jon Lee 2017-07-28 10:41:59 PDT
Why is this not testable?
Comment 9 Said Abou-Hallawa 2017-07-28 22:42:56 PDT
Created attachment 316703 [details]
Test case (will crash)
Comment 10 Said Abou-Hallawa 2017-07-28 23:42:19 PDT
Created attachment 316704 [details]
Patch
Comment 11 Said Abou-Hallawa 2017-07-28 23:44:15 PDT
Created attachment 316705 [details]
Patch
Comment 12 Said Abou-Hallawa 2017-07-29 12:16:01 PDT
Created attachment 316722 [details]
Patch
Comment 13 Darin Adler 2017-07-29 19:45:40 PDT
Still need an answer to Jon’s question. Why no test?
Comment 14 Tim Horton 2017-07-29 22:59:33 PDT
Hmmwhat? There's totally a test now.
Comment 15 WebKit Commit Bot 2017-07-30 00:38:34 PDT
Comment on attachment 316722 [details]
Patch

Clearing flags on attachment: 316722

Committed r220048: <http://trac.webkit.org/changeset/220048>
Comment 16 WebKit Commit Bot 2017-07-30 00:38:36 PDT
All reviewed patches have been landed.  Closing bug.
Comment 17 Matt Lewis 2017-07-31 13:31:54 PDT
Reverted r220048 for reason:

This revision caused multiple crashes in fast/images. See webkit.org/b/174990

Committed r220073: <http://trac.webkit.org/changeset/220073>
Comment 18 Said Abou-Hallawa 2017-08-01 15:18:16 PDT
Created attachment 316902 [details]
Patch
Comment 19 Said Abou-Hallawa 2017-08-01 15:29:48 PDT
The changed functions:

RenderImageResourceStyleImage::shutdown()
RenderImageResourceStyleImage::image()

do not even get called when running the crashed tests

fast/images/low-memory-decode.html
fast/images/link-body-content-imageDimensionChanged-crash.html

The only thing that I can think of that may have caused these crashes is removing including the style image header files from some sources. So I reverted these changes and I uploaded a new patch with the changes in the above two functions only.
Comment 20 Jonathan Bedard 2017-08-01 16:39:25 PDT
(In reply to Said Abou-Hallawa from comment #19)
> The changed functions:
> 
> RenderImageResourceStyleImage::shutdown()
> RenderImageResourceStyleImage::image()
> 
> do not even get called when running the crashed tests
> 
> fast/images/low-memory-decode.html
> fast/images/link-body-content-imageDimensionChanged-crash.html
> 
> The only thing that I can think of that may have caused these crashes is
> removing including the style image header files from some sources. So I
> reverted these changes and I uploaded a new patch with the changes in the
> above two functions only.

I'm thinking that you've triggered some stateful flakiness in the test runner.  I'm going to look into this tomorrow morning.
Comment 21 Jonathan Bedard 2017-08-02 15:49:57 PDT
(In reply to Jonathan Bedard from comment #20)
> ...
> 
> I'm thinking that you've triggered some stateful flakiness in the test
> runner.  I'm going to look into this tomorrow morning.

Ok, this is actually pretty easy to reproduce.

If you run 'run-webkit-tests --child-processes=1 fast/images' with the patch vs the same command without the patch, you will see a leak in fast/images/low-memory-decode.html which we treat as a crash.

Not sure how your patch is causing this, but I'd like to see that resolved before this lands again.
Comment 22 Said Abou-Hallawa 2017-08-02 20:27:04 PDT
(In reply to Jonathan Bedard from comment #21)
> (In reply to Jonathan Bedard from comment #20)
> > ...
> > 
> > I'm thinking that you've triggered some stateful flakiness in the test
> > runner.  I'm going to look into this tomorrow morning.
> 
> Ok, this is actually pretty easy to reproduce.
> 
> If you run 'run-webkit-tests --child-processes=1 fast/images' with the patch
> vs the same command without the patch, you will see a leak in
> fast/images/low-memory-decode.html which we treat as a crash.
> 
> Not sure how your patch is causing this, but I'd like to see that resolved
> before this lands again.

I ran 'run-webkit-tests --child-processes=1 fast/images' with the patch but without the new test, which I added in this patch, LayoutTests/fast/images/image-element-image-content-data.html, and I did not see a leak in fast/images/low-memory-decode.html.
Comment 23 Said Abou-Hallawa 2017-08-02 21:02:20 PDT
Created attachment 317085 [details]
leak_results

I ran 'run-webkit-tests --child-processes=1  --leak LayoutTests/fast/images/image-element-image-content-data.html --repeat-each=10 -1' and I got the attached leak_results. I could not find in this file anything related to the CachedImage or the RenderImageResourceStyleImage.
Comment 24 Said Abou-Hallawa 2017-08-02 21:04:57 PDT
I think I need to skip this new test, land this patch and file a separate bug for the memory leak bug.
Comment 25 Said Abou-Hallawa 2017-08-02 21:30:58 PDT
Created attachment 317089 [details]
Patch
Comment 26 Jonathan Bedard 2017-08-03 08:28:24 PDT
(In reply to Said Abou-Hallawa from comment #24)
> I think I need to skip this new test, land this patch and file a separate
> bug for the memory leak bug.

What happens if you run the tests with the new test but without the patch?  Do you still see a leak?
Comment 27 Said Abou-Hallawa 2017-08-03 12:44:00 PDT
(In reply to Jonathan Bedard from comment #26)
> (In reply to Said Abou-Hallawa from comment #24)
> > I think I need to skip this new test, land this patch and file a separate
> > bug for the memory leak bug.
> 
> What happens if you run the tests with the new test but without the patch? 
> Do you still see a leak?

When running the test without the C++ changes (expect a null check to prevent the crash), I was getting a crash in fast/images/low-memory-decode.html and a memory leak in LayoutTests/fast/images/image-element-image-content-data.html.

After <http://trac.webkit.org/changeset/220183>, the memory leak is gone but still the crash still exists. This crash is different from the crash we see when opening the attached test case. It happens in CachedImage::canDestroyDecodedData() when accessing the local variable 'client'. The call stack is similar to this: https://build.webkit.org/results/Apple%20Sierra%20Debug%20WK2%20(Tests)/r220068%20(2283)/fast/images/low-memory-decode-crash-log.txt

To confirm this is the case, I changed CachedImage::canDestroyDecodedData() such that it returns false always without accessing any of the CacheImageClients. I ran

run-webkit-tests --debug --child-processes=1 LayoutTests/fast/images/
run-webkit-tests --child-processes=1 --leak LayoutTests/fast/images/image-element-image-content-data.html --repeat-each=100 -1

And all the tests including the new test passed without crashes or memory leaks.
Comment 28 Said Abou-Hallawa 2017-08-04 00:19:08 PDT
Created attachment 317220 [details]
Patch
Comment 29 Said Abou-Hallawa 2017-08-04 00:27:13 PDT
I figured out why the other crash was happening. It can happen if a RenderImageResourceStyleImage has its m_styleImage of type StyleGeneratedImage but its m_cachedImage is set when loading the src url finishes. RenderImageResourceStyleImage::shutdown() does not remove m_renderer from the clients of m_cachedImage. So we end having a freed pointer in the CachedImage::m_clients. If the CachedImage is deleted by the MemoryCache, it is going to call BitmapImage::destroyDecodedData() which will end up calling CachedImage::canDestroyDecodedData(). This function function will enumerate the clients stored in m_clients. The crash will happen when trying to call canDestroyDecodedData() of the freed RenderImage client.
Comment 30 Simon Fraser (smfr) 2017-08-04 12:55:18 PDT
Comment on attachment 317220 [details]
Patch

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

> Source/WebCore/ChangeLog:9
> +        If an <img> element has a none CachedImage content data, e.g.

Do you mean non-CachedImage ?
Comment 31 Said Abou-Hallawa 2017-08-04 13:02:23 PDT
Created attachment 317271 [details]
Patch
Comment 32 Darin Adler 2017-08-04 13:13:02 PDT
Comment on attachment 317271 [details]
Patch

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

> Source/WebCore/rendering/RenderImageResourceStyleImage.cpp:62
> +    if (!m_styleImage->isCachedImage() && m_cachedImage)
> +        m_cachedImage->removeClient(*m_renderer);

This code is really confusing and does not seem right. I would expect the removeClient call would be made by the same class as the addClient call, and be a counterpart to that call. Where is the addClient call that this removeClient call balances?
Comment 33 WebKit Commit Bot 2017-08-04 13:42:46 PDT
Comment on attachment 317271 [details]
Patch

Clearing flags on attachment: 317271

Committed r220289: <http://trac.webkit.org/changeset/220289>
Comment 34 WebKit Commit Bot 2017-08-04 13:42:48 PDT
All reviewed patches have been landed.  Closing bug.
Comment 35 Darin Adler 2017-08-05 09:17:50 PDT
(In reply to Darin Adler from comment #32)
> Comment on attachment 317271 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=317271&action=review
> 
> > Source/WebCore/rendering/RenderImageResourceStyleImage.cpp:62
> > +    if (!m_styleImage->isCachedImage() && m_cachedImage)
> > +        m_cachedImage->removeClient(*m_renderer);
> 
> This code is really confusing and does not seem right. I would expect the
> removeClient call would be made by the same class as the addClient call, and
> be a counterpart to that call. Where is the addClient call that this
> removeClient call balances?

At some point I would like to hear the answer to this code style/structure question. I think some kind of change here can improve clarity.
Comment 36 Said Abou-Hallawa 2017-08-05 11:51:34 PDT
(In reply to Darin Adler from comment #35)
> (In reply to Darin Adler from comment #32)
> > Comment on attachment 317271 [details]
> > Patch
> > 
> > View in context:
> > https://bugs.webkit.org/attachment.cgi?id=317271&action=review
> > 
> > > Source/WebCore/rendering/RenderImageResourceStyleImage.cpp:62
> > > +    if (!m_styleImage->isCachedImage() && m_cachedImage)
> > > +        m_cachedImage->removeClient(*m_renderer);
> > 
> > This code is really confusing and does not seem right. I would expect the
> > removeClient call would be made by the same class as the addClient call, and
> > be a counterpart to that call. Where is the addClient call that this
> > removeClient call balances?
> 
> At some point I would like to hear the answer to this code style/structure
> question. I think some kind of change here can improve clarity.

I am sorry for missing your comment. When I received the bugzilla mail saying the patch is +r'ed by smfr, I just +cq'ed it without refreshing the page. I will address your comment in a follow up patch.
Comment 37 Darin Adler 2017-08-05 17:36:32 PDT
No problem. I was not trying to prevent you from checking in; but it does seem worth some further thought and possibly further refinement.
Comment 38 Said Abou-Hallawa 2017-08-10 14:55:56 PDT
(In reply to Darin Adler from comment #37)
> No problem. I was not trying to prevent you from checking in; but it does
> seem worth some further thought and possibly further refinement.

Followup patch is in https://bugs.webkit.org/show_bug.cgi?id=175444.