Firefox · DOM
CVE-2025-14321
UAF in DOM
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifdom/media/webrtc/jsapi/RTCEncodedFrameBase.cpp |
modified | |
TakeFramedom/media/webrtc/jsapi/RTCEncodedFrameBase.cpp |
modified |
Files Changed
dom/media/webrtc/jsapi/RTCEncodedFrameBase.cppdom/media/webrtc/jsapi/RTCEncodedFrameBase.htesting/web-platform/tests/webrtc-encoded-transform/RTCRtpScriptTransform-sender-worker-single-frame.https.html
Patch
diff --git a/dom/media/webrtc/jsapi/RTCEncodedFrameBase.cpp b/dom/media/webrtc/jsapi/RTCEncodedFrameBase.cpp
index 8d85c62f87d..abf2b82101c 100644
--- a/dom/media/webrtc/jsapi/RTCEncodedFrameBase.cpp
+++ b/dom/media/webrtc/jsapi/RTCEncodedFrameBase.cpp
@@ -13,8 +13,21 @@
#include "nsIGlobalObject.h"
namespace mozilla::dom {
-NS_IMPL_CYCLE_COLLECTION_WITH_JS_MEMBERS(RTCEncodedFrameBase, (mGlobal),
- (mData))
+
+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(mData)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(RTCEncodedFrameBase)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(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_END
+
NS_IMPL_CYCLE_COLLECTING_ADDREF(RTCEncodedFrameBase)
NS_IMPL_CYCLE_COLLECTING_RELEASE(RTCEncodedFrameBase)
@@ -42,13 +55,29 @@ RTCEncodedFrameState::RTCEncodedFrameState(
uint64_t aCounter, unsigned long aTimestamp)
: mFrame(std::move(aFrame)), mCounter(aCounter), mTimestamp(aTimestamp) {}
-RTCEncodedFrameBase::~RTCEncodedFrameBase() = default;
+RTCEncodedFrameBase::~RTCEncodedFrameBase() { DetachData(); }
+
+void RTCEncodedFrameBase::DetachData() {
+ // We might have handled this in unlink already
+ if (mGlobal) {
+ AutoJSAPI jsapi;
+ if (NS_WARN_IF(!jsapi.Init(mGlobal))) {
+ return;
+ }
+
+ JS::Rooted<JSObject*> rootedData(jsapi.cx(), mData);
+ if (rootedData) {
+ JS::DetachArrayBuffer(jsapi.cx(), rootedData);
+ }
+ }
+}
unsigned long RTCEncodedFrameBase::Timestamp() const {
return mState.mTimestamp;
}
void RTCEncodedFrameBase::SetData(const ArrayBuffer& aData) {
+ DetachData();
mData.set(aData.Obj());
if (mState.mFrame) {
aData.ProcessData([&](const Span<uint8_t>& aData, JS::AutoCheckCannotGC&&) {
@@ -67,20 +96,7 @@ uint64_t RTCEncodedFrameBase::GetCounter() const { return mState.mCounter; }
std::unique_ptr<webrtc::TransformableFrameInterface>
RTCEncodedFrameBase::TakeFrame() {
- if (mState.mFrame) {
- AutoJSAPI jsapi;
- if (!jsapi.Init(mGlobal)) {
- MOZ_CRASH("Could not init JSAPI!");
- }
- // If the JS buffer was transferred (or otherwise detached), neuter native.
- JS::Rooted<JSObject*> rootedData(jsapi.cx(), mData);
- if (rootedData && JS::IsDetachedArrayBufferObject(rootedData)) {
- mState.mFrame.reset();
- return nullptr;
- }
- // Still attached: detach now since we're consuming the frame.
- JS::DetachArrayBuffer(jsapi.cx(), rootedData);
- }
+ DetachData();
return std::move(mState.mFrame);
}
diff --git a/dom/media/webrtc/jsapi/RTCEncodedFrameBase.h b/dom/media/webrtc/jsapi/RTCEncodedFrameBase.h
index 96653fee38a..35bf8bb0b06 100644
--- a/dom/media/webrtc/jsapi/RTCEncodedFrameBase.h
+++ b/dom/media/webrtc/jsapi/RTCEncodedFrameBase.h
@@ -68,6 +68,7 @@ class RTCEncodedFrameBase : public nsISupports, public nsWrapperCache {
protected:
virtual ~RTCEncodedFrameBase();
+ void DetachData();
// forbid copy/move to protect mState
RTCEncodedFrameBase(const RTCEncodedFrameBase&) = delete;
diff --git a/testing/web-platform/tests/webrtc-encoded-transform/RTCRtpScriptTransform-sender-worker-single-frame.https.html b/testing/web-platform/tests/webrtc-encoded-transform/RTCRtpScriptTransform-sender-worker-single-frame.https.html
index bcf2963661c..025073e4ba8 100644
--- a/testing/web-platform/tests/webrtc-encoded-transform/RTCRtpScriptTransform-sender-worker-single-frame.https.html
+++ b/testing/web-platform/tests/webrtc-encoded-transform/RTCRtpScriptTransform-sender-worker-single-frame.https.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html>
<head>
+<meta name="timeout" content="long">
<title>RTCRtpScriptTransform Insertable Streams - Worker</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/testing/web-platform/tests/webrtc-encoded-transform/RTCRtpScriptTransform-sender-worker-single-frame.https.html b/testing/web-platform/tests/webrtc-encoded-transform/RTCRtpScriptTransform-sender-worker-single-frame.https.html index bcf2963661c..025073e4ba8 100644 --- a/testing/web-platform/tests/webrtc-encoded-transform/RTCRtpScriptTransform-sender-worker-single-frame.https.html +++ b/testing/web-platform/tests/webrtc-encoded-transform/RTCRtpScriptTransform-sender-worker-single-frame.https.html @@ -1,6 +1,7 @@ <!DOCTYPE html> <html> <head> +<meta name="timeout" content="long"> <title>RTCRtpScriptTransform Insertable Streams - Worker</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
Loading diff…
References
On This Page