Moderate firefox Logic Error 🔧 Commit mapped

Overview

Moderate
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactmoderate
DescriptionUse-after-free in the Graphics component
ComponentGraphics
Bug ClassLogic Error
Tracker2068438
Fix commiteb05f7288c75 (firefox) +15/-17
CISA KEVNot listed
CreditedMozilla
Disclosed2026-09-15

Changed Functions

FunctionChangeNotes
if
gfx/layers/client/TextureClient.cpp
modified

Files Changed

  • gfx/layers/ImageContainer.cpp
  • gfx/layers/client/TextureClient.cpp
  • gfx/layers/client/TextureClient.h
diff --git a/gfx/layers/ImageContainer.cpp b/gfx/layers/ImageContainer.cpp
index 9ab29f4a53a..143aecb6afd 100644
--- a/gfx/layers/ImageContainer.cpp
+++ b/gfx/layers/ImageContainer.cpp
@@ -319,10 +319,8 @@ Maybe<SurfaceDescriptor> Image::GetDescFromTexClient(
     return {};
   }
 
-  const auto& tcd = tc->GetInternalData();
-
   SurfaceDescriptor ret;
-  if (!tcd->Serialize(ret)) {
+  if (!tc->ToSurfaceDescriptor(ret)) {
     return {};
   }
   return Some(ret);
diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp
index d7b8eab5065..dbae5dfdebb 100644
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -524,8 +524,12 @@ void TextureClient::Destroy() {
     actor = nullptr;
   }
 
-  TextureData* data = mData;
-  mData = nullptr;
+  TextureData* data;
+  {
+    MutexAutoLock lock(mMutex);
+    data = mData;
+    mData = nullptr;
+  }
 
   if (data || actor || readLock) {
     TextureDeallocParams params;
@@ -1010,8 +1014,7 @@ bool TextureClient::BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap) {
 }
 
 bool TextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) {
-  MOZ_ASSERT(IsValid());
-
+  MutexAutoLock lock(mMutex);
   return mData ? mData->Serialize(aOutDescriptor) : false;
 }
 
diff --git a/gfx/layers/client/TextureClient.h b/gfx/layers/client/TextureClient.h
index 5c784fdea58..d3f59f443b4 100644
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -619,6 +619,13 @@ class TextureClient : public AtomicRefCountedWithFinalize<TextureClient> {
   TextureData* GetInternalData() { return mData; }
   const TextureData* GetInternalData() const { return mData; }
 
+  /**
+   * Serializes the underlying TextureData into aDescriptor. Returns false if
+   * the TextureData has already been destroyed. Safe to call from any thread
+   * concurrently with Destroy().
+   */
+  bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor);
+
   uint64_t GetSerial() const { return mSerial; }
   void GetSurfaceDescriptorRemoteDecoder(
       SurfaceDescriptorRemoteDecoder* aOutDesc);
@@ -717,16 +724,6 @@ class TextureClient : public AtomicRefCountedWithFinalize<TextureClient> {
   friend class AtomicRefCountedWithFinalize<TextureClient>;
 
  protected:
-  /**
-   * Should only be called *once* per texture, in TextureClient::InitIPDLActor.
-   * Some texture implementations rely on the fact that the descriptor will be
-   * deserialized.
-   * Calling ToSurfaceDescriptor again after it has already returned true,
-   * or never constructing a TextureHost with aDescriptor may result in a memory
-   * leak (see TextureClientD3D9 for example).
-   */
-  bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor);
-
   void LockActor() const;
   void UnlockActor() const;
 
Loading diff…