Medium firefox Logic Error 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactmoderate
DescriptionMemory safety bug fixed in Firefox 152
ComponentCore
Bug ClassLogic Error
Tracker2038133
Fix commitc406de81099c (firefox) +26/-23
CISA KEVNot listed
CreditedAtsushi Sada
Disclosed2026-06-16

Changed Functions

FunctionChangeNotes
add_task
devtools/client/styleeditor/test/browser_styleeditor_filesave.js
modified

Files Changed

  • devtools/client/styleeditor/StyleSheetEditor.sys.mjs
  • devtools/client/styleeditor/test/browser_styleeditor_filesave.js
  • devtools/client/styleeditor/test/browser_styleeditor_sourcemap_watching.js
diff --git a/devtools/client/styleeditor/StyleSheetEditor.sys.mjs b/devtools/client/styleeditor/StyleSheetEditor.sys.mjs
index 4b74a5b2114..26d90bcb523 100644
--- a/devtools/client/styleeditor/StyleSheetEditor.sys.mjs
+++ b/devtools/client/styleeditor/StyleSheetEditor.sys.mjs
@@ -113,14 +113,6 @@ export class StyleSheetEditor extends EventEmitter {
       },
     };
 
-    this._styleSheetFilePath = null;
-    if (
-      this.styleSheet.href &&
-      Services.io.extractScheme(this.styleSheet.href) == "file"
-    ) {
-      this._styleSheetFilePath = this.styleSheet.href;
-    }
-
     this.onPropertyChange = this.onPropertyChange.bind(this);
     this.onAtRulesChanged = this.onAtRulesChanged.bind(this);
     this.checkLinkedFileForChanges = this.checkLinkedFileForChanges.bind(this);
@@ -823,13 +815,7 @@ export class StyleSheetEditor extends EventEmitter {
         ? PathUtils.filename(this._friendlyName)
         : this._friendlyName;
     }
-    showFilePicker(
-      file || this._styleSheetFilePath,
-      true,
-      this._window,
-      onFile,
-      defaultName
-    );
+    showFilePicker(file, true, this._window, onFile, defaultName);
   }
 
   /**
diff --git a/devtools/client/styleeditor/test/browser_styleeditor_filesave.js b/devtools/client/styleeditor/test/browser_styleeditor_filesave.js
index d59137af252..d4624b2bc86 100644
--- a/devtools/client/styleeditor/test/browser_styleeditor_filesave.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_filesave.js
@@ -9,7 +9,7 @@ const TESTCASE_URI_CSS = TEST_BASE_HTTP + "simple.css";
 
 add_task(async function () {
   const htmlFile = await copy(TESTCASE_URI_HTML, "simple.html");
-  await copy(TESTCASE_URI_CSS, "simple.css");
+  const cssFile = await copy(TESTCASE_URI_CSS, "simple.css");
   const uri = Services.io.newFileURI(htmlFile);
   const filePath = uri.resolve("");
 
@@ -18,6 +18,12 @@ add_task(async function () {
   const editor = ui.editors[0];
   await editor.getSourceEditor();
 
+  is(
+    editor.savedFile,
+    null,
+    "savedFile should not be pre-populated from the source file"
+  );
+
   info("Editing the style sheet.");
   let dirty = editor.sourceEditor.once("dirty-change");
   const beginCursor = { line: 0, ch: 0 };
@@ -31,11 +37,13 @@ add_task(async function () {
     "Star icon is present in the corresponding summary."
   );
 
-  info("Saving the changes.");
+  info(
+    "Saving the changes with an explicit file (simulating a user-chosen save location)."
+  );
   dirty = editor.sourceEditor.once("dirty-change");
 
-  editor.saveToFile(null, function (file) {
-    ok(file, "file should get saved directly when using a file:// URI");
+  editor.saveToFile(cssFile, function (file) {
+    ok(file, "file should get saved when explicitly passing a file");
   });
 
   await dirty;
@@ -45,6 +53,12 @@ add_task(async function () {
     !editor.summary.classList.contains("unsaved"),
     "Star icon is not present in the corresponding summary."
   );
+
+  is(
+    editor.savedFile?.path,
+    cssFile.path,
+    "savedFile should now be set on the editor"
+  );
 });
 
 function copy(srcChromeURL, destFileName) {
diff --git a/devtools/client/styleeditor/test/browser_styleeditor_sourcemap_watching.js b/devtools/client/styleeditor/test/browser_styleeditor_sourcemap_watching.js
index 582f9f0a43c..8de40a02e37 100644
--- a/devtools/client/styleeditor/test/browser_styleeditor_sourcemap_watching.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_sourcemap_watching.js
@@ -26,7 +26,10 @@ add_task(async function () {
     "sourcemap-css",
     "sourcemaps.css",
   ]);
-  await copy(TESTCASE_URI_SCSS, ["sourcemap-sass", "sourcemaps.scss"]);
+  const SCSSFile = await copy(TESTCASE_URI_SCSS, [
+    "sourcemap-sass",
+    "sourcemaps.scss",
+  ]);
   await copy(TESTCASE_URI_MAP, ["sourcemap-css", "sourcemaps.css.map"]);
   await copy(TESTCASE_URI_REG_CSS, ["simple.css"]);
 
@@ -59,7 +62,7 @@ add_task(async function () {
 
   // Edit and save Sass in the editor. This will start off a file-watching
   // process waiting for the CSS file to change.
-  await editSCSS(editor);
+  await editSCSS(SCSSFile, editor);
 
   // We can't run Sass or another compiler, so we fake it by just
   // directly changing the CSS file.
@@ -76,11 +79,11 @@ add_task(async function () {
   is(editor.sourceEditor.getText(), CSS_TEXT, "edits remain applied");
 });
 
-function editSCSS(editor) {
+function editSCSS(SCSSFile, editor) {
   return new Promise(resolve => {
     editor.sourceEditor.setText(CSS_TEXT);
 
-    editor.saveToFile(null, function (file) {
+    editor.saveToFile(SCSSFile, function (file) {
       ok(file, "Scss file should be saved");
       resolve();
     });
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/devtools/client/styleeditor/test/browser_styleeditor_filesave.js b/devtools/client/styleeditor/test/browser_styleeditor_filesave.js
index d59137af252..d4624b2bc86 100644
--- a/devtools/client/styleeditor/test/browser_styleeditor_filesave.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_filesave.js
@@ -9,7 +9,7 @@ const TESTCASE_URI_CSS = TEST_BASE_HTTP + "simple.css";
 
 add_task(async function () {
   const htmlFile = await copy(TESTCASE_URI_HTML, "simple.html");
-  await copy(TESTCASE_URI_CSS, "simple.css");
+  const cssFile = await copy(TESTCASE_URI_CSS, "simple.css");
   const uri = Services.io.newFileURI(htmlFile);
   const filePath = uri.resolve("");
 
@@ -18,6 +18,12 @@ add_task(async function () {
   const editor = ui.editors[0];
   await editor.getSourceEditor();
 
+  is(
+    editor.savedFile,
+    null,
+    "savedFile should not be pre-populated from the source file"
+  );
+
   info("Editing the style sheet.");
   let dirty = editor.sourceEditor.once("dirty-change");
   const beginCursor = { line: 0, ch: 0 };
@@ -31,11 +37,13 @@ add_task(async function () {
     "Star icon is present in the corresponding summary."
   );
 
-  info("Saving the changes.");
+  info(
+    "Saving the changes with an explicit file (simulating a user-chosen save location)."
+  );
   dirty = editor.sourceEditor.once("dirty-change");
 
-  editor.saveToFile(null, function (file) {
-    ok(file, "file should get saved directly when using a file:// URI");
+  editor.saveToFile(cssFile, function (file) {
+    ok(file, "file should get saved when explicitly passing a file");
   });
 
   await dirty;
@@ -45,6 +53,12 @@ add_task(async function () {
     !editor.summary.classList.contains("unsaved"),
     "Star icon is not present in the corresponding summary."
   );
+
+  is(
+    editor.savedFile?.path,
+    cssFile.path,
+    "savedFile should now be set on the editor"
+  );
 });
 
 function copy(srcChromeURL, destFileName) {
diff --git a/devtools/client/styleeditor/test/browser_styleeditor_sourcemap_watching.js b/devtools/client/styleeditor/test/browser_styleeditor_sourcemap_watching.js
index 582f9f0a43c..8de40a02e37 100644
--- a/devtools/client/styleeditor/test/browser_styleeditor_sourcemap_watching.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_sourcemap_watching.js
@@ -26,7 +26,10 @@ add_task(async function () {
     "sourcemap-css",
     "sourcemaps.css",
   ]);
-  await copy(TESTCASE_URI_SCSS, ["sourcemap-sass", "sourcemaps.scss"]);
+  const SCSSFile = await copy(TESTCASE_URI_SCSS, [
+    "sourcemap-sass",
+    "sourcemaps.scss",
+  ]);
   await copy(TESTCASE_URI_MAP, ["sourcemap-css", "sourcemaps.css.map"]);
   await copy(TESTCASE_URI_REG_CSS, ["simple.css"]);
 
@@ -59,7 +62,7 @@ add_task(async function () {
 
   // Edit and save Sass in the editor. This will start off a file-watching
   // process waiting for the CSS file to change.
-  await editSCSS(editor);
+  await editSCSS(SCSSFile, editor);
 
   // We can't run Sass or another compiler, so we fake it by just
   // directly changing the CSS file.
@@ -76,11 +79,11 @@ add_task(async function () {
   is(editor.sourceEditor.getText(), CSS_TEXT, "edits remain applied");
 });
 
-function editSCSS(editor) {
+function editSCSS(SCSSFile, editor) {
   return new Promise(resolve => {
     editor.sourceEditor.setText(CSS_TEXT);
 
-    editor.saveToFile(null, function (file) {
+    editor.saveToFile(SCSSFile, function (file) {
       ok(file, "Scss file should be saved");
       resolve();
     });
Loading diff…