High firefox Logic Error 🔧 Commit mapped

Overview

High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Impacthigh
DescriptionUse-after-free in the Audio/Video: Web Codecs component
ComponentDOM
Bug ClassLogic Error
Tracker2056051
Fix commite8ff0efe95ed (firefox) +14/-5
CISA KEVNot listed
Crediteddevdharan9424@gmail.com
Disclosed2026-09-15

Changed Functions

FunctionChangeNotes
if
dom/media/webcodecs/ImageDecoder.cpp
modified

Files Changed

  • dom/base/NodeIterator.cpp
  • dom/media/webcodecs/ImageDecoder.cpp
  • dom/media/webcodecs/ImageDecoder.h
diff --git a/dom/base/NodeIterator.cpp b/dom/base/NodeIterator.cpp
index dda163e6fa9..2034517fbe7 100644
--- a/dom/base/NodeIterator.cpp
+++ b/dom/base/NodeIterator.cpp
@@ -141,6 +141,8 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(NodeIterator)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(NodeIterator)
   if (tmp->mRoot) tmp->mRoot->RemoveMutationObserver(tmp);
+  tmp->mPointer.Clear();
+  tmp->mWorkingPointer.Clear();
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFilter)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
diff --git a/dom/media/webcodecs/ImageDecoder.cpp b/dom/media/webcodecs/ImageDecoder.cpp
index 30857ef982b..991b608da5d 100644
--- a/dom/media/webcodecs/ImageDecoder.cpp
+++ b/dom/media/webcodecs/ImageDecoder.cpp
@@ -79,8 +79,11 @@ class ImageDecoder::SelectTrackMessage final
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(ImageDecoder)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ImageDecoder)
+  // Do not cancel mReadRequest here: cancellation synchronously invokes the
+  // page's UnderlyingSource.cancel() callback
   tmp->CloseWithoutRef(
-      MediaResult(NS_ERROR_DOM_ABORT_ERR, "Cycle-collected decoder"_ns));
+      MediaResult(NS_ERROR_DOM_ABORT_ERR, "Cycle-collected decoder"_ns),
+      /* aCancelReadRequest */ false);
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTracks)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mReadRequest)
@@ -119,7 +122,9 @@ ImageDecoder::ImageDecoder(nsCOMPtr<nsIGlobalObject>&& aParent,
 ImageDecoder::~ImageDecoder() {
   MOZ_LOG_FMT(gWebCodecsLog, LogLevel::Debug, "ImageDecoder {} ~ImageDecoder",
               fmt::ptr(this));
-  CloseWithoutRef(MediaResult(NS_ERROR_DOM_ABORT_ERR, "Destroyed decoder"_ns));
+  // Similar to CYCLE_COLLECTION_UNLINK_BEGIN above
+  CloseWithoutRef(MediaResult(NS_ERROR_DOM_ABORT_ERR, "Destroyed decoder"_ns),
+                  /* aCancelReadRequest */ false);
 }
 
 JSObject* ImageDecoder::WrapObject(JSContext* aCx,
@@ -1082,7 +1087,8 @@ void ImageDecoder::Close(const MediaResult& aResult) {
   CloseWithoutRef(aResult);
 }
 
-void ImageDecoder::CloseWithoutRef(const MediaResult& aResult) {
+void ImageDecoder::CloseWithoutRef(const MediaResult& aResult,
+                                   bool aCancelReadRequest) {
   if (mClosed) {
     return;
   }
@@ -1103,7 +1109,7 @@ void ImageDecoder::CloseWithoutRef(const MediaResult& aResult) {
   }
 
   if (mReadRequest) {
-    mReadRequest->Destroy(/* aCancel */ true);
+    mReadRequest->Destroy(aCancelReadRequest);
     mReadRequest = nullptr;
   }
 
diff --git a/dom/media/webcodecs/ImageDecoder.h b/dom/media/webcodecs/ImageDecoder.h
index fa508bbfb7a..eccb162a70d 100644
--- a/dom/media/webcodecs/ImageDecoder.h
+++ b/dom/media/webcodecs/ImageDecoder.h
@@ -107,7 +107,8 @@ class ImageDecoder final : public nsISupports,
   void Initialize(const GlobalObject& aGLobal, const ImageDecoderInit& aInit,
                   ErrorResult& aRv);
   void Close(const MediaResult& aResult);
-  void CloseWithoutRef(const MediaResult& aResult);
+  void CloseWithoutRef(const MediaResult& aResult,
+                       bool aCancelReadRequest = true);
 
   void QueueConfigureMessage(const Maybe<gfx::IntSize>& aOutputSize,
                              ColorSpaceConversion aColorSpaceConversion);
Loading diff…