RenderImageResourceStyleImage::image() should return the nullImage() if the image...
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Aug 2017 20:42:43 +0000 (20:42 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Aug 2017 20:42:43 +0000 (20:42 +0000)
commit17d99a18e22b58ff4ca2376abe5d6748729a50b0
tree8b5a460e3b7426cbcc3c18d8f6d2ee90d6442ec1
parent29aeb9a1a757b2da9b48bbdab3f7d3adccb2f7bb
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.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@220289 268f45cc-cd09-0410-ab3c-d52691b4dbfc
LayoutTests/ChangeLog
LayoutTests/fast/images/image-element-image-content-data-expected.txt [new file with mode: 0644]
LayoutTests/fast/images/image-element-image-content-data.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderImageResourceStyleImage.cpp