High firefox Logic Error 🔧 Commit mapped

Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impacthigh
DescriptionPrivilege escalation in the Graphics: WebRender component
ComponentDOM
Bug ClassLogic Error
Tracker2023407
Fix commit3169838537d4 (firefox) +27/-42
CISA KEVNot listed
Creditedchoeseyeong
Disclosed2026-04-21

Changed Functions

FunctionChangeNotes
WrStartCaptureSequence
dom/base/nsDOMWindowUtils.cpp
modified
if
gfx/webrender_bindings/WebRenderAPI.cpp
modified

Files Changed

  • dom/base/nsDOMWindowUtils.cpp
  • dom/interfaces/base/nsIDOMWindowUtils.idl
  • gfx/layers/ipc/PWebRenderBridge.ipdl
  • gfx/layers/wr/WebRenderBridgeChild.cpp
  • gfx/layers/wr/WebRenderBridgeChild.h
  • gfx/layers/wr/WebRenderBridgeParent.cpp
  • gfx/layers/wr/WebRenderBridgeParent.h
  • gfx/webrender_bindings/WebRenderAPI.cpp
  • gfx/webrender_bindings/WebRenderAPI.h
  • gfx/webrender_bindings/src/bindings.rs
diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp
index 3d36876ed2b..f5ae11b8d1b 100644
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -4291,10 +4291,9 @@ nsDOMWindowUtils::WrCapture() {
 }
 
 NS_IMETHODIMP
-nsDOMWindowUtils::WrStartCaptureSequence(const nsACString& aPath,
-                                         uint32_t aFlags) {
+nsDOMWindowUtils::WrStartCaptureSequence(uint32_t aFlags) {
   if (WebRenderBridgeChild* wrbc = GetWebRenderBridge()) {
-    wrbc->StartCaptureSequence(nsCString(aPath), aFlags);
+    wrbc->StartCaptureSequence(aFlags);
   }
   return NS_OK;
 }
diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl
index 8c9784baced..1d904783296 100644
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -2031,7 +2031,7 @@ interface nsIDOMWindowUtils : nsISupports {
   /**
    * Start capturing each WebRender frame to disk.
    *
-   * |aPath| is the name of a new directory to be created to hold the captures.
+   * a new directory with name "wr-capture" is created to hold the captures.
    * it is relative to:
    * - the |PUBLIC_STORAGE| environment variable, if set, else
    * - the |MOZ_UPLOAD_DIR| environment variable, if set, else
@@ -2039,15 +2039,14 @@ interface nsIDOMWindowUtils : nsISupports {
    * the current directory.
    *
    * If there is already a directory with the given name, a numeric suffix is
-   * added to ensure a fresh directory is created. This means that you can't
-   * be sure your capture directory is actually named |aPath|.
+   * added to ensure a fresh directory is created.
    *
    * |aFlags| is a set of flags from |webrender::render_api::CaptureBits|.
    *
    * If there is already a sequence capture in progress, stop it and start a new
    * one, with the new path and flags.
    */
-  void wrStartCaptureSequence(in ACString aPath, in uint32_t aFlags);
+  void wrStartCaptureSequence(in uint32_t aFlags);
 
   /**
    * Stop a capture begun with |wrStartCaptureSequence|.
diff --git a/gfx/layers/ipc/PWebRenderBridge.ipdl b/gfx/layers/ipc/PWebRenderBridge.ipdl
index fbea4162b59..f22b5d0aa0e 100644
--- a/gfx/layers/ipc/PWebRenderBridge.ipdl
+++ b/gfx/layers/ipc/PWebRenderBridge.ipdl
@@ -75,7 +75,7 @@ parent:
 
   // Start capturing each frame to disk. See
   // nsIDOMWindowUtils::wrStartCaptureSequence for documentation.
-  async StartCaptureSequence(nsCString aPath, uint32_t aFlags);
+  async StartCaptureSequence(uint32_t aFlags);
 
   // Stop the captures started by StartCaptureSequence. See
   // nsIDOMWindowUtils::wrStopCaptureSequence for documentation.
diff --git a/gfx/layers/wr/WebRenderBridgeChild.cpp b/gfx/layers/wr/WebRenderBridgeChild.cpp
index f73074133d8..86d3b297604 100644
--- a/gfx/layers/wr/WebRenderBridgeChild.cpp
+++ b/gfx/layers/wr/WebRenderBridgeChild.cpp
@@ -589,9 +589,8 @@ void WebRenderBridgeChild::DeallocResourceShmem(RefCountedShmem& aShm) {
 
 void WebRenderBridgeChild::Capture() { this->SendCapture(); }
 
-void WebRenderBridgeChild::StartCaptureSequence(const nsCString& aPath,
-                                                uint32_t aFlags) {
-  this->SendStartCaptureSequence(aPath, aFlags);
+void WebRenderBridgeChild::StartCaptureSequence(uint32_t aFlags) {
+  this->SendStartCaptureSequence(aFlags);
 }
 
 void WebRenderBridgeChild::StopCaptureSequence() {
diff --git a/gfx/layers/wr/WebRenderBridgeChild.h b/gfx/layers/wr/WebRenderBridgeChild.h
index ad2c1b68594..2a32643b7af 100644
--- a/gfx/layers/wr/WebRenderBridgeChild.h
+++ b/gfx/layers/wr/WebRenderBridgeChild.h
@@ -183,7 +183,7 @@ class WebRenderBridgeChild final : public PWebRenderBridgeChild,
   void DeallocResourceShmem(RefCountedShmem& aShm);
 
   void Capture();
-  void StartCaptureSequence(const nsCString& path, uint32_t aFlags);
+  void StartCaptureSequence(uint32_t aFlags);
   void StopCaptureSequence();
 
   bool SendEnsureConnected(TextureFactoryIdentifier* textureFactoryIdentifier,
diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp
index e6ac646e451..ef4b5b085da 100644
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -2301,9 +2301,9 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvCapture() {
 }
 
 mozilla::ipc::IPCResult WebRenderBridgeParent::RecvStartCaptureSequence(
-    const nsACString& aPath, const uint32_t& aFlags) {
+    const uint32_t& aFlags) {
   if (EnsureInitialized()) {
-    mLateInit->mApi->StartCaptureSequence(aPath, aFlags);
+    mLateInit->mApi->StartCaptureSequence(aFlags);
   }
   return IPC_OK();
 }
diff --git a/gfx/layers/wr/WebRenderBridgeParent.h b/gfx/layers/wr/WebRenderBridgeParent.h
index d88f9a02110..698943773a0 100644
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -158,7 +158,7 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
       const wr::RenderReasons& aReasons) override;
   mozilla::ipc::IPCResult RecvCapture() override;
   mozilla::ipc::IPCResult RecvStartCaptureSequence(
-      const nsACString& path, const uint32_t& aFlags) override;
+      const uint32_t& aFlags) override;
   mozilla::ipc::IPCResult RecvStopCaptureSequence() override;
   mozilla::ipc::IPCResult RecvSyncWithCompositor() override;
 
diff --git a/gfx/webrender_bindings/WebRenderAPI.cpp b/gfx/webrender_bindings/WebRenderAPI.cpp
index 513c7a6df19..0a598c091bf 100644
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -876,23 +876,20 @@ bool WebRenderAPI::CheckAndClearDidRasterize() {
 void WebRenderAPI::Capture() {
   // see CaptureBits
   // SCENE | FRAME | TILE_CACHE
-  uint8_t bits = 15;                // TODO: get from JavaScript
-  const char* path = "wr-capture";  // TODO: get from JavaScript
+  uint8_t bits = 15;  // TODO: get from JavaScript
   const char* revision =
       gAppData ? (const char*)gAppData->sourceRevision : nullptr;
-  wr_api_capture(mDocHandle, path, revision, bits);
+  wr_api_capture(mDocHandle, revision, bits);
 }
 
-void WebRenderAPI::StartCaptureSequence(const nsACString& aPath,
-                                        uint32_t aFlags) {
+void WebRenderAPI::StartCaptureSequence(uint32_t aFlags) {
   if (mCaptureSequence) {
     wr_api_stop_capture_sequence(mDocHandle);
   }
   const char* revision =
       gAppData ? (const char*)gAppData->sourceRevision : nullptr;
 
-  wr_api_start_capture_sequence(mDocHandle, PromiseFlatCString(aPath).get(),
-                                revision, aFlags);
+  wr_api_start_capture_sequence(mDocHandle, revision, aFlags);
 
   mCaptureSequence = true;
 }
diff --git a/gfx/webrender_bindings/WebRenderAPI.h b/gfx/webrender_bindings/WebRenderAPI.h
index 949ff2b37d8..a769e010fe3 100644
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -313,7 +313,7 @@ class WebRenderAPI final {
 
   void Capture();
 
-  void StartCaptureSequence(const nsACString& aPath, uint32_t aFlags);
+  void StartCaptureSequence(uint32_t aFlags);
   void StopCaptureSequence();
 
   void BeginRecording(const TimeStamp& aRecordingStart,
diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs
index 1326e6c7efa..80d69bb107e 100644
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -2756,12 +2756,11 @@ pub extern "C" fn wr_resource_updates_add_raw_font(
     txn.add_raw_font(key, bytes.flush_into_vec(), index);
 }
 
-fn generate_capture_path(path: *const c_char, moz_revision: *const c_char) -> Option<PathBuf> {
+fn generate_capture_path(moz_revision: *const c_char) -> Option<PathBuf> {
     use std::fs::{create_dir_all, File};
     use std::io::Write;
 
-    let cstr = unsafe { CStr::from_ptr(path) };
-    let local_dir = PathBuf::from(&*cstr.to_string_lossy());
+    let local_dir = PathBuf::from("wr-capture");
 
     // On Android we need to write into a particular folder on external
     // storage so that (a) it can be written without requiring permissions
@@ -2812,26 +2811,16 @@ fn generate_capture_path(path: *const c_char, moz_revision: *const c_char) -> Op
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_capture(
-    dh: &mut DocumentHandle,
-    path: *const c_char,
-    moz_revision: *const c_char,
-    bits_raw: u32,
-) {
-    if let Some(path) = generate_capture_path(path, moz_revision) {
+pub extern "C" fn wr_api_capture(dh: &mut DocumentHandle, moz_revision: *const c_char, bits_raw: u32) {
+    if let Some(path) = generate_capture_path(moz_revision) {
         let bits = CaptureBits::from_bits(bits_raw as _).unwrap();
         dh.api.save_capture(path, bits);
     }
 }
Loading diff…