Firefox · DOM
CVE-2026-8968
Logic Error in DOM
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifdom/media/webcodecs/ImageDecoder.cpp |
modified |
Files Changed
dom/media/webcodecs/ImageDecoder.cppdom/media/webcodecs/ImageDecoder.hdom/media/webcodecs/ImageTrackList.cpp
Patch
diff --git a/dom/media/webcodecs/ImageDecoder.cpp b/dom/media/webcodecs/ImageDecoder.cpp
index 78a93f22e6a..ae93624cbd1 100644
--- a/dom/media/webcodecs/ImageDecoder.cpp
+++ b/dom/media/webcodecs/ImageDecoder.cpp
@@ -79,7 +79,8 @@ class ImageDecoder::SelectTrackMessage final
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(ImageDecoder)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ImageDecoder)
- tmp->Destroy();
+ tmp->CloseWithoutRef(
+ MediaResult(NS_ERROR_DOM_ABORT_ERR, "Cycle-collected decoder"_ns));
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTracks)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mReadRequest)
@@ -118,7 +119,7 @@ ImageDecoder::ImageDecoder(nsCOMPtr<nsIGlobalObject>&& aParent,
ImageDecoder::~ImageDecoder() {
MOZ_LOG(gWebCodecsLog, LogLevel::Debug,
("ImageDecoder %p ~ImageDecoder", this));
- Destroy();
+ CloseWithoutRef(MediaResult(NS_ERROR_DOM_ABORT_ERR, "Destroyed decoder"_ns));
}
JSObject* ImageDecoder::WrapObject(JSContext* aCx,
@@ -127,33 +128,6 @@ JSObject* ImageDecoder::WrapObject(JSContext* aCx,
return ImageDecoder_Binding::Wrap(aCx, this, aGivenProto);
}
-void ImageDecoder::Destroy() {
- MOZ_LOG(gWebCodecsLog, LogLevel::Debug, ("ImageDecoder %p Destroy", this));
- MOZ_ASSERT(mOutstandingDecodes.IsEmpty());
-
- if (mReadRequest) {
- mReadRequest->Destroy(/* aCancel */ false);
- mReadRequest = nullptr;
- }
-
- if (mDecoder) {
- mDecoder->Destroy();
- }
-
- if (mTracks) {
- mTracks->Destroy();
- }
-
- if (mShutdownWatcher) {
- mShutdownWatcher->Destroy();
- mShutdownWatcher = nullptr;
- }
-
- mSourceBuffer = nullptr;
- mDecoder = nullptr;
- mParent = nullptr;
-}
-
void ImageDecoder::QueueConfigureMessage(
const Maybe<gfx::IntSize>& aOutputSize,
ColorSpaceConversion aColorSpaceConversion) {
@@ -180,7 +154,7 @@ void ImageDecoder::ResumeControlMessageQueue() {
}
void ImageDecoder::ProcessControlMessageQueue() {
- while (!mMessageQueueBlocked && !mControlMessageQueue.empty()) {
+ while (!mClosed && !mMessageQueueBlocked && !mControlMessageQueue.empty()) {
auto& msg = mControlMessageQueue.front();
auto result = MessageProcessedResult::Processed;
if (auto* submsg = msg->AsConfigureMessage()) {
@@ -990,6 +964,7 @@ already_AddRefed<Promise> ImageDecoder::Decode(
QueueDecodeFrameMessage();
// 7. Process the control message queue.
+ RefPtr<ImageDecoder> kungFuDeathGrip(this);
ProcessControlMessageQueue();
// 8. Return promise.
@@ -1036,8 +1011,9 @@ void ImageDecoder::OnDecodeFramesFailed(const nsresult& aErr) {
}
}
-void ImageDecoder::Reset(const MediaResult& aResult) {
- MOZ_LOG(gWebCodecsLog, LogLevel::Debug, ("ImageDecoder %p Reset", this));
+void ImageDecoder::ResetWithoutRef(const MediaResult& aResult) {
+ MOZ_LOG(gWebCodecsLog, LogLevel::Debug,
+ ("ImageDecoder %p Reset '%s'", this, aResult.Message().get()));
// 10.2.5. Reset ImageDecoder (with exception)
// 1. Signal [[codec implementation]] to abort any active decoding operation.
@@ -1058,18 +1034,23 @@ void ImageDecoder::Reset(const MediaResult& aResult) {
void ImageDecoder::Close(const MediaResult& aResult) {
RefPtr<ImageDecoder> kungFuDeathGrip(this);
- MOZ_LOG(gWebCodecsLog, LogLevel::Debug, ("ImageDecoder %p Close", this));
+ CloseWithoutRef(aResult);
+}
+void ImageDecoder::CloseWithoutRef(const MediaResult& aResult) {
if (mClosed) {
return;
}
+ MOZ_LOG(gWebCodecsLog, LogLevel::Debug,
+ ("ImageDecoder %p Close '%s'", this, aResult.Message().get()));
+
// 10.2.5. Algorithms - Close ImageDecoder (with exception)
mClosed = true;
mTypeNotSupported = aResult.Code() == NS_ERROR_DOM_NOT_SUPPORTED_ERR;
// 1. Run the Reset ImageDecoder algorithm with exception.
- Reset(aResult);
+ ResetWithoutRef(aResult);
// 3. Clear [[codec implementation]] and release associated system resources.
if (mDecoder) {
@@ -1093,7 +1074,9 @@ void ImageDecoder::Close(const MediaResult& aResult) {
}
if (!mComplete) {
- aResult.RejectTo(mCompletePromise);
+ if (mCompletePromise) {
+ aResult.RejectTo(mCompletePromise);
+ }
mComplete = true;
}
@@ -1104,7 +1087,8 @@ void ImageDecoder::Close(const MediaResult& aResult) {
}
void ImageDecoder::Reset() {
- Reset(MediaResult(NS_ERROR_DOM_ABORT_ERR, "Reset decoder"_ns));
+ RefPtr<ImageDecoder> kungFuDeathGrip(this);
+ ResetWithoutRef(MediaResult(NS_ERROR_DOM_ABORT_ERR, "Reset decoder"_ns));
}
void ImageDecoder::Close() {
diff --git a/dom/media/webcodecs/ImageDecoder.h b/dom/media/webcodecs/ImageDecoder.h
index ed87b4b047a..855712a4c59 100644
--- a/dom/media/webcodecs/ImageDecoder.h
+++ b/dom/media/webcodecs/ImageDecoder.h
@@ -80,6 +80,8 @@ class ImageDecoder final : public nsISupports,
void QueueSelectTrackMessage(uint32_t aSelectedIndex);
void ProcessControlMessageQueue();
+ void ResetWithoutRef(const MediaResult& aResult);
+
private:
~ImageDecoder();
@@ -104,9 +106,8 @@ class ImageDecoder final : public nsISupports,
void Initialize(const GlobalObject& aGLobal, const ImageDecoderInit& aInit,
ErrorResult& aRv);
- void Destroy();
- void Reset(const MediaResult& aResult);
void Close(const MediaResult& aResult);
+ void CloseWithoutRef(const MediaResult& aResult);
void QueueConfigureMessage(const Maybe<gfx::IntSize>& aOutputSize,
ColorSpaceConversion aColorSpaceConversion);
diff --git a/dom/media/webcodecs/ImageTrackList.cpp b/dom/media/webcodecs/ImageTrackList.cpp
index aa4314ec06d..455e70a6a6b 100644
--- a/dom/media/webcodecs/ImageTrackList.cpp
+++ b/dom/media/webcodecs/ImageTrackList.cpp
@@ -201,14 +201,16 @@ void ImageTrackList::SetSelectedIndex(int32_t aIndex, bool aSelected) {
}
// 10. Run the Reset ImageDecoder algorithm on [[ImageDecoder]].
- mDecoder->Reset();
+ RefPtr<ImageDecoder> decoder = mDecoder;
+ decoder->ResetWithoutRef(
+ MediaResult(NS_ERROR_DOM_ABORT_ERR, "Reset decoder (select index)"_ns));
// 11. Queue a control message to [[ImageDecoder]]'s control message queue to
// update the internal selected track index with selectedIndex.
- mDecoder->QueueSelectTrackMessage(mSelectedIndex);
+ decoder->QueueSelectTrackMessage(mSelectedIndex);
// 12. Process the control message queue belonging to [[ImageDecoder]].
- mDecoder->ProcessControlMessageQueue();
+ decoder->ProcessControlMessageQueue();
}
} // namespace mozilla::dom
Loading diff…
References
On This Page