Firefox · DOM
CVE-2026-6747
UAF in DOM
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
mOwnerdom/media/webrtc/jsapi/RTCEncodedAudioFrame.cpp |
modified | |
ifdom/media/webrtc/jsapi/RTCEncodedFrameBase.cpp |
modified | |
RTCEncodedFrameBasedom/media/webrtc/jsapi/RTCEncodedFrameBase.h |
modified | |
mOwnerdom/media/webrtc/jsapi/RTCEncodedVideoFrame.cpp |
modified |
Files Changed
dom/media/webrtc/jsapi/RTCEncodedAudioFrame.cppdom/media/webrtc/jsapi/RTCEncodedAudioFrame.hdom/media/webrtc/jsapi/RTCEncodedFrameBase.cppdom/media/webrtc/jsapi/RTCEncodedFrameBase.hdom/media/webrtc/jsapi/RTCEncodedVideoFrame.cppdom/media/webrtc/jsapi/RTCEncodedVideoFrame.h
Patch
diff --git a/dom/media/webrtc/jsapi/RTCEncodedAudioFrame.cpp b/dom/media/webrtc/jsapi/RTCEncodedAudioFrame.cpp
index 5dd474ce6db..d65ef46375e 100644
--- a/dom/media/webrtc/jsapi/RTCEncodedAudioFrame.cpp
+++ b/dom/media/webrtc/jsapi/RTCEncodedAudioFrame.cpp
@@ -14,7 +14,6 @@
#include "js/RootingAPI.h"
#include "jsapi/RTCEncodedFrameBase.h"
#include "jsapi/RTCRtpScriptTransform.h"
-#include "mozilla/HoldDropJSObjects.h"
#include "mozilla/RefPtr.h"
#include "mozilla/dom/RTCEncodedAudioFrameBinding.h"
#include "mozilla/dom/RTCRtpScriptTransformer.h"
@@ -22,42 +21,20 @@
#include "mozilla/dom/StructuredCloneTags.h"
#include "mozilla/fallible.h"
#include "nsContentUtils.h"
-#include "nsCycleCollectionParticipant.h"
#include "nsIGlobalObject.h"
#include "nsISupports.h"
#include "nsWrapperCache.h"
namespace mozilla::dom {
-NS_IMPL_CYCLE_COLLECTION_CLASS(RTCEncodedAudioFrame)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(RTCEncodedAudioFrame,
- RTCEncodedFrameBase)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
- NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(RTCEncodedAudioFrame,
- RTCEncodedFrameBase)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(RTCEncodedAudioFrame,
- RTCEncodedFrameBase)
- NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-NS_IMPL_ADDREF_INHERITED(RTCEncodedAudioFrame, RTCEncodedFrameBase)
-NS_IMPL_RELEASE_INHERITED(RTCEncodedAudioFrame, RTCEncodedFrameBase)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RTCEncodedAudioFrame)
- NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-NS_INTERFACE_MAP_END_INHERITING(RTCEncodedFrameBase)
-
RTCEncodedAudioFrame::RTCEncodedAudioFrame(
nsIGlobalObject* aGlobal,
std::unique_ptr<webrtc::TransformableFrameInterface> aFrame,
uint64_t aCounter, RTCRtpScriptTransformer* aOwner)
: RTCEncodedAudioFrameData{RTCEncodedFrameState{std::move(aFrame), aCounter,
/*timestamp*/ 0}},
- RTCEncodedFrameBase(aGlobal, static_cast<RTCEncodedFrameState&>(*this)),
- mOwner(aOwner) {
+ RTCEncodedFrameBase(aGlobal, static_cast<RTCEncodedFrameState&>(*this),
+ aOwner) {
mMetadata.mSynchronizationSource.Construct(mFrame->GetSsrc());
mMetadata.mPayloadType.Construct(mFrame->GetPayloadType());
const auto& audioFrame(
@@ -69,10 +46,6 @@ RTCEncodedAudioFrame::RTCEncodedAudioFrame(
if (const auto optionalSeqNum = audioFrame.SequenceNumber()) {
mMetadata.mSequenceNumber.Construct(*optionalSeqNum);
}
-
- // Base class needs this, but can't do it itself because of an assertion in
- // the cycle-collector.
- mozilla::HoldJSObjects(this);
}
RTCEncodedAudioFrame::RTCEncodedAudioFrame(nsIGlobalObject* aGlobal,
@@ -81,21 +54,8 @@ RTCEncodedAudioFrame::RTCEncodedAudioFrame(nsIGlobalObject* aGlobal,
aData.mCounter,
aData.mTimestamp},
std::move(aData.mMetadata)},
- RTCEncodedFrameBase(aGlobal, static_cast<RTCEncodedFrameState&>(*this)),
- mOwner(nullptr) {
- // Base class needs this, but can't do it itself because of an assertion in
- // the cycle-collector.
- mozilla::HoldJSObjects(this);
-}
-
-RTCEncodedAudioFrame::~RTCEncodedAudioFrame() {
- // Clear JS::Heap<> members before unregistering as a script holder,
- // so their destructors don't barrier against a finalized JS object.
- mData = nullptr; // from RTCEncodedFrameBase (protected)
- // Base class needs this, but can't do it itself because of an assertion in
- // the cycle-collector.
- mozilla::DropJSObjects(this);
-}
+ RTCEncodedFrameBase(aGlobal, static_cast<RTCEncodedFrameState&>(*this),
+ nullptr) {}
JSObject* RTCEncodedAudioFrame::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
@@ -137,10 +97,6 @@ RTCEncodedAudioFrameData RTCEncodedAudioFrameData::Clone() const {
RTCEncodedAudioFrameMetadata(mMetadata)};
}
-nsIGlobalObject* RTCEncodedAudioFrame::GetParentObject() const {
- return mGlobal;
-}
-
void RTCEncodedAudioFrame::GetMetadata(
RTCEncodedAudioFrameMetadata& aMetadata) const {
aMetadata = mMetadata;
diff --git a/dom/media/webrtc/jsapi/RTCEncodedAudioFrame.h b/dom/media/webrtc/jsapi/RTCEncodedAudioFrame.h
index 4c1f794ccef..001ce00a7d8 100644
--- a/dom/media/webrtc/jsapi/RTCEncodedAudioFrame.h
+++ b/dom/media/webrtc/jsapi/RTCEncodedAudioFrame.h
@@ -5,7 +5,6 @@
#ifndef MOZILLA_DOM_MEDIA_WEBRTC_JSAPI_RTCENCODEDAUDIOFRAME_H_
#define MOZILLA_DOM_MEDIA_WEBRTC_JSAPI_RTCENCODEDAUDIOFRAME_H_
-#include "mozilla/RefPtr.h"
#include "mozilla/dom/RTCEncodedAudioFrameBinding.h"
#include "mozilla/dom/RTCEncodedFrameBase.h"
#include "nsIGlobalObject.h"
@@ -36,11 +35,6 @@ class RTCEncodedAudioFrame final : public RTCEncodedAudioFrameData,
explicit RTCEncodedAudioFrame(nsIGlobalObject* aGlobal,
RTCEncodedAudioFrameData&& aData);
- // nsISupports
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(RTCEncodedAudioFrame,
- RTCEncodedFrameBase)
-
// webidl (timestamp and data accessors live in base class)
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
@@ -49,8 +43,6 @@ class RTCEncodedAudioFrame final : public RTCEncodedAudioFrameData,
const GlobalObject& aGlobal, const RTCEncodedAudioFrame& aOriginalFrame,
const RTCEncodedAudioFrameOptions& aOptions, ErrorResult& aRv);
- nsIGlobalObject* GetParentObject() const;
-
void GetMetadata(RTCEncodedAudioFrameMetadata& aMetadata) const;
bool CheckOwner(RTCRtpScriptTransformer* aOwner) const override;
@@ -64,7 +56,7 @@ class RTCEncodedAudioFrame final : public RTCEncodedAudioFrameData,
StructuredCloneHolder* aHolder) const;
private:
- virtual ~RTCEncodedAudioFrame();
+ virtual ~RTCEncodedAudioFrame() = default;
// forbid copy/move to keep mState member in base valid
RTCEncodedAudioFrame(const RTCEncodedAudioFrame&) = delete;
@@ -76,8 +68,6 @@ class RTCEncodedAudioFrame final : public RTCEncodedAudioFrameData,
void AssertIsOnOwningThread() const {
NS_ASSERT_OWNINGTHREAD(RTCEncodedAudioFrame);
}
-
- RefPtr<RTCRtpScriptTransformer> mOwner;
};
} // namespace mozilla::dom
diff --git a/dom/media/webrtc/jsapi/RTCEncodedFrameBase.cpp b/dom/media/webrtc/jsapi/RTCEncodedFrameBase.cpp
index 6c1e0dd0bc5..455c26e3be1 100644
--- a/dom/media/webrtc/jsapi/RTCEncodedFrameBase.cpp
+++ b/dom/media/webrtc/jsapi/RTCEncodedFrameBase.cpp
@@ -7,6 +7,7 @@
#include "api/frame_transformer_interface.h"
#include "js/ArrayBuffer.h"
#include "js/GCAPI.h"
+#include "mozilla/HoldDropJSObjects.h"
#include "mozilla/dom/ScriptSettings.h"
#include "nsIGlobalObject.h"
@@ -16,32 +17,38 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(RTCEncodedFrameBase)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(RTCEncodedFrameBase)
using ::ImplCycleCollectionUnlink;
tmp->DetachData();
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner, mGlobal)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mData)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(RTCEncodedFrameBase)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner, mGlobal)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(RTCEncodedFrameBase)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBERS(mData)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(RTCEncodedFrameBase)
NS_IMPL_CYCLE_COLLECTING_RELEASE(RTCEncodedFrameBase)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RTCEncodedFrameBase)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
RTCEncodedFrameBase::RTCEncodedFrameBase(nsIGlobalObject* aGlobal,
- RTCEncodedFrameState& aState)
- : mGlobal(aGlobal), mState(aState), mData(nullptr) {
+ RTCEncodedFrameState& aState,
+ RTCRtpScriptTransformer* aOwner)
+ : mGlobal(aGlobal), mOwner(aOwner), mState(aState), mData(nullptr) {
mState.mTimestamp = mState.mFrame->GetTimestamp();
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(mGlobal))) {
return;
}
+ mozilla::HoldJSObjects(this);
+
// Avoid a copy
mData = JS::NewArrayBufferWithUserOwnedContents(
jsapi.cx(), mState.mFrame->GetData().size(),
@@ -53,11 +60,15 @@ RTCEncodedFrameState::RTCEncodedFrameState(
uint64_t aCounter, unsigned long aTimestamp)
: mFrame(std::move(aFrame)), mCounter(aCounter), mTimestamp(aTimestamp) {}
-RTCEncodedFrameBase::~RTCEncodedFrameBase() { DetachData(); }
+RTCEncodedFrameBase::~RTCEncodedFrameBase() {
+ DetachData();
+ mData = nullptr;
+ mozilla::DropJSObjects(this);
+}
void RTCEncodedFrameBase::DetachData() {
// We might have handled this in unlink already
- if (mGlobal) {
+ if (mGlobal && mData) {
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(mGlobal))) {
return;
@@ -70,6 +81,10 @@ void RTCEncodedFrameBase::DetachData() {
}
}
+nsIGlobalObject* RTCEncodedFrameBase::GetParentObject() const {
+ return mGlobal;
+}
+
unsigned long RTCEncodedFrameBase::Timestamp() const {
return mState.mTimestamp;
}
diff --git a/dom/media/webrtc/jsapi/RTCEncodedFrameBase.h b/dom/media/webrtc/jsapi/RTCEncodedFrameBase.h
index 5df6b3780be..15e6432ef28 100644
--- a/dom/media/webrtc/jsapi/RTCEncodedFrameBase.h
+++ b/dom/media/webrtc/jsapi/RTCEncodedFrameBase.h
@@ -43,12 +43,15 @@ class RTCRtpScriptTransformer;
class RTCEncodedFrameBase : public nsISupports, public nsWrapperCache {
public:
explicit RTCEncodedFrameBase(nsIGlobalObject* aGlobal,
- RTCEncodedFrameState& aState);
+ RTCEncodedFrameState& aState,
+ RTCRtpScriptTransformer* aOwner);
// nsISupports
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(RTCEncodedFrameBase)
+ nsIGlobalObject* GetParentObject() const;
+
// Common webidl for RTCEncodedVideoFrame/RTCEncodedAudioFrame
unsigned long Timestamp() const;
@@ -75,6 +78,7 @@ class RTCEncodedFrameBase : public nsISupports, public nsWrapperCache {
RTCEncodedFrameBase& operator=(RTCEncodedFrameBase&&) = delete;
RefPtr<nsIGlobalObject> mGlobal;
+ RefPtr<RTCRtpScriptTransformer> mOwner;
// Keep serializable state separate in this base and its subclasses
// in a manner that avoids diamond inheritance. Subclasses must pass
diff --git a/dom/media/webrtc/jsapi/RTCEncodedVideoFrame.cpp b/dom/media/webrtc/jsapi/RTCEncodedVideoFrame.cpp
index 638db726ff9..47e53471344 100644
--- a/dom/media/webrtc/jsapi/RTCEncodedVideoFrame.cpp
+++ b/dom/media/webrtc/jsapi/RTCEncodedVideoFrame.cpp
@@ -21,45 +21,21 @@
#include "mozilla/dom/StructuredCloneTags.h"
#include "mozilla/fallible.h"
#include "nsContentUtils.h"
-#include "nsCycleCollectionParticipant.h"
#include "nsIGlobalObject.h"
#include "nsISupports.h"
#include "nsWrapperCache.h"
namespace mozilla::dom {
-NS_IMPL_CYCLE_COLLECTION_CLASS(RTCEncodedVideoFrame)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(RTCEncodedVideoFrame,
- RTCEncodedFrameBase)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
- NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(RTCEncodedVideoFrame,
- RTCEncodedFrameBase)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(RTCEncodedVideoFrame,
- RTCEncodedFrameBase)
- NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-NS_IMPL_ADDREF_INHERITED(RTCEncodedVideoFrame, RTCEncodedFrameBase)
-NS_IMPL_RELEASE_INHERITED(RTCEncodedVideoFrame, RTCEncodedFrameBase)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RTCEncodedVideoFrame)
- NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-NS_INTERFACE_MAP_END_INHERITING(RTCEncodedFrameBase)
-
RTCEncodedVideoFrame::RTCEncodedVideoFrame(
nsIGlobalObject* aGlobal,
std::unique_ptr<webrtc::TransformableFrameInterface> aFrame,
uint64_t aCounter, RTCRtpScriptTransformer* aOwner)
: RTCEncodedVideoFrameData{RTCEncodedFrameState{std::move(aFrame), aCounter,
/*timestamp*/ 0}},
- RTCEncodedFrameBase(aGlobal, static_cast<RTCEncodedFrameState&>(*this)),
- mOwner(aOwner) {
+ RTCEncodedFrameBase(aGlobal, static_cast<RTCEncodedFrameState&>(*this),
+ aOwner) {
InitMetadata();
- // Base class needs this, but can't do it itself because of an assertion in
- // the cycle-collector.
- mozilla::HoldJSObjects(this);
}
RTCEncodedVideoFrame::RTCEncodedVideoFrame(nsIGlobalObject* aGlobal,
@@ -69,12 +45,8 @@ RTCEncodedVideoFrame::RTCEncodedVideoFrame(nsIGlobalObject* aGlobal,
aData.mTimestamp},
aData.mType, std::move(aData.mMetadata),
aData.mRid},
- RTCEncodedFrameBase(aGlobal, static_cast<RTCEncodedFrameState&>(*this)),
- mOwner(nullptr) {
- // Base class needs this, but can't do it itself because of an assertion in
- // the cycle-collector.
- mozilla::HoldJSObjects(this);
-}
+ RTCEncodedFrameBase(aGlobal, static_cast<RTCEncodedFrameState&>(*this),
+ nullptr) {}
void RTCEncodedVideoFrame::InitMetadata() {
const auto& videoFrame(
@@ -113,15 +85,6 @@ void RTCEncodedVideoFrame::InitMetadata() {
}
}
-RTCEncodedVideoFrame::~RTCEncodedVideoFrame() {
- // Clear JS::Heap<> members before unregistering as a script holder,
- // so their destructors don't barrier against a finalized JS object.
- mData = nullptr; // from RTCEncodedFrameBase (protected)
- // Base class needs this, but can't do it itself because of an assertion in
- // the cycle-collector.
- mozilla::DropJSObjects(this);
-}
-
JSObject* RTCEncodedVideoFrame::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
return RTCEncodedVideoFrame_Binding::Wrap(aCx, this, aGivenProto);
@@ -170,10 +133,6 @@ RTCEncodedVideoFrameData RTCEncodedVideoFrameData::Clone() const {
mType, RTCEncodedVideoFrameMetadata(mMetadata), mRid};
}
-nsIGlobalObject* RTCEncodedVideoFrame::GetParentObject() const {
- return mGlobal;
-}
-
RTCEncodedVideoFrameType RTCEncodedVideoFrame::Type() const { return mType; }
void RTCEncodedVideoFrame::GetMetadata(
diff --git a/dom/media/webrtc/jsapi/RTCEncodedVideoFrame.h b/dom/media/webrtc/jsapi/RTCEncodedVideoFrame.h
index 1e0811b4930..20da221e339 100644
--- a/dom/media/webrtc/jsapi/RTCEncodedVideoFrame.h
+++ b/dom/media/webrtc/jsapi/RTCEncodedVideoFrame.h
@@ -5,7 +5,6 @@
#ifndef MOZILLA_DOM_MEDIA_WEBRTC_JSAPI_RTCENCODEDVIDEOFRAME_H_
#define MOZILLA_DOM_MEDIA_WEBRTC_JSAPI_RTCENCODEDVIDEOFRAME_H_
-#include "mozilla/RefPtr.h"
#include "mozilla/dom/RTCEncodedFrameBase.h"
#include "mozilla/dom/RTCEncodedVideoFrameBinding.h"
#include "nsIGlobalObject.h"
@@ -39,11 +38,6 @@ class RTCEncodedVideoFrame final : public RTCEncodedVideoFrameData,
explicit RTCEncodedVideoFrame(nsIGlobalObject* aGlobal,
RTCEncodedVideoFrameData&& aData);
- // nsISupports
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(RTCEncodedVideoFrame,
- RTCEncodedFrameBase)
-
// webidl (timestamp and data accessors live in base class)
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
@@ -52,8 +46,6 @@ class RTCEncodedVideoFrame final : public RTCEncodedVideoFrameData,
const GlobalObject& aGlobal, const RTCEncodedVideoFrame& aOriginalFrame,
const RTCEncodedVideoFrameOptions& aOptions, ErrorResult& aRv);
- nsIGlobalObject* GetParentObject() const;
-
RTCEncodedVideoFrameType Type() const;
void InitMetadata();
@@ -75,7 +67,7 @@ class RTCEncodedVideoFrame final : public RTCEncodedVideoFrameData,
StructuredCloneHolder* aHolder) const;
private:
- virtual ~RTCEncodedVideoFrame();
+ virtual ~RTCEncodedVideoFrame() = default;
... (file diff truncated)
Loading diff…
References
On This Page