[Webkit-unassigned] [Bug 173077] New: Image should clear its ImageObserver* when CachedImage releases the last reference to its RefCounted<ImageObserver>
bugzilla-daemon at webkit.org
bugzilla-daemon at webkit.org
Wed Jun 7 15:07:17 PDT 2017
https://bugs.webkit.org/show_bug.cgi?id=173077
Bug ID: 173077
Summary: Image should clear its ImageObserver* when CachedImage
releases the last reference to its
RefCounted<ImageObserver>
Product: WebKit
Version: WebKit Nightly Build
Hardware: Unspecified
OS: Unspecified
Status: NEW
Severity: Normal
Priority: P2
Component: Images
Assignee: webkit-unassigned at lists.webkit.org
Reporter: sabouhallawa at apple.com
Here is how the objects Image, ImageObserver and CachedImage are related to each other.
-- CachedImage has a RefPtr<Image> and RefPtr<ImageObserver> (or actually it is RefPtr<CachedImageObserver>). CachedImage is the creator and the destroyer of these two pointers.
-- ImageObserver has a Vector<CachedImage*>. CachedImage maintains correct state for this vector by adding and removing itself upon creation and deletion.
-- Image has a raw pointer of ImageObserver*. This pointer is only cleared temporarily but it is never cleared permanently.
Two things to mention here:
-- CachedImage can clone itself to another CachedImage through CachedImage::setBodyDataFrom(). The RefPtr<Image> and RefPtr<ImageObserver> will be set in the cloned CachedImage, which means their ref counts are incremented.
-- Image object can outlive the CachedImage. In the CachedImage destructor, CachedImage::clearImage() is called to clear the references from the ImageObserver to the destructing CachedImage.
If CachedImage releases the last reference to its ImageObserver, this ImageObserver will eventually be deleted. A crash can happen if the Image accesses its raw pointer after the ImageObserver is deleted. So ideally CachedImage::clearImage(): should set the m_imageObserver of the Image to nullptr by calling m_image->setImageObserver(nullptr). But since the CachedImage can be cloned, ImageObserver will not be deleted until the last referencing CachedImage calls CachedImage::clearImage(). So calling m_image->setImageObserver(nullptr) unconditionally from CachedImage::clearImage() is wrong as well.
This is the history of CachedImage::clearImage():
Before https://trac.webkit.org/changeset/209914
inline void CachedImage::clearImage()
{
// If our Image has an observer, it's always us so we need to clear the back pointer
// before dropping our reference.
if (m_image)
m_image->setImageObserver(nullptr);
m_image = nullptr;
}
After https://trac.webkit.org/changeset/209914
inline void CachedImage::clearImage()
{
if (m_imageObserver) {
m_imageObserver->remove(*this);
m_imageObserver = nullptr;
}
m_image = nullptr;
}
After https://trac.webkit.org/changeset/216273
inline void CachedImage::clearImage()
{
if (m_imageObserver) {
m_imageObserver->remove(*this);
m_imageObserver = nullptr;
}
if (m_image) {
m_image->setImageObserver(nullptr);
m_image = nullptr;
}
}
But this caused a crash in http/tests/security/cross-origin-cached-images-with-memory-pressure.html so it was rolled out in https://trac.webkit.org/changeset/216293.
So we still have a bug for not clearing the raw pointer Image::m_imageObserver if CachedImage releases the last reference to its CachedImage::m_imageObserver and Image accesses the deleted ImageObserver through the raw pointer Image::m_imageObserver.
--
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.webkit.org/pipermail/webkit-unassigned/attachments/20170607/1025db78/attachment.html>
More information about the webkit-unassigned
mailing list