Firefox · DOM
CVE-2026-8963
Logic Error in DOM
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
functiondom/media/webspeech/synth/test/test_speech_cancel_on_navigation.html |
modified |
Files Changed
dom/media/webspeech/synth/SpeechSynthesis.cppdom/media/webspeech/synth/SpeechSynthesis.hdom/media/webspeech/synth/test/file_speech_cancel_on_navigation_page1.htmldom/media/webspeech/synth/test/file_speech_cancel_on_navigation_page2.htmldom/media/webspeech/synth/test/mochitest.tomldom/media/webspeech/synth/test/test_speech_cancel_on_navigation.html
Patch
diff --git a/dom/media/webspeech/synth/SpeechSynthesis.cpp b/dom/media/webspeech/synth/SpeechSynthesis.cpp
index 100fee9982e..0bb806013f8 100644
--- a/dom/media/webspeech/synth/SpeechSynthesis.cpp
+++ b/dom/media/webspeech/synth/SpeechSynthesis.cpp
@@ -270,6 +270,11 @@ void SpeechSynthesis::ForceEnd() {
}
}
+void SpeechSynthesis::DisconnectFromOwner() {
+ Cancel();
+ DOMEventTargetHelper::DisconnectFromOwner();
+}
+
NS_IMETHODIMP
SpeechSynthesis::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) {
diff --git a/dom/media/webspeech/synth/SpeechSynthesis.h b/dom/media/webspeech/synth/SpeechSynthesis.h
index 7d69f98ba73..2c9e4ff062b 100644
--- a/dom/media/webspeech/synth/SpeechSynthesis.h
+++ b/dom/media/webspeech/synth/SpeechSynthesis.h
@@ -57,6 +57,8 @@ class SpeechSynthesis final : public DOMEventTargetHelper,
void ForceEnd();
+ void DisconnectFromOwner() override;
+
IMPL_EVENT_HANDLER(voiceschanged)
private:
diff --git a/dom/media/webspeech/synth/test/file_speech_cancel_on_navigation_page1.html b/dom/media/webspeech/synth/test/file_speech_cancel_on_navigation_page1.html
new file mode 100644
index 00000000000..3714e5aff2c
--- /dev/null
+++ b/dom/media/webspeech/synth/test/file_speech_cancel_on_navigation_page1.html
@@ -0,0 +1,11 @@
+<html>
+<script>
+ var u = new SpeechSynthesisUtterance("hello");
+ u.lang = "it-IT-noend";
+ u.addEventListener("start", function() {
+ location = "file_speech_cancel_on_navigation_page2.html";
+ });
+ speechSynthesis.speak(u);
+</script>
+<body></body>
+</html>
diff --git a/dom/media/webspeech/synth/test/file_speech_cancel_on_navigation_page2.html b/dom/media/webspeech/synth/test/file_speech_cancel_on_navigation_page2.html
new file mode 100644
index 00000000000..5a4fa20a47e
--- /dev/null
+++ b/dom/media/webspeech/synth/test/file_speech_cancel_on_navigation_page2.html
@@ -0,0 +1,13 @@
+<html>
+<script>
+ window.ok = parent.ok;
+
+ var u = new SpeechSynthesisUtterance("hi");
+ u.addEventListener("end", function() {
+ ok(true, "Speech in new page completed: previous speech was cancelled on navigation.");
+ parent.onDone();
+ });
+ speechSynthesis.speak(u);
+</script>
+<body></body>
+</html>
diff --git a/dom/media/webspeech/synth/test/mochitest.toml b/dom/media/webspeech/synth/test/mochitest.toml
index 5180e2ea018..dc41cec561b 100644
--- a/dom/media/webspeech/synth/test/mochitest.toml
+++ b/dom/media/webspeech/synth/test/mochitest.toml
@@ -15,6 +15,8 @@ support-files = [
"file_global_queue_cancel.html",
"file_global_queue_pause.html",
"file_speech_repeating_utterance.html",
+ "file_speech_cancel_on_navigation_page1.html",
+ "file_speech_cancel_on_navigation_page2.html",
]
["test_bfcache.html"]
@@ -38,3 +40,5 @@ support-files = [
["test_speech_repeating_utterance.html"]
["test_speech_simple.html"]
+
+["test_speech_cancel_on_navigation.html"]
diff --git a/dom/media/webspeech/synth/test/test_speech_cancel_on_navigation.html b/dom/media/webspeech/synth/test/test_speech_cancel_on_navigation.html
new file mode 100644
index 00000000000..72fd0b3fef0
--- /dev/null
+++ b/dom/media/webspeech/synth/test/test_speech_cancel_on_navigation.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test speech is cancelled when the page navigates away</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="common.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<iframe id="testFrame"></iframe>
+<pre id="test">
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+function onDone() {
+ SimpleTest.finish();
+}
+
+SpecialPowers.pushPrefEnv(
+ { set: [["media.webspeech.synth.enabled", true],
+ ["media.webspeech.synth.force_global_queue", true]] },
+ function() { loadSpeechTest("file_speech_cancel_on_navigation_page1.html"); }
+);
+
+</script>
+</pre>
+</body>
+</html>
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/dom/media/webspeech/synth/test/file_speech_cancel_on_navigation_page1.html b/dom/media/webspeech/synth/test/file_speech_cancel_on_navigation_page1.html
new file mode 100644
index 00000000000..3714e5aff2c
--- /dev/null
+++ b/dom/media/webspeech/synth/test/file_speech_cancel_on_navigation_page1.html
@@ -0,0 +1,11 @@
+<html>
+<script>
+ var u = new SpeechSynthesisUtterance("hello");
+ u.lang = "it-IT-noend";
+ u.addEventListener("start", function() {
+ location = "file_speech_cancel_on_navigation_page2.html";
+ });
+ speechSynthesis.speak(u);
+</script>
+<body></body>
+</html>
diff --git a/dom/media/webspeech/synth/test/file_speech_cancel_on_navigation_page2.html b/dom/media/webspeech/synth/test/file_speech_cancel_on_navigation_page2.html
new file mode 100644
index 00000000000..5a4fa20a47e
--- /dev/null
+++ b/dom/media/webspeech/synth/test/file_speech_cancel_on_navigation_page2.html
@@ -0,0 +1,13 @@
+<html>
+<script>
+ window.ok = parent.ok;
+
+ var u = new SpeechSynthesisUtterance("hi");
+ u.addEventListener("end", function() {
+ ok(true, "Speech in new page completed: previous speech was cancelled on navigation.");
+ parent.onDone();
+ });
+ speechSynthesis.speak(u);
+</script>
+<body></body>
+</html>
diff --git a/dom/media/webspeech/synth/test/mochitest.toml b/dom/media/webspeech/synth/test/mochitest.toml
index 5180e2ea018..dc41cec561b 100644
--- a/dom/media/webspeech/synth/test/mochitest.toml
+++ b/dom/media/webspeech/synth/test/mochitest.toml
@@ -15,6 +15,8 @@ support-files = [
"file_global_queue_cancel.html",
"file_global_queue_pause.html",
"file_speech_repeating_utterance.html",
+ "file_speech_cancel_on_navigation_page1.html",
+ "file_speech_cancel_on_navigation_page2.html",
]
["test_bfcache.html"]
@@ -38,3 +40,5 @@ support-files = [
["test_speech_repeating_utterance.html"]
["test_speech_simple.html"]
+
+["test_speech_cancel_on_navigation.html"]
diff --git a/dom/media/webspeech/synth/test/test_speech_cancel_on_navigation.html b/dom/media/webspeech/synth/test/test_speech_cancel_on_navigation.html
new file mode 100644
index 00000000000..72fd0b3fef0
--- /dev/null
+++ b/dom/media/webspeech/synth/test/test_speech_cancel_on_navigation.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test speech is cancelled when the page navigates away</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="common.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<iframe id="testFrame"></iframe>
+<pre id="test">
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+function onDone() {
+ SimpleTest.finish();
+}
+
+SpecialPowers.pushPrefEnv(
+ { set: [["media.webspeech.synth.enabled", true],
+ ["media.webspeech.synth.force_global_queue", true]] },
+ function() { loadSpeechTest("file_speech_cancel_on_navigation_page1.html"); }
+);
+
+</script>
+</pre>
+</body>
+</html>
Loading diff…
References
On This Page