Firefox · DOM
CVE-2026-118019
Logic Error in DOM
Overview
Moderate
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
nsIHandleReportCallbackdom/file/BlobImpl.h |
modified | |
nsIInputStreamdom/file/BlobImpl.h |
modified | |
ifdom/file/BlobMemoryReporter.cpp |
modified | |
fordom/file/BlobMemoryReporter.cpp |
modified | |
BlobImpldom/file/BlobMemoryReporter.h |
modified | |
BlobMemoryReporterdom/file/BlobMemoryReporter.h |
modified | |
ifdom/file/StreamBlobImpl.cpp |
modified | |
StreamBlobImpldom/file/StreamBlobImpl.h |
modified | |
StringBlobImpldom/file/StringBlobImpl.h |
modified |
Files Changed
dom/file/BlobImpl.hdom/file/BlobMemoryReporter.cppdom/file/BlobMemoryReporter.hdom/file/StreamBlobImpl.cppdom/file/StreamBlobImpl.hdom/file/StringBlobImpl.cppdom/file/StringBlobImpl.hdom/file/moz.build
Patch
diff --git a/dom/file/BlobImpl.h b/dom/file/BlobImpl.h
index fea43f77b98..4b93e80e5c9 100644
--- a/dom/file/BlobImpl.h
+++ b/dom/file/BlobImpl.h
@@ -12,6 +12,7 @@
#define BLOBIMPL_IID \
{0xbccb3275, 0x6778, 0x4ac5, {0xaf, 0x03, 0x90, 0xed, 0x37, 0xad, 0xdf, 0x5d}}
+class nsIHandleReportCallback;
class nsIInputStream;
namespace mozilla {
@@ -103,6 +104,11 @@ class BlobImpl : public SupportsThreadSafeWeakPtr<BlobImpl>,
// file is a directory.
virtual bool IsDirectory() const { return false; }
+ virtual nsresult CollectReports(nsIHandleReportCallback* aHandleReport,
+ nsISupports* aData, bool aAnonymize) {
+ return NS_OK;
+ }
+
protected:
friend SupportsThreadSafeWeakPtr<BlobImpl>;
diff --git a/dom/file/BlobMemoryReporter.cpp b/dom/file/BlobMemoryReporter.cpp
new file mode 100644
index 00000000000..0fdd8b2f085
--- /dev/null
+++ b/dom/file/BlobMemoryReporter.cpp
@@ -0,0 +1,73 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "BlobMemoryReporter.h"
+
+#include "BlobImpl.h"
+#include "mozilla/StaticMutex.h"
+#include "mozilla/StaticPtr.h"
+#include "mozilla/ThreadSafeWeakPtr.h"
+#include "nsTHashSet.h"
+
+namespace mozilla::dom {
+
+static StaticMutex sMutex;
+static StaticAutoPtr<nsTHashSet<ThreadSafeWeakPtr<BlobImpl>>> sEntries
+ MOZ_GUARDED_BY(sMutex);
+
+NS_IMPL_ISUPPORTS(BlobMemoryReporter, nsIMemoryReporter)
+
+BlobMemoryReporter::~BlobMemoryReporter() {
+ StaticMutexAutoLock lock(sMutex);
+ sEntries = nullptr;
+}
+
+/* static */
+void BlobMemoryReporter::Register(BlobImpl* aImpl) {
+ StaticMutexAutoLock lock(sMutex);
+
+ if (!sEntries) {
+ sEntries = new nsTHashSet<ThreadSafeWeakPtr<BlobImpl>>();
+ RegisterStrongMemoryReporter(MakeAndAddRef<BlobMemoryReporter>());
+ }
+
+ sEntries->Insert(aImpl);
+}
+
+/* static */
+void BlobMemoryReporter::Unregister(BlobImpl* aImpl) {
+ StaticMutexAutoLock lock(sMutex);
+ if (sEntries) {
+ sEntries->Remove(aImpl);
+ }
+}
+
+NS_IMETHODIMP
+BlobMemoryReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
+ nsISupports* aData, bool aAnonymize) {
+ // Don't release the strong reference under the lock.
+ nsTArray<RefPtr<BlobImpl>> alive;
+
+ {
+ StaticMutexAutoLock lock(sMutex);
+ if (!sEntries) {
+ return NS_OK;
+ }
+
+ for (const auto& key : *sEntries) {
+ if (RefPtr<BlobImpl> ref(key); ref) {
+ alive.AppendElement(std::move(ref));
+ }
+ }
+ }
+
+ for (const auto& impl : alive) {
+ nsresult rv = impl->CollectReports(aHandleReport, aData, aAnonymize);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ return NS_OK;
+}
+
+} // namespace mozilla::dom
diff --git a/dom/file/BlobMemoryReporter.h b/dom/file/BlobMemoryReporter.h
new file mode 100644
index 00000000000..af2de0a1044
--- /dev/null
+++ b/dom/file/BlobMemoryReporter.h
@@ -0,0 +1,30 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_BlobMemoryReporter_h
+#define mozilla_dom_BlobMemoryReporter_h
+
+#include "nsIMemoryReporter.h"
+
+namespace mozilla::dom {
+
+class BlobImpl;
+
+// Shared memory reporter for all BlobImpl instances.
+// Call Register/Unregister from BlobImpl ctor/dtor.
+class BlobMemoryReporter final : public nsIMemoryReporter {
+ public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIMEMORYREPORTER
+
+ static void Register(BlobImpl* aImpl);
+ static void Unregister(BlobImpl* aImpl);
+
+ private:
+ ~BlobMemoryReporter();
+};
+
+} // namespace mozilla::dom
+
+#endif // mozilla_dom_BlobMemoryReporter_h
diff --git a/dom/file/StreamBlobImpl.cpp b/dom/file/StreamBlobImpl.cpp
index e8d934bcfe8..3aacfd25451 100644
--- a/dom/file/StreamBlobImpl.cpp
+++ b/dom/file/StreamBlobImpl.cpp
@@ -4,6 +4,7 @@
#include "StreamBlobImpl.h"
+#include "BlobMemoryReporter.h"
#include "EmptyBlobImpl.h"
#include "js/GCAPI.h"
#include "mozilla/InputStreamLengthWrapper.h"
@@ -19,7 +20,7 @@
namespace mozilla::dom {
-NS_IMPL_ISUPPORTS_INHERITED(StreamBlobImpl, BlobImpl, nsIMemoryReporter)
+MOZ_DEFINE_MALLOC_SIZE_OF(StreamBlobImplMallocSizeOf)
static already_AddRefed<nsICloneableInputStream> EnsureCloneableStream(
nsIInputStream* aInputStream, uint64_t aLength) {
@@ -120,7 +121,7 @@ StreamBlobImpl::~StreamBlobImpl() {
nsCOMPtr<nsIInputStream> stream = do_QueryInterface(mInputStream);
stream->Close();
}
- UnregisterWeakMemoryReporter(this);
+ BlobMemoryReporter::Unregister(this);
}
void StreamBlobImpl::CreateInputStream(nsIInputStream** aStream,
@@ -185,12 +186,11 @@ void StreamBlobImpl::MaybeRegisterMemoryReporter() {
return;
}
- RegisterWeakMemoryReporter(this);
+ BlobMemoryReporter::Register(this);
}
-NS_IMETHODIMP
-StreamBlobImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
- nsISupports* aData, bool aAnonymize) {
+nsresult StreamBlobImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
+ nsISupports* aData, bool aAnonymize) {
nsCOMPtr<nsIStringInputStream> stringInputStream =
do_QueryInterface(mInputStream);
if (!stringInputStream) {
@@ -198,10 +198,11 @@ StreamBlobImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
}
MOZ_COLLECT_REPORT(
- "explicit/dom/memory-file-data/stream", KIND_HEAP, UNITS_BYTES,
- stringInputStream->SizeOfIncludingThisIfUnshared(MallocSizeOf),
+ "explicit/dom/memory-file-data/stream", nsIMemoryReporter::KIND_HEAP,
+ nsIMemoryReporter::UNITS_BYTES,
+ stringInputStream->SizeOfIncludingThisIfUnshared(
+ StreamBlobImplMallocSizeOf),
"Memory used to back a File/Blob based on an input stream.");
-
return NS_OK;
}
@@ -217,7 +218,8 @@ size_t StreamBlobImpl::GetAllocationSize() const {
return 0;
}
- return stringInputStream->SizeOfIncludingThisEvenIfShared(MallocSizeOf);
+ return stringInputStream->SizeOfIncludingThisEvenIfShared(
+ StreamBlobImplMallocSizeOf);
}
void StreamBlobImpl::GetBlobImplType(nsAString& aBlobImplType) const {
diff --git a/dom/file/StreamBlobImpl.h b/dom/file/StreamBlobImpl.h
index 03becc95d52..29781394e0f 100644
--- a/dom/file/StreamBlobImpl.h
+++ b/dom/file/StreamBlobImpl.h
@@ -8,16 +8,12 @@
#include "BaseBlobImpl.h"
#include "nsCOMPtr.h"
#include "nsICloneableInputStream.h"
-#include "nsIMemoryReporter.h"
namespace mozilla::dom {
-class StreamBlobImpl final : public BaseBlobImpl, public nsIMemoryReporter {
- MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
-
+class StreamBlobImpl final : public BaseBlobImpl {
public:
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_NSIMEMORYREPORTER
+ NS_INLINE_DECL_REFCOUNTING_INHERITED(StreamBlobImpl, BaseBlobImpl)
// Blob constructor.
static already_AddRefed<StreamBlobImpl> Create(
@@ -77,6 +73,9 @@ class StreamBlobImpl final : public BaseBlobImpl, public nsIMemoryReporter {
~StreamBlobImpl() override;
+ nsresult CollectReports(nsIHandleReportCallback* aHandleReport,
+ nsISupports* aData, bool aAnonymize) override;
+
void MaybeRegisterMemoryReporter();
nsCOMPtr<nsICloneableInputStream> mInputStream;
diff --git a/dom/file/StringBlobImpl.cpp b/dom/file/StringBlobImpl.cpp
index f5817545e5d..faabdd43d4d 100644
--- a/dom/file/StringBlobImpl.cpp
+++ b/dom/file/StringBlobImpl.cpp
@@ -4,17 +4,18 @@
#include "StringBlobImpl.h"
+#include "BlobMemoryReporter.h"
#include "nsStringStream.h"
namespace mozilla::dom {
-NS_IMPL_ISUPPORTS_INHERITED(StringBlobImpl, BlobImpl, nsIMemoryReporter)
+MOZ_DEFINE_MALLOC_SIZE_OF(StringBlobImplMallocSizeOf)
/* static */
already_AddRefed<StringBlobImpl> StringBlobImpl::Create(
const nsACString& aData, const nsAString& aContentType) {
RefPtr<StringBlobImpl> blobImpl = new StringBlobImpl(aData, aContentType);
- RegisterWeakMemoryReporter(blobImpl);
+ BlobMemoryReporter::Register(blobImpl);
return blobImpl.forget();
}
@@ -22,13 +23,14 @@ StringBlobImpl::StringBlobImpl(const nsACString& aData,
const nsAString& aContentType)
: BaseBlobImpl(aContentType, aData.Length()), mData(aData) {}
-StringBlobImpl::~StringBlobImpl() { UnregisterWeakMemoryReporter(this); }
+StringBlobImpl::~StringBlobImpl() { BlobMemoryReporter::Unregister(this); }
already_AddRefed<BlobImpl> StringBlobImpl::CreateSlice(
uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
ErrorResult& aRv) const {
RefPtr<BlobImpl> impl =
new StringBlobImpl(Substring(mData, aStart, aLength), aContentType);
+ BlobMemoryReporter::Register(impl);
return impl.forget();
}
@@ -37,13 +39,13 @@ void StringBlobImpl::CreateInputStream(nsIInputStream** aStream,
aRv = NS_NewCStringInputStream(aStream, mData);
}
-NS_IMETHODIMP
-StringBlobImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
- nsISupports* aData, bool aAnonymize) {
- MOZ_COLLECT_REPORT("explicit/dom/memory-file-data/string", KIND_HEAP,
- UNITS_BYTES,
- mData.SizeOfExcludingThisIfUnshared(MallocSizeOf),
- "Memory used to back a File/Blob based on a string.");
+nsresult StringBlobImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
+ nsISupports* aData, bool aAnonymize) {
+ MOZ_COLLECT_REPORT(
+ "explicit/dom/memory-file-data/string", nsIMemoryReporter::KIND_HEAP,
+ nsIMemoryReporter::UNITS_BYTES,
+ mData.SizeOfExcludingThisIfUnshared(StringBlobImplMallocSizeOf),
+ "Memory used to back a File/Blob based on a string.");
return NS_OK;
}
diff --git a/dom/file/StringBlobImpl.h b/dom/file/StringBlobImpl.h
index 796311c33da..245ee85728a 100644
--- a/dom/file/StringBlobImpl.h
+++ b/dom/file/StringBlobImpl.h
@@ -6,16 +6,12 @@
#define mozilla_dom_StringBlobImpl_h
#include "BaseBlobImpl.h"
-#include "nsIMemoryReporter.h"
namespace mozilla::dom {
-class StringBlobImpl final : public BaseBlobImpl, public nsIMemoryReporter {
- MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
-
+class StringBlobImpl final : public BaseBlobImpl {
public:
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_NSIMEMORYREPORTER
+ NS_INLINE_DECL_REFCOUNTING_INHERITED(StringBlobImpl, BaseBlobImpl)
static already_AddRefed<StringBlobImpl> Create(const nsACString& aData,
const nsAString& aContentType);
@@ -43,6 +39,9 @@ class StringBlobImpl final : public BaseBlobImpl, public nsIMemoryReporter {
~StringBlobImpl() override;
+ nsresult CollectReports(nsIHandleReportCallback* aHandleReport,
+ nsISupports* aData, bool aAnonymize) override;
+
nsCString mData;
};
diff --git a/dom/file/moz.build b/dom/file/moz.build
index b8467975cf6..efc522f038f 100644
--- a/dom/file/moz.build
+++ b/dom/file/moz.build
@@ -11,6 +11,7 @@ EXPORTS.mozilla.dom += [
"BaseBlobImpl.h",
"Blob.h",
"BlobImpl.h",
+ "BlobMemoryReporter.h",
"BlobSet.h",
"EmptyBlobImpl.h",
"File.h",
@@ -30,6 +31,7 @@ UNIFIED_SOURCES += [
"BaseBlobImpl.cpp",
"Blob.cpp",
"BlobImpl.cpp",
+ "BlobMemoryReporter.cpp",
"BlobSet.cpp",
"EmptyBlobImpl.cpp",
"File.cpp",
Loading diff…
References
On This Page