High firefox Logic Error 🔧 Commit mapped

Overview

High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Impacthigh
DescriptionUninitialized memory in the Graphics: Canvas2D component
ComponentDOM
Bug ClassLogic Error
Tracker2078649
Fix commitb5a7d53b5968 (firefox) +69/-46
CISA KEVNot listed
CreditedMinseong Kim
Disclosed2026-10-27

Changed Functions

FunctionChangeNotes
mContentId
dom/canvas/DrawTargetWebgl.cpp
modified
switch
dom/canvas/DrawTargetWebgl.cpp
modified
for
dom/canvas/DrawTargetWebgl.cpp
modified
if
dom/canvas/DrawTargetWebgl.cpp
modified
if
gfx/2d/RecordedEventImpl.h
modified
if
gfx/layers/ipc/CanvasTranslator.cpp
modified
GetZeroCopySurfaceFromDMABuf
gfx/layers/ipc/CanvasTranslator.cpp
modified

Files Changed

  • dom/canvas/DrawTargetWebgl.cpp
  • dom/canvas/DrawTargetWebgl.h
  • dom/canvas/DrawTargetWebglInternal.h
  • gfx/2d/RecordedEvent.h
  • gfx/2d/RecordedEventImpl.h
  • gfx/layers/ipc/CanvasTranslator.cpp
  • gfx/layers/ipc/CanvasTranslator.h
diff --git a/dom/canvas/DrawTargetWebgl.cpp b/dom/canvas/DrawTargetWebgl.cpp
index ecd4d069629..4254a2467d4 100644
--- a/dom/canvas/DrawTargetWebgl.cpp
+++ b/dom/canvas/DrawTargetWebgl.cpp
@@ -102,7 +102,8 @@ static const Etagere::AllocatorOptions kR8AllocatorOptions = {16, 1, 1, 0};
 #endif
 
 SharedTexture::SharedTexture(const IntSize& aSize, SurfaceFormat aFormat,
-                             const RefPtr<WebGLTexture>& aTexture)
+                             const RefPtr<WebGLTexture>& aTexture,
+                             const dom::ContentParentId& aContentId)
     : BackingTexture(aSize, aFormat, aTexture),
       mAtlasAllocator(
 #ifdef XP_WIN
@@ -111,7 +112,8 @@ SharedTexture::SharedTexture(const IntSize& aSize, SurfaceFormat aFormat,
                     aSize.width, aSize.height, &kR8AllocatorOptions)
               :
 #endif
-              Etagere::etagere_atlas_allocator_new(aSize.width, aSize.height)) {
+              Etagere::etagere_atlas_allocator_new(aSize.width, aSize.height)),
+      mContentId(aContentId) {
 }
 
 SharedTexture::~SharedTexture() {
@@ -432,7 +434,8 @@ void SharedContextWebgl::ClearCachesIfNecessary() {
 // Try to initialize a new WebGL context. Verifies that the requested size does
 // not exceed the available texture limits and that shader creation succeeded.
 bool DrawTargetWebgl::Init(const IntSize& size, const SurfaceFormat format,
-                           const RefPtr<SharedContextWebgl>& aSharedContext) {
+                           const RefPtr<SharedContextWebgl>& aSharedContext,
+                           const dom::ContentParentId& aContentId) {
   switch (format) {
     case SurfaceFormat::B8G8R8A8:
     case SurfaceFormat::B8G8R8X8:
@@ -454,6 +457,8 @@ bool DrawTargetWebgl::Init(const IntSize& size, const SurfaceFormat format,
   mSharedContext->mDrawTargetCount++;
   gReportedTargetCount++;
 
+  mContentId = aContentId;
+
   if (size_t(std::max(size.width, size.height)) >
       mSharedContext->mMaxTextureSize) {
     return false;
@@ -1060,14 +1065,15 @@ bool DrawTargetWebgl::CanCreate(const IntSize& aSize, SurfaceFormat aFormat) {
 
 already_AddRefed<DrawTargetWebgl> DrawTargetWebgl::Create(
     const IntSize& aSize, SurfaceFormat aFormat,
-    const RefPtr<SharedContextWebgl>& aSharedContext) {
+    const RefPtr<SharedContextWebgl>& aSharedContext,
+    const dom::ContentParentId& aContentId) {
   // Validate the size and format.
   if (!CanCreate(aSize, aFormat)) {
     return nullptr;
   }
 
   RefPtr<DrawTargetWebgl> dt = new DrawTargetWebgl;
-  if (!dt->Init(aSize, aFormat, aSharedContext) || !dt->IsValid()) {
+  if (!dt->Init(aSize, aFormat, aSharedContext, aContentId) || !dt->IsValid()) {
     return nullptr;
   }
 
@@ -2855,8 +2861,8 @@ void SharedContextWebgl::BindScratchFramebuffer(TextureHandle* aHandle,
 // Allocate a new texture handle backed by either a standalone texture or as a
 // sub-texture of a larger shared texture.
 already_AddRefed<TextureHandle> SharedContextWebgl::AllocateTextureHandle(
-    SurfaceFormat aFormat, const IntSize& aSize, bool aAllowShared,
-    bool aRenderable, const WebGLTexture* aAvoid) {
+    DrawTargetWebgl* aDT, SurfaceFormat aFormat, const IntSize& aSize,
+    bool aAllowShared, bool aRenderable, const WebGLTexture* aAvoid) {
   // Don't allow allocating textures bigger than the reported limit.
   if (size_t(std::max(aSize.width, aSize.height)) > mMaxTextureSize) {
     return nullptr;
@@ -2870,13 +2876,17 @@ already_AddRefed<TextureHandle> SharedContextWebgl::AllocateTextureHandle(
   // The requested page size for shared textures.
   int32_t pageSize = int32_t(std::min(
       StaticPrefs::gfx_canvas_accelerated_shared_page_size(), mMaxTextureSize));
-  if (aAllowShared && std::max(aSize.width, aSize.height) <= pageSize / 2) {
+  if (aAllowShared && aDT &&
+      std::max(aSize.width, aSize.height) <= pageSize / 2) {
     // Ensure that the surface is no bigger than a quadrant of a shared texture
     // page. If so, try to allocate it to a shared texture. Look for any
-    // existing shared texture page with a matching format and allocate
-    // from that if possible.
+    // existing shared texture page with a matching format and allocate from
+    // that if possible. Restrict allocation to pages that only match the
+    // target's content id.
+    const dom::ContentParentId& contentId = aDT->GetContentId();
     for (auto& shared : mSharedTextures) {
-      if (shared->GetFormat() == aFormat &&
+      if (shared->GetContentId() == contentId &&
+          shared->GetFormat() == aFormat &&
           shared->IsRenderable() == aRenderable &&
           shared->GetWebGLTexture() != aAvoid) {
         bool wasEmpty = !shared->HasAllocatedHandles();
@@ -2895,8 +2905,8 @@ already_AddRefed<TextureHandle> SharedContextWebgl::AllocateTextureHandle(
     // format, then allocate a new page to put the request in.
     if (!handle) {
       if (RefPtr<WebGLTexture> tex = mWebgl->CreateTexture()) {
-        RefPtr<SharedTexture> shared =
-            new SharedTexture(IntSize(pageSize, pageSize), aFormat, tex);
+        RefPtr<SharedTexture> shared = new SharedTexture(
+            IntSize(pageSize, pageSize), aFormat, tex, contentId);
         if (aRenderable) {
           shared->MarkRenderable();
         }
@@ -3346,7 +3356,7 @@ bool SharedContextWebgl::DrawRectAccel(
         // surface size may change via a forced update, then don't allocate
         // from a shared texture page.
         handle = AllocateTextureHandle(
-            format, texSize,
+            mCurrentTarget, format, texSize,
             !aForceUpdate && surfacePattern.mExtendMode == ExtendMode::CLAMP);
         if (!handle) {
           MOZ_ASSERT(false);
@@ -3579,7 +3589,7 @@ already_AddRefed<WebGLTexture> SharedContextWebgl::GetFilterInputTexture(
     // There is no existing handle. Try to allocate a new one. If the
     // surface size may change via a forced update, then don't allocate
     // from a shared texture page.
-    handle = AllocateTextureHandle(format, texSize);
+    handle = AllocateTextureHandle(mCurrentTarget, format, texSize);
     if (!handle) {
       MOZ_ASSERT(false);
       return nullptr;
@@ -3645,8 +3655,8 @@ bool SharedContextWebgl::FilterRect(const Rect& aDestRect,
     // If sourcing from a texture handle as input, be careful not to render to
     // a handle with the same exact backing texture, which is not allowed in
     // WebGL.
-    RefPtr<TextureHandle> targetHandle =
-        AllocateTextureHandle(format, targetSize, true, true, tex);
+    RefPtr<TextureHandle> targetHandle = AllocateTextureHandle(
+        mCurrentTarget, format, targetSize, true, true, tex);
     if (!targetHandle) {
       MOZ_ASSERT(false);
       return false;
@@ -3837,7 +3847,8 @@ bool SharedContextWebgl::BlurRectPass(
     // a handle with the same exact backing texture, which is not allowed in
     // WebGL.
     RefPtr<TextureHandle> targetHandle = AllocateTextureHandle(
-        aFilter ? format : SurfaceFormat::A8, targetSize, true, true, tex);
+        mCurrentTarget, aFilter ? format : SurfaceFormat::A8, targetSize, true,
+        true, tex);
     if (!targetHandle) {
       MOZ_ASSERT(false);
       return false;
@@ -4022,7 +4033,7 @@ already_AddRefed<SourceSurface> SharedContextWebgl::DownscaleBlurInput(
       IntSize halfSize = (sourceRect.Size() + IntSize(1, 1)) / 2;
       // Allocate a half-size texture for the downscale target.
       RefPtr<TextureHandle> halfHandle = AllocateTextureHandle(
-          aSurface->GetFormat(), halfSize, true, true, fullTex);
+          mCurrentTarget, aSurface->GetFormat(), halfSize, true, true, fullTex);
       if (!halfHandle) {
         break;
       }
@@ -4232,7 +4243,7 @@ already_AddRefed<TextureHandle> SharedContextWebgl::ResolveFilterInputAccel(
                     RoundToFactor(aSourceRect.height, roundFactor))
           : aSourceRect.Size();
   RefPtr<TextureHandle> handle =
-      AllocateTextureHandle(aFormat, roundSize, true, true);
+      AllocateTextureHandle(aDT, aFormat, roundSize, true, true);
   if (!handle) {
     return nullptr;
   }
@@ -5014,8 +5025,8 @@ static inline AAStrokeMode SupportsAAStroke(const Pattern& aPattern,
 already_AddRefed<TextureHandle> SharedContextWebgl::DrawStrokeMask(
     const PathVertexRange& aVertexRange, const IntSize& aSize) {
   // Allocate a new texture handle to store the rendered mask.
-  RefPtr<TextureHandle> handle =
-      AllocateTextureHandle(SurfaceFormat::A8, aSize, true, true);
+  RefPtr<TextureHandle> handle = AllocateTextureHandle(
+      mCurrentTarget, SurfaceFormat::A8, aSize, true, true);
   if (!handle) {
     return nullptr;
   }
@@ -6725,14 +6736,14 @@ std::shared_ptr<gl::SharedSurface> SharedContextWebgl::ExportSharedSurface(
 }
 
 already_AddRefed<SourceSurface> SharedContextWebgl::ImportSurfaceDescriptor(
-    const layers::SurfaceDescriptor& aDesc, const IntSize& aSize,
-    SurfaceFormat aFormat) {
+    DrawTargetWebgl* aDT, const layers::SurfaceDescriptor& aDesc,
+    const IntSize& aSize, SurfaceFormat aFormat) {
   if (IsContextLost()) {
     return nullptr;
   }
 
   RefPtr<TextureHandle> handle =
-      AllocateTextureHandle(aFormat, aSize, true, true);
+      AllocateTextureHandle(aDT, aFormat, aSize, true, true);
   if (!handle) {
     return nullptr;
   }
@@ -6775,7 +6786,7 @@ already_AddRefed<SourceSurface> SharedContextWebgl::ImportSurfaceDescriptor(
 already_AddRefed<SourceSurface> DrawTargetWebgl::ImportSurfaceDescriptor(
     const layers::SurfaceDescriptor& aDesc, const IntSize& aSize,
     SurfaceFormat aFormat) {
-  return mSharedContext->ImportSurfaceDescriptor(aDesc, aSize, aFormat);
+  return mSharedContext->ImportSurfaceDescriptor(this, aDesc, aSize, aFormat);
 }
 
 already_AddRefed<DrawTarget> DrawTargetWebgl::CreateSimilarDrawTarget(
diff --git a/dom/canvas/DrawTargetWebgl.h b/dom/canvas/DrawTargetWebgl.h
index e63da448eb3..cc980c44ac0 100644
--- a/dom/canvas/DrawTargetWebgl.h
+++ b/dom/canvas/DrawTargetWebgl.h
@@ -13,6 +13,7 @@
 #include "mozilla/Array.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/WeakPtr.h"
+#include "mozilla/dom/ipc/IdType.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/PathSkia.h"
 #include "mozilla/ipc/SharedMemoryHandle.h"
@@ -104,8 +105,8 @@ class SharedContextWebgl : public mozilla::RefCounted<SharedContextWebgl>,
       layers::TextureType aTextureType, SourceSurface* aSurface);
 
   already_AddRefed<SourceSurface> ImportSurfaceDescriptor(
-      const layers::SurfaceDescriptor& aDesc, const gfx::IntSize& aSize,
-      SurfaceFormat aFormat);
+      DrawTargetWebgl* aDT, const layers::SurfaceDescriptor& aDesc,
+      const gfx::IntSize& aSize, SurfaceFormat aFormat);
 
  private:
   SharedContextWebgl();
@@ -390,8 +391,9 @@ class SharedContextWebgl : public mozilla::RefCounted<SharedContextWebgl>,
   void BindScratchFramebuffer(TextureHandle* aHandle, bool aInit,
                               const IntSize& aViewportSize = IntSize());
   already_AddRefed<TextureHandle> AllocateTextureHandle(
-      SurfaceFormat aFormat, const IntSize& aSize, bool aAllowShared = true,
-      bool aRenderable = false, const WebGLTexture* aAvoid = nullptr);
+      DrawTargetWebgl* aDT, SurfaceFormat aFormat, const IntSize& aSize,
+      bool aAllowShared = true, bool aRenderable = false,
+      const WebGLTexture* aAvoid = nullptr);
   void DrawQuad();
   void DrawTriangles(const PathVertexRange& aRange);
   bool DrawRectAccel(const Rect& aRect, const Pattern& aPattern,
@@ -601,6 +603,7 @@ class DrawTargetWebgl : public DrawTarget, public SupportsWeakPtr {
   UsageProfile mProfile;
 
   RefPtr<SharedContextWebgl> mSharedContext;
+  dom::ContentParentId mContentId;
 
  public:
   DrawTargetWebgl();
@@ -609,10 +612,12 @@ class DrawTargetWebgl : public DrawTarget, public SupportsWeakPtr {
   static bool CanCreate(const IntSize& aSize, SurfaceFormat aFormat);
   static already_AddRefed<DrawTargetWebgl> Create(
       const IntSize& aSize, SurfaceFormat aFormat,
-      const RefPtr<SharedContextWebgl>& aSharedContext);
+      const RefPtr<SharedContextWebgl>& aSharedContext,
+      const dom::ContentParentId& aContentId);
 
   bool Init(const IntSize& aSize, SurfaceFormat aFormat,
-            const RefPtr<SharedContextWebgl>& aSharedContext);
+            const RefPtr<SharedContextWebgl>& aSharedContext,
+            const dom::ContentParentId& aContentId);
 
   bool IsValid() const override;
 
@@ -625,6 +630,7 @@ class DrawTargetWebgl : public DrawTarget, public SupportsWeakPtr {
   const RefPtr<SharedContextWebgl>& GetSharedContext() const {
     return mSharedContext;
   }
+  const dom::ContentParentId& GetContentId() const { return mContentId; }
 
   bool HasDataSnapshot() const;
   bool EnsureDataSnapshot();
diff --git a/dom/canvas/DrawTargetWebglInternal.h b/dom/canvas/DrawTargetWebglInternal.h
index dda9b25b9bf..ed72c54cd84 100644
--- a/dom/canvas/DrawTargetWebglInternal.h
+++ b/dom/canvas/DrawTargetWebglInternal.h
@@ -220,7 +220,8 @@ class SharedTexture : public RefCounted<SharedTexture>, public BackingTexture {
   MOZ_DECLARE_REFCOUNTED_TYPENAME(SharedTexture)
 
   SharedTexture(const IntSize& aSize, SurfaceFormat aFormat,
-                const RefPtr<WebGLTexture>& aTexture);
+                const RefPtr<WebGLTexture>& aTexture,
+                const dom::ContentParentId& aContentId);
   ~SharedTexture();
 
   already_AddRefed<SharedTextureHandle> Allocate(const IntSize& aSize);
@@ -231,8 +232,11 @@ class SharedTexture : public RefCounted<SharedTexture>, public BackingTexture {
                                   mAtlasAllocator) > 0;
   }
 
+  const dom::ContentParentId& GetContentId() const { return mContentId; }
+
  private:
   Etagere::AtlasAllocator* mAtlasAllocator = nullptr;
+  dom::ContentParentId mContentId;
 };
 
 // SharedTextureHandle is an allocated region within a large SharedTexture page
diff --git a/gfx/2d/RecordedEvent.h b/gfx/2d/RecordedEvent.h
index b3049d86f8d..a3a81b300c7 100644
--- a/gfx/2d/RecordedEvent.h
+++ b/gfx/2d/RecordedEvent.h
@@ -109,7 +109,7 @@ class Translator {
   }
   virtual already_AddRefed<SourceSurface>
   LookupSourceSurfaceFromSurfaceDescriptor(
-      const layers::SurfaceDescriptor& aDesc) {
+      DrawTarget* aDT, const layers::SurfaceDescriptor& aDesc) {
     MOZ_ASSERT_UNREACHABLE("unexpected to be called");
     return nullptr;
   }
diff --git a/gfx/2d/RecordedEventImpl.h b/gfx/2d/RecordedEventImpl.h
index 6ba0fb68575..88ec520156f 100644
--- a/gfx/2d/RecordedEventImpl.h
+++ b/gfx/2d/RecordedEventImpl.h
@@ -3297,7 +3297,7 @@ inline bool RecordedDrawSurfaceDescriptor::PlayEvent(
   }
 
   RefPtr<SourceSurface> surface =
-      aTranslator->LookupSourceSurfaceFromSurfaceDescriptor(mDesc);
+      aTranslator->LookupSourceSurfaceFromSurfaceDescriptor(dt, mDesc);
   if (!surface) {
     return false;
   }
diff --git a/gfx/layers/ipc/CanvasTranslator.cpp b/gfx/layers/ipc/CanvasTranslator.cpp
index befffefb5c5..2c1b6d6718c 100644
--- a/gfx/layers/ipc/CanvasTranslator.cpp
+++ b/gfx/layers/ipc/CanvasTranslator.cpp
@@ -1243,8 +1243,8 @@ already_AddRefed<gfx::DrawTarget> CanvasTranslator::CreateDrawTarget(
     if (EnsureSharedContextWebgl()) {
       mSharedContext->EnterTlsScope();
     }
-    if (RefPtr<gfx::DrawTargetWebgl> webgl =
-            gfx::DrawTargetWebgl::Create(aSize, aFormat, mSharedContext)) {
+    if (RefPtr<gfx::DrawTargetWebgl> webgl = gfx::DrawTargetWebgl::Create(
+            aSize, aFormat, mSharedContext, mContentId)) {
       webgl->BeginFrame(true);
       dt = webgl.forget().downcast<gfx::DrawTarget>();
       if (dt) {
@@ -1637,7 +1637,8 @@ CanvasTranslator::MaybeRecycleDataSurfaceForSurfaceDescriptor(
 
 #ifdef MOZ_WIDGET_GTK
 already_AddRefed<gfx::SourceSurface>
-CanvasTranslator::GetZeroCopySurfaceFromDMABuf(TextureHost* aTextureHost) {
+CanvasTranslator::GetZeroCopySurfaceFromDMABuf(gfx::DrawTarget* aDT,
+                                               TextureHost* aTextureHost) {
   if (!aTextureHost) {
     return nullptr;
   }
@@ -1672,16 +1673,17 @@ CanvasTranslator::GetZeroCopySurfaceFromDMABuf(TextureHost* aTextureHost) {
     default:
       return nullptr;
   }
-  if (!EnsureSharedContextWebgl() || !mSharedContext) {
-    return nullptr;
+  if (aDT->GetBackendType() == gfx::BackendType::WEBGL) {
+    return static_cast<gfx::DrawTargetWebgl*>(aDT)->ImportSurfaceDescriptor(
+        hostSd, size, format);
   }
-  return mSharedContext->ImportSurfaceDescriptor(hostSd, size, format);
+  return nullptr;
 }
 #endif
 
 already_AddRefed<gfx::SourceSurface>
 CanvasTranslator::LookupSourceSurfaceFromSurfaceDescriptor(
-    const SurfaceDescriptor& aDesc) {
+    DrawTarget* aDT, const SurfaceDescriptor& aDesc) {
   if (!SDIsSupportedRemoteDecoder(aDesc)) {
     return nullptr;
   }
@@ -1749,7 +1751,7 @@ CanvasTranslator::LookupSourceSurfaceFromSurfaceDescriptor(
 #ifdef MOZ_WIDGET_GTK
   if (sdrd.videoType() == RemoteDecoderVideoType::DMABuf) {
     if (RefPtr<gfx::SourceSurface> surf =
-            GetZeroCopySurfaceFromDMABuf(texture)) {
+            GetZeroCopySurfaceFromDMABuf(aDT, texture)) {
       return surf.forget();
     }
     // The zero-copy import can fail for an unsupported layout or a lost shared
@@ -1891,7 +1893,7 @@ bool CanvasTranslator::ResolveExternalSnapshot(uint64_t aSyncId,
         // If we can't import the surface using the DT, then try using the
         // global shared context to allow for a readback.
         resolved = mSharedContext->ImportSurfaceDescriptor(
-            *snapshot.mDescriptor, aSize, aFormat);
+            nullptr, *snapshot.mDescriptor, aSize, aFormat);
       }
     }
     snapshot.mSharedSurface->EndRead();
diff --git a/gfx/layers/ipc/CanvasTranslator.h b/gfx/layers/ipc/CanvasTranslator.h
index 09d9325d112..2b783e782e2 100644
--- a/gfx/layers/ipc/CanvasTranslator.h
+++ b/gfx/layers/ipc/CanvasTranslator.h
@@ -253,7 +253,7 @@ class CanvasTranslator final : public gfx::InlineTranslator,
       uint64_t aKey) final;
 
   already_AddRefed<gfx::SourceSurface> LookupSourceSurfaceFromSurfaceDescriptor(
-      const SurfaceDescriptor& aDesc) final;
+      gfx::DrawTarget* aDT, const SurfaceDescriptor& aDesc) final;
 
   /**
    * Gets the cached DataSourceSurface, if it exists, associated with a
@@ -479,7 +479,7 @@ class CanvasTranslator final : public gfx::InlineTranslator,
   // on the GPU, returning a directly samplable surface (no CPU download).
   // Falls back to nullptr when GL import is unavailable.
   already_AddRefed<gfx::SourceSurface> GetZeroCopySurfaceFromDMABuf(
... (file diff truncated)
Loading diff…