High firefox Memory Corruption 🔧 Commit mapped

Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impacthigh
DescriptionMemory safety bugs present in Firefox ESR 115.26, Firefox ESR 128.13, Thunderbird ESR 128.13, Firefox ESR 140.1, Thunderbird ESR 140.1, Firefox 141 and Thunderbird 141. Some of these bugs showed evidence of memory corruption and we presume that with enough effort some of these could have been exploited to run arbitrary code.
ComponentSpiderMonkey
Bug ClassMemory Corruption
Tracker1970154
Fix commitd061aaeaff07 (firefox) +23/-12
CISA KEVNot listed
CreditedThe Mozilla Fuzzing Team
Disclosed2025-08-19

Changed Functions

FunctionChangeNotes
if
dom/streams/ByteStreamHelpers.cpp
modified

Files Changed

  • dom/streams/ByteStreamHelpers.cpp
  • js/src/vm/ArrayBufferViewObject.cpp
diff --git a/dom/streams/ByteStreamHelpers.cpp b/dom/streams/ByteStreamHelpers.cpp
index 5022bb2c729..1d85b09c6eb 100644
--- a/dom/streams/ByteStreamHelpers.cpp
+++ b/dom/streams/ByteStreamHelpers.cpp
@@ -16,22 +16,34 @@ namespace mozilla::dom {
 // https://streams.spec.whatwg.org/#transfer-array-buffer
 // As some parts of the specifcation want to use the abrupt completion value,
 // this function may leave a pending exception if it returns nullptr.
+//
+// This can be called with a CCW to an ArrayBuffer Object as we handle the
+// case explicitly.
 JSObject* TransferArrayBuffer(JSContext* aCx, JS::Handle<JSObject*> aObject) {
-  MOZ_ASSERT(JS::IsArrayBufferObject(aObject));
+  JS::Rooted<JSObject*> unwrappedObj(aCx, JS::UnwrapArrayBuffer(aObject));
+  if (!unwrappedObj) {
+    js::ReportAccessDenied(aCx);
+    return nullptr;
+  }
 
-  // Step 1.
-  MOZ_ASSERT(!JS::IsDetachedArrayBufferObject(aObject));
+  size_t bufferLength = 0;
+  UniquePtr<void, JS::FreePolicy> bufferData;
+  {
+    JSAutoRealm ar(aCx, unwrappedObj);
 
-  // Step 3 (Reordered)
-  size_t bufferLength = JS::GetArrayBufferByteLength(aObject);
+    // Step 1.
+    MOZ_ASSERT(!JS::IsDetachedArrayBufferObject(unwrappedObj));
 
-  // Step 2 (Reordered)
-  UniquePtr<void, JS::FreePolicy> bufferData{
-      JS::StealArrayBufferContents(aCx, aObject)};
+    // Step 3 (Reordered)
+    bufferLength = JS::GetArrayBufferByteLength(unwrappedObj);
 
-  // Step 4.
-  if (!JS::DetachArrayBuffer(aCx, aObject)) {
-    return nullptr;
+    // Step 2 (Reordered)
+    bufferData.reset(JS::StealArrayBufferContents(aCx, unwrappedObj));
+
+    // Step 4.
+    if (!JS::DetachArrayBuffer(aCx, unwrappedObj)) {
+      return nullptr;
+    }
   }
 
   // Step 5.
diff --git a/js/src/vm/ArrayBufferViewObject.cpp b/js/src/vm/ArrayBufferViewObject.cpp
index e258b57baac..322d72bec13 100644
--- a/js/src/vm/ArrayBufferViewObject.cpp
+++ b/js/src/vm/ArrayBufferViewObject.cpp
@@ -465,7 +465,6 @@ JS_PUBLIC_API JSObject* JS_GetArrayBufferViewBuffer(JSContext* cx,
                                                     bool* isSharedMemory) {
   AssertHeapIsIdle();
   CHECK_THREAD(cx);
-  cx->check(obj);
 
   Rooted<ArrayBufferViewObject*> unwrappedView(
       cx, obj->maybeUnwrapAs<ArrayBufferViewObject>());
Loading diff…