High firefox Logic Error 🔧 Commit mapped

Overview

High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Impacthigh
DescriptionUse-after-free in the Graphics: ImageLib component
ComponentImageLib
Bug ClassLogic Error
Tracker2079069
Fix commit3f0e52fe9455 (firefox) +32/-26
CISA KEVNot listed
CreditedMozilla
Disclosed2026-10-27

Changed Functions

FunctionChangeNotes
GetFrame
image/ImageWrapper.cpp
modified
StartDecoding
image/ImageWrapper.cpp
modified
RequestDiscard
image/ImageWrapper.cpp
modified
RequestRefresh
image/ImageWrapper.cpp
modified
ResetAnimation
image/ImageWrapper.cpp
modified
GetFrameIndex
image/ImageWrapper.cpp
modified
if
image/MultipartImage.cpp
modified

Files Changed

  • image/ImageWrapper.cpp
  • image/MultipartImage.cpp
diff --git a/image/ImageWrapper.cpp b/image/ImageWrapper.cpp
index 7d314a17138..a3ad450af01 100644
--- a/image/ImageWrapper.cpp
+++ b/image/ImageWrapper.cpp
@@ -155,13 +155,15 @@ ImageWrapper::GetAnimated(bool* aAnimated) {
 
 NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
 ImageWrapper::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) {
-  return mInnerImage->GetFrame(aWhichFrame, aFlags);
+  RefPtr<Image> inner = mInnerImage;
+  return inner->GetFrame(aWhichFrame, aFlags);
 }
 
 NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
 ImageWrapper::GetFrameAtSize(const IntSize& aSize, uint32_t aWhichFrame,
                              uint32_t aFlags) {
-  return mInnerImage->GetFrameAtSize(aSize, aWhichFrame, aFlags);
+  RefPtr<Image> inner = mInnerImage;
+  return inner->GetFrameAtSize(aSize, aWhichFrame, aFlags);
 }
 
 NS_IMETHODIMP_(bool)
@@ -180,8 +182,9 @@ ImageWrapper::GetImageProvider(WindowRenderer* aRenderer,
                                const Maybe<ImageIntRegion>& aRegion,
                                uint32_t aFlags,
                                WebRenderImageProvider** aProvider) {
-  return mInnerImage->GetImageProvider(aRenderer, aSize, aSVGContext, aRegion,
-                                       aFlags, aProvider);
+  RefPtr<Image> inner = mInnerImage;
+  return inner->GetImageProvider(aRenderer, aSize, aSVGContext, aRegion, aFlags,
+                                 aProvider);
 }
 
 NS_IMETHODIMP_(ImgDrawResult)
@@ -190,18 +193,21 @@ ImageWrapper::Draw(gfxContext* aContext, const nsIntSize& aSize,
                    SamplingFilter aSamplingFilter,
                    const SVGImageContext& aSVGContext, uint32_t aFlags,
                    float aOpacity) {
-  return mInnerImage->Draw(aContext, aSize, aRegion, aWhichFrame,
-                           aSamplingFilter, aSVGContext, aFlags, aOpacity);
+  RefPtr<Image> inner = mInnerImage;
+  return inner->Draw(aContext, aSize, aRegion, aWhichFrame, aSamplingFilter,
+                     aSVGContext, aFlags, aOpacity);
 }
 
 NS_IMETHODIMP
 ImageWrapper::StartDecoding(uint32_t aFlags, uint32_t aWhichFrame) {
-  return mInnerImage->StartDecoding(aFlags, aWhichFrame);
+  RefPtr<Image> inner = mInnerImage;
+  return inner->StartDecoding(aFlags, aWhichFrame);
 }
 
 bool ImageWrapper::StartDecodingWithResult(uint32_t aFlags,
                                            uint32_t aWhichFrame) {
-  return mInnerImage->StartDecodingWithResult(aFlags, aWhichFrame);
+  RefPtr<Image> inner = mInnerImage;
+  return inner->StartDecodingWithResult(aFlags, aWhichFrame);
 }
 
 bool ImageWrapper::HasDecodedPixels() {
@@ -210,13 +216,15 @@ bool ImageWrapper::HasDecodedPixels() {
 
 imgIContainer::DecodeResult ImageWrapper::RequestDecodeWithResult(
     uint32_t aFlags, uint32_t aWhichFrame) {
-  return mInnerImage->RequestDecodeWithResult(aFlags, aWhichFrame);
+  RefPtr<Image> inner = mInnerImage;
+  return inner->RequestDecodeWithResult(aFlags, aWhichFrame);
 }
 
 NS_IMETHODIMP
 ImageWrapper::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags,
                                    uint32_t aWhichFrame) {
-  return mInnerImage->RequestDecodeForSize(aSize, aFlags, aWhichFrame);
+  RefPtr<Image> inner = mInnerImage;
+  return inner->RequestDecodeForSize(aSize, aFlags, aWhichFrame);
 }
 
 NS_IMETHODIMP
@@ -234,7 +242,10 @@ ImageWrapper::UnlockImage() {
 }
 
 NS_IMETHODIMP
-ImageWrapper::RequestDiscard() { return mInnerImage->RequestDiscard(); }
+ImageWrapper::RequestDiscard() {
+  RefPtr<Image> inner = mInnerImage;
+  return inner->RequestDiscard();
+}
 
 NS_IMETHODIMP_(void)
 ImageWrapper::RequestRefresh(const TimeStamp& aTime) {
@@ -253,7 +264,10 @@ ImageWrapper::SetAnimationMode(uint16_t aAnimationMode) {
 }
 
 NS_IMETHODIMP
-ImageWrapper::ResetAnimation() { return mInnerImage->ResetAnimation(); }
+ImageWrapper::ResetAnimation() {
+  RefPtr<Image> inner = mInnerImage;
+  return inner->ResetAnimation();
+}
 
 NS_IMETHODIMP_(float)
 ImageWrapper::GetFrameIndex(uint32_t aWhichFrame) {
diff --git a/image/MultipartImage.cpp b/image/MultipartImage.cpp
index fdb3f0a2b00..872e70f38ed 100644
--- a/image/MultipartImage.cpp
+++ b/image/MultipartImage.cpp
@@ -301,13 +301,9 @@ nsresult MultipartImage::OnImageDataAvailable(nsIRequest* aRequest,
   // Note that this method is special in that we forward it to the next part if
   // one exists, and *not* the current part.
 
-  // We may trigger notifications that will free mNextPart, so keep it alive.
-  RefPtr<Image> nextPart = mNextPart;
-  if (nextPart) {
-    nextPart->OnImageDataAvailable(aRequest, aInStr, aSourceOffset, aCount);
-  } else {
-    InnerImage()->OnImageDataAvailable(aRequest, aInStr, aSourceOffset, aCount);
-  }
+  // We may trigger notifications that will free the part, so keep it alive.
+  RefPtr<Image> part = mNextPart ? mNextPart.get() : InnerImage();
+  part->OnImageDataAvailable(aRequest, aInStr, aSourceOffset, aCount);
 
   return NS_OK;
 }
@@ -317,13 +313,9 @@ nsresult MultipartImage::OnImageDataComplete(nsIRequest* aRequest,
   // Note that this method is special in that we forward it to the next part if
   // one exists, and *not* the current part.
 
-  // We may trigger notifications that will free mNextPart, so keep it alive.
-  RefPtr<Image> nextPart = mNextPart;
-  if (nextPart) {
-    nextPart->OnImageDataComplete(aRequest, aStatus, aLastPart);
-  } else {
-    InnerImage()->OnImageDataComplete(aRequest, aStatus, aLastPart);
-  }
+  // We may trigger notifications that will free the part, so keep it alive.
+  RefPtr<Image> part = mNextPart ? mNextPart.get() : InnerImage();
+  part->OnImageDataComplete(aRequest, aStatus, aLastPart);
 
   return NS_OK;
 }
Loading diff…