Moderate firefox Logic Error 🔧 Commit mapped

Overview

Moderate
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactmoderate
DescriptionOther issue in the DOM: File component
ComponentDOM
Bug ClassLogic Error
Tracker2059211
Fix commitad10ba22dfff (firefox) +23/-15
CISA KEVNot listed
CreditedMozilla
Disclosed2026-10-13

Changed Functions

FunctionChangeNotes
if
dom/file/FileBlobImpl.cpp
modified

Files Changed

  • dom/file/BaseBlobImpl.h
  • dom/file/BlobImpl.cpp
  • dom/file/BlobImpl.h
  • dom/file/FileBlobImpl.cpp
  • dom/file/FileBlobImpl.h
  • dom/file/MultipartBlobImpl.h
  • dom/indexedDB/ActorsParent.cpp
diff --git a/dom/file/BaseBlobImpl.h b/dom/file/BaseBlobImpl.h
index b43e2a31969..28f7dc201d3 100644
--- a/dom/file/BaseBlobImpl.h
+++ b/dom/file/BaseBlobImpl.h
@@ -66,7 +66,7 @@ class BaseBlobImpl : public BlobImpl {
 
   void GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) override;
 
-  uint64_t GetSize(ErrorResult& aRv) override { return mLength; }
+  uint64_t GetSize(ErrorResult& aRv) const override { return mLength; }
 
   void GetType(nsAString& aType) override;
 
diff --git a/dom/file/BlobImpl.cpp b/dom/file/BlobImpl.cpp
index b561758fab8..38e328ebf23 100644
--- a/dom/file/BlobImpl.cpp
+++ b/dom/file/BlobImpl.cpp
@@ -67,13 +67,16 @@ nsresult BlobImpl::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
 
   ErrorResult rv;
 
-  nsCOMPtr<nsIInputStream> stream;
-  CreateInputStream(getter_AddRefs(stream), rv);
+  // Query the size before creating the stream: blobs with a lazy size (e.g.
+  // FileBlobImpl) snapshot it on first use, and the stream handed out below
+  // must be capped at the very same size we declare as the Content-Length.
+  *aContentLength = GetSize(rv);
   if (NS_WARN_IF(rv.Failed())) {
     return rv.StealNSResult();
   }
 
-  *aContentLength = GetSize(rv);
+  nsCOMPtr<nsIInputStream> stream;
+  CreateInputStream(getter_AddRefs(stream), rv);
   if (NS_WARN_IF(rv.Failed())) {
     return rv.StealNSResult();
   }
diff --git a/dom/file/BlobImpl.h b/dom/file/BlobImpl.h
index fea43f77b98..b973b3b69da 100644
--- a/dom/file/BlobImpl.h
+++ b/dom/file/BlobImpl.h
@@ -53,7 +53,7 @@ class BlobImpl : public SupportsThreadSafeWeakPtr<BlobImpl>,
   virtual void GetMozFullPathInternal(nsAString& aFileName,
                                       ErrorResult& aRv) = 0;
 
-  virtual uint64_t GetSize(ErrorResult& aRv) = 0;
+  virtual uint64_t GetSize(ErrorResult& aRv) const = 0;
 
   virtual void GetType(nsAString& aType) = 0;
 
diff --git a/dom/file/FileBlobImpl.cpp b/dom/file/FileBlobImpl.cpp
index 13bd025b9bf..2adad00e896 100644
--- a/dom/file/FileBlobImpl.cpp
+++ b/dom/file/FileBlobImpl.cpp
@@ -134,7 +134,7 @@ void FileBlobImpl::GetMozFullPathInternal(nsAString& aFilename,
   mMozFullPath = aFilename;
 }
 
-uint64_t FileBlobImpl::GetSize(ErrorResult& aRv) {
+uint64_t FileBlobImpl::GetSize(ErrorResult& aRv) const {
   MutexAutoLock lock(mMutex);
 
   if (mLength.isNothing()) {
@@ -272,6 +272,11 @@ const uint32_t sFileStreamFlags =
 
 void FileBlobImpl::CreateInputStream(nsIInputStream** aStream,
                                      ErrorResult& aRv) const {
+  const uint64_t length = GetSize(aRv);
+  if (NS_WARN_IF(aRv.Failed())) {
+    return;
+  }
+
   nsCOMPtr<nsIInputStream> stream;
   aRv = NS_NewLocalFileInputStream(getter_AddRefs(stream), mFile, -1, -1,
                                    sFileStreamFlags);
@@ -280,14 +285,14 @@ void FileBlobImpl::CreateInputStream(nsIInputStream** aStream,
   }
 
   if (mWholeFile) {
-    stream.forget(aStream);
+    RefPtr<SlicedInputStream> slicedInputStream =
+        new SlicedInputStream(stream.forget(), 0, length);
+    slicedInputStream.forget(aStream);
     return;
   }
 
-  MOZ_ASSERT(mLength.isSome());
-
   RefPtr<SlicedInputStream> slicedInputStream =
-      new SlicedInputStream(stream.forget(), mStart, mLength.value());
+      new SlicedInputStream(stream.forget(), mStart, length);
   slicedInputStream.forget(aStream);
 }
 
diff --git a/dom/file/FileBlobImpl.h b/dom/file/FileBlobImpl.h
index 7a2e606d275..c0b9d86c027 100644
--- a/dom/file/FileBlobImpl.h
+++ b/dom/file/FileBlobImpl.h
@@ -61,7 +61,7 @@ class FileBlobImpl : public BlobImpl {
 
   void GetMozFullPathInternal(nsAString& aFilename, ErrorResult& aRv) override;
 
-  uint64_t GetSize(ErrorResult& aRv) override;
+  uint64_t GetSize(ErrorResult& aRv) const override;
 
   void GetType(nsAString& aType) override;
 
@@ -127,7 +127,7 @@ class FileBlobImpl : public BlobImpl {
 
   // FileBlobImpl has getter methods with lazy initialization. Because any
   // BlobImpl must work thread-safe, we use a mutex.
-  Mutex mMutex MOZ_UNANNOTATED;
+  mutable Mutex mMutex MOZ_UNANNOTATED;
 
   nsCOMPtr<nsIFile> mFile;
 
@@ -141,7 +141,7 @@ class FileBlobImpl : public BlobImpl {
 
   int64_t mFileId;
 
-  Maybe<uint64_t> mLength;
+  mutable Maybe<uint64_t> mLength;
 
   Maybe<int64_t> mLastModified;
 
diff --git a/dom/file/MultipartBlobImpl.h b/dom/file/MultipartBlobImpl.h
index 131727dd12f..47567de9d52 100644
--- a/dom/file/MultipartBlobImpl.h
+++ b/dom/file/MultipartBlobImpl.h
@@ -56,7 +56,7 @@ class MultipartBlobImpl final : public BaseBlobImpl {
                                          const nsAString& aContentType,
                                          ErrorResult& aRv) const override;
 
-  uint64_t GetSize(ErrorResult& aRv) override { return mLength; }
+  uint64_t GetSize(ErrorResult& aRv) const override { return mLength; }
 
   void CreateInputStream(nsIInputStream** aStream,
                          ErrorResult& aRv) const override;
diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp
index 3fd600c60a1..fa7f9b8e0b2 100644
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -5490,7 +5490,7 @@ class EncryptedFileBlobImpl final : public FileBlobImpl {
   // only accesses it. And the reason why 0 is returned, even when the size is
   // not set in a child process, is is because the spec doesn't allow Blob.size
   // to throw.
-  uint64_t GetSize(ErrorResult& aRv) override {
+  uint64_t GetSize(ErrorResult& aRv) const override {
     MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess() || mLength.isSome());
     return mLength.valueOr(0);
   }
Loading diff…