Changeset 220289 in webkit


Ignore:
Timestamp:
Aug 4, 2017 1:42:43 PM (7 years ago)
Author:
commit-queue@webkit.org
Message:

RenderImageResourceStyleImage::image() should return the nullImage() if the image is not available
https://bugs.webkit.org/show_bug.cgi?id=174874
<rdar://problem/33530130>

Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2017-08-04
Reviewed by Simon Fraser.

Source/WebCore:

If an <img> element has a non-CachedImage content data, e.g. -webkit-named-image,
RenderImageResourceStyleImage will be created and attached to the RenderImage.
RenderImageResourceStyleImage::m_cachedImage will be set to null at the
beginning because the m_styleImage->isCachedImage() is false in this case.
When ImageLoader finishes loading the url of the src attribute,
RenderImageResource::setCachedImage() will be called to set m_cachedImage.

A crash will happen when the RenderImage is destroyed. Destroying the
RenderImage calls RenderImageResourceStyleImage::shutdown() which checks
m_cachedImage and finds it not null, so it calls RenderImageResourceStyleImage::image()
which ends up calling CSSNamedImageValue::image() which returns a null pointer
because the size is empty. RenderImageResourceStyleImage::shutdown() calls
image()->stopAnimation() without checking the return value of image().

Another crash will happen later when deleting the CachedImage from the memory
cache if CachedImage::canDestroyDecodedData() is called because the client
it gets from m_clients is a freed pointer. This happens because RenderImageResourceStyleImage
has m_styleImage of type StyleGeneratedImage but its m_cachedImage is set
by RenderImageResource::setCachedImage(). When RenderImageResourceStyleImage::shutdown()
is called, it calls StyleGeneratedImage::removeClient() which does not
know anything about RenderImageResourceStyleImage::m_cachedImage. So we
end up having a freed pointer in the m_clients of the CachedImage.

Test: fast/images/image-element-image-content-data.html

  • rendering/RenderImageResourceStyleImage.cpp:

(WebCore::RenderImageResourceStyleImage::shutdown): Revert back the changes
of r208511 in this function. Add a call to image()->stopAnimation() without
checking the return of image() since it will return the nullImage() if
the image not available. There is no need to check m_cachedImage before
calling image() because image() does not check or access m_cachedImage.

If m_styleImage is not a CachedStyleImage but m_cachedImage is not null,
we need to remove m_renderer from the set of the clients of this m_cachedImage.

(WebCore::RenderImageResourceStyleImage::image const): The base class method
RenderImageResource::image() returns the nullImage() if the image not
available. This is because CachedImage::imageForRenderer() returns
the nullImage() if the image is not available; see CachedImage.h. We should
do the same for the derived class for consistency.

LayoutTests:

  • fast/images/image-element-image-content-data-expected.txt: Added.
  • fast/images/image-element-image-content-data.html: Added.
Location:
trunk
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r220285 r220289  
     12017-08-04  Said Abou-Hallawa  <sabouhallawa@apple.com>
     2
     3        RenderImageResourceStyleImage::image() should return the nullImage() if the image is not available
     4        https://bugs.webkit.org/show_bug.cgi?id=174874
     5        <rdar://problem/33530130>
     6
     7        Reviewed by Simon Fraser.
     8
     9        * fast/images/image-element-image-content-data-expected.txt: Added.
     10        * fast/images/image-element-image-content-data.html: Added.
     11
    1122017-08-04  Matt Lewis  <jlewis3@apple.com>
    213
  • trunk/Source/WebCore/ChangeLog

    r220288 r220289  
     12017-08-04  Said Abou-Hallawa  <sabouhallawa@apple.com>
     2
     3        RenderImageResourceStyleImage::image() should return the nullImage() if the image is not available
     4        https://bugs.webkit.org/show_bug.cgi?id=174874
     5        <rdar://problem/33530130>
     6
     7        Reviewed by Simon Fraser.
     8
     9        If an <img> element has a non-CachedImage content data, e.g. -webkit-named-image,
     10        RenderImageResourceStyleImage will be created and  attached to the RenderImage.
     11        RenderImageResourceStyleImage::m_cachedImage will be set to null at the
     12        beginning because the m_styleImage->isCachedImage() is false in this case.
     13        When ImageLoader finishes loading the url of the src attribute,
     14        RenderImageResource::setCachedImage() will be called to set m_cachedImage.
     15
     16        A crash will happen when the RenderImage is destroyed. Destroying the
     17        RenderImage calls RenderImageResourceStyleImage::shutdown() which checks
     18        m_cachedImage and finds it not null, so it calls RenderImageResourceStyleImage::image()
     19        which ends up calling CSSNamedImageValue::image() which returns a null pointer
     20        because the size is empty. RenderImageResourceStyleImage::shutdown() calls
     21        image()->stopAnimation() without checking the return value of image().
     22
     23        Another crash will happen later when deleting the CachedImage from the memory
     24        cache if CachedImage::canDestroyDecodedData() is called because the client
     25        it gets from m_clients is a freed pointer. This happens because RenderImageResourceStyleImage
     26        has m_styleImage of type StyleGeneratedImage but its m_cachedImage is set
     27        by RenderImageResource::setCachedImage(). When RenderImageResourceStyleImage::shutdown()
     28        is called, it calls  StyleGeneratedImage::removeClient() which does not
     29        know anything about RenderImageResourceStyleImage::m_cachedImage. So we
     30        end up having a freed pointer in the m_clients of the CachedImage.
     31
     32        Test: fast/images/image-element-image-content-data.html
     33
     34        * rendering/RenderImageResourceStyleImage.cpp:
     35        (WebCore::RenderImageResourceStyleImage::shutdown):  Revert back the changes
     36        of r208511 in this function. Add a call to image()->stopAnimation() without
     37        checking the return of image() since it will return the nullImage() if
     38        the image not available. There is no need to check m_cachedImage before
     39        calling image() because image() does not check or access m_cachedImage.
     40
     41        If m_styleImage is not a CachedStyleImage but m_cachedImage is not null,
     42        we need to remove m_renderer from the set of the clients of this m_cachedImage.
     43
     44        (WebCore::RenderImageResourceStyleImage::image const): The base class method
     45        RenderImageResource::image() returns the nullImage() if the image not
     46        available. This is because CachedImage::imageForRenderer() returns
     47        the nullImage() if the image is not available; see CachedImage.h. We should
     48        do the same for the derived class for consistency.
     49
    1502017-08-04  Jeremy Jones  <jeremyj@apple.com>
    251
  • trunk/Source/WebCore/rendering/RenderImageResourceStyleImage.cpp

    r220073 r220289  
    5757{
    5858    ASSERT(m_renderer);
     59    image()->stopAnimation();
    5960    m_styleImage->removeClient(m_renderer);
    60     if (m_cachedImage) {
    61         image()->stopAnimation();
    62         m_cachedImage = nullptr;
    63     }
     61    if (!m_styleImage->isCachedImage() && m_cachedImage)
     62        m_cachedImage->removeClient(*m_renderer);
     63    m_cachedImage = nullptr;
    6464}
    6565
     
    6767{
    6868    // Generated content may trigger calls to image() while we're still pending, don't assert but gracefully exit.
    69     return !m_styleImage->isPending() ? m_styleImage->image(m_renderer, size) : &Image::nullImage();
     69    if (m_styleImage->isPending())
     70        return &Image::nullImage();
     71    if (auto image = m_styleImage->image(m_renderer, size))
     72        return image;
     73    return &Image::nullImage();
    7074}
    7175
Note: See TracChangeset for help on using the changeset viewer.