Firefox · DOM
CVE-2026-109724
Logic Error in DOM
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
fordom/html/HTMLSelectElement.cpp |
modified | |
Resetdom/html/HTMLSelectElement.cpp |
modified | |
ifdom/html/HTMLSelectElement.cpp |
modified |
Files Changed
dom/html/HTMLOptionElement.cppdom/html/HTMLOptionsCollection.cppdom/html/HTMLSelectElement.cppdom/prototype/PrototypeDocumentContentSink.cppdom/xml/nsXMLContentSink.cpp
Patch
diff --git a/dom/html/HTMLOptionElement.cpp b/dom/html/HTMLOptionElement.cpp
index fc17181ef7d..4fe0db3ad31 100644
--- a/dom/html/HTMLOptionElement.cpp
+++ b/dom/html/HTMLOptionElement.cpp
@@ -17,6 +17,7 @@
#include "mozilla/dom/Document.h"
#include "nsCOMPtr.h"
#include "nsContentCreatorFunctions.h"
+#include "nsContentUtils.h"
#include "nsNodeInfoManager.h"
#include "nsTextNode.h"
@@ -88,6 +89,7 @@ void HTMLOptionElement::SetSelected(bool aValue) {
// Note: The select content obj maintains all the PresState
// so defer to it to get the answer
if (HTMLSelectElement* select = GetSelect()) {
+ nsAutoScriptBlocker scriptBlocker;
int32_t index = Index();
HTMLSelectElement::OptionFlags mask{
HTMLSelectElement::OptionFlag::SetDisabled,
@@ -129,6 +131,7 @@ int32_t HTMLOptionElement::Index() {
return defaultIndex;
}
+ nsAutoScriptBlocker scriptBlocker;
int32_t index = defaultIndex;
MOZ_ALWAYS_SUCCEEDS(options->GetOptionIndex(this, 0, true, &index));
return index;
diff --git a/dom/html/HTMLOptionsCollection.cpp b/dom/html/HTMLOptionsCollection.cpp
index bbb221d3bde..399f46a4150 100644
--- a/dom/html/HTMLOptionsCollection.cpp
+++ b/dom/html/HTMLOptionsCollection.cpp
@@ -7,6 +7,7 @@
#include "mozilla/dom/HTMLOptionElement.h"
#include "mozilla/dom/HTMLOptionsCollectionBinding.h"
#include "mozilla/dom/HTMLSelectElement.h"
+#include "nsContentUtils.h"
namespace mozilla::dom {
@@ -41,6 +42,8 @@ HTMLSelectElement* HTMLOptionsCollection::Select() const {
nsresult HTMLOptionsCollection::GetOptionIndex(Element* aOption,
int32_t aStartIndex,
bool aForward, int32_t* aIndex) {
+ MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(),
+ "Callers must hold a script blocker");
BringSelfUpToDate(true);
// NOTE: aIndex shouldn't be set if the returned value isn't NS_OK.
diff --git a/dom/html/HTMLSelectElement.cpp b/dom/html/HTMLSelectElement.cpp
index a2ccb9e8965..8d74c97bc0d 100644
--- a/dom/html/HTMLSelectElement.cpp
+++ b/dom/html/HTMLSelectElement.cpp
@@ -692,6 +692,7 @@ HTMLOptionElement* HTMLSelectElement::GetSelectedOption(
}
int32_t HTMLSelectElement::SelectedIndex() const {
+ nsAutoScriptBlocker scriptBlocker;
uint32_t len = Length();
for (uint32_t i = 0; i < len; ++i) {
if (Item(i)->Selected()) {
@@ -702,6 +703,7 @@ int32_t HTMLSelectElement::SelectedIndex() const {
}
void HTMLSelectElement::SetSelectedIndex(int32_t aIdx) {
+ nsAutoScriptBlocker scriptBlocker;
SetSelectedIndexInternal(aIdx, true);
// https://html.spec.whatwg.org/#dom-select-selectedindex
// Step 4: Run update a select's descendant selectedcontent elements.
@@ -815,6 +817,8 @@ void HTMLSelectElement::OnOptionSelected(int32_t aIndex, bool aSelected,
bool HTMLSelectElement::SetOptionsSelectedByIndex(int32_t aStartIndex,
int32_t aEndIndex,
OptionFlags aOptionsMask) {
+ MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(),
+ "Callers must hold a script blocker");
#if 0
printf("SetOption(%d-%d, %c, ClearAll=%c)\n", aStartIndex, aEndIndex,
(aOptionsMask.contains(OptionFlag::IsSelected) ? 'Y' : 'N'),
@@ -982,6 +986,7 @@ void HTMLSelectElement::GetValue(nsAString& aValue) const {
// https://html.spec.whatwg.org/#dom-select-value
void HTMLSelectElement::SetValue(const nsAString& aValue) {
+ nsAutoScriptBlocker scriptBlocker;
uint32_t length = Length();
int32_t matchIndex = -1;
for (uint32_t i = 0; i < length; i++) {
@@ -1397,31 +1402,34 @@ void HTMLSelectElement::RestoreStateTo(const SelectContentData& aNewSelected) {
NS_IMETHODIMP
HTMLSelectElement::Reset() {
- //
- // Cycle through the options array and reset the options
- //
- uint32_t numOptions = Length();
+ {
+ nsAutoScriptBlocker scriptBlocker;
+ //
+ // Cycle through the options array and reset the options
+ //
+ uint32_t numOptions = Length();
+
+ for (uint32_t i = 0; i < numOptions; i++) {
+ RefPtr<HTMLOptionElement> option = Item(i);
+ if (option) {
+ //
+ // Reset the option to its default value
+ //
+
+ OptionFlags mask = {OptionFlag::SetDisabled, OptionFlag::Notify,
+ OptionFlag::NoReselect};
+ if (option->DefaultSelected()) {
+ mask += OptionFlag::IsSelected;
+ }
- for (uint32_t i = 0; i < numOptions; i++) {
- RefPtr<HTMLOptionElement> option = Item(i);
- if (option) {
- //
- // Reset the option to its default value
- //
-
- OptionFlags mask = {OptionFlag::SetDisabled, OptionFlag::Notify,
- OptionFlag::NoReselect};
- if (option->DefaultSelected()) {
- mask += OptionFlag::IsSelected;
+ SetOptionsSelectedByIndex(i, i, mask);
+ option->SetSelectedChanged(false);
}
-
- SetOptionsSelectedByIndex(i, i, mask);
- option->SetSelectedChanged(false);
}
- }
- // https://html.spec.whatwg.org/#concept-form-reset-control step 3
- RunSelectednessSettingAlgorithm();
+ // https://html.spec.whatwg.org/#concept-form-reset-control step 3
+ RunSelectednessSettingAlgorithm();
+ }
OnSelectionChanged();
SetUserInteracted(false);
@@ -2113,6 +2121,7 @@ void HTMLSelectElement::RemoveOptionFromListBoxSelection(
bool HTMLSelectElement::ExtendedSelection(int32_t aStartIndex,
int32_t aEndIndex, bool aClearAll) {
+ nsAutoScriptBlocker scriptBlocker;
OptionFlags mask = OptionFlag::Notify;
mask += OptionFlag::IsSelected;
if (aClearAll) {
@@ -2122,6 +2131,7 @@ bool HTMLSelectElement::ExtendedSelection(int32_t aStartIndex,
}
bool HTMLSelectElement::ToggleOptionSelected(int32_t aIndex) {
+ nsAutoScriptBlocker scriptBlocker;
RefPtr<HTMLOptionElement> option = Item(static_cast<uint32_t>(aIndex));
NS_ENSURE_TRUE(option, false);
@@ -2537,16 +2547,19 @@ nsresult HTMLSelectElement::HandleKeyPress(EventChainPostVisitor& aVisitor) {
});
if (isSelectAll) {
using OptionFlag = HTMLSelectElement::OptionFlag;
- uint32_t numOptions = Length();
- if (numOptions) {
- HTMLSelectElement::OptionFlags mask = {
- OptionFlag::IsSelected, OptionFlag::ClearAll, OptionFlag::Notify};
- const bool wasChanged = SetOptionsSelectedByIndex(
- 0, AssertedCast<int32_t>(numOptions - 1), mask);
- if (wasChanged) {
- UserFinishedInteracting(/* aChanged = */ true);
+ bool wasChanged = false;
+ {
+ nsAutoScriptBlocker scriptBlocker;
+ if (uint32_t numOptions = Length()) {
+ HTMLSelectElement::OptionFlags mask = {
+ OptionFlag::IsSelected, OptionFlag::ClearAll, OptionFlag::Notify};
+ wasChanged = SetOptionsSelectedByIndex(
+ 0, AssertedCast<int32_t>(numOptions - 1), mask);
}
}
+ if (wasChanged) {
+ UserFinishedInteracting(/* aChanged = */ true);
+ }
aVisitor.mEvent->PreventDefault();
}
return NS_OK;
diff --git a/dom/prototype/PrototypeDocumentContentSink.cpp b/dom/prototype/PrototypeDocumentContentSink.cpp
index a916c5ceaa9..a991a397f24 100644
--- a/dom/prototype/PrototypeDocumentContentSink.cpp
+++ b/dom/prototype/PrototypeDocumentContentSink.cpp
@@ -420,6 +420,7 @@ void PrototypeDocumentContentSink::CloseElement(Element* aElement) {
if (nsIContent::RequiresDoneAddingChildren(
aElement->NodeInfo()->NamespaceID(),
aElement->NodeInfo()->NameAtom())) {
+ nsAutoScriptBlocker scriptBlocker;
aElement->DoneAddingChildren(false);
}
diff --git a/dom/xml/nsXMLContentSink.cpp b/dom/xml/nsXMLContentSink.cpp
index a07667efd11..f815a85a3d0 100644
--- a/dom/xml/nsXMLContentSink.cpp
+++ b/dom/xml/nsXMLContentSink.cpp
@@ -630,6 +630,7 @@ nsresult nsXMLContentSink::CloseElement(nsIContent* aContent) {
// properly (eg form state restoration).
if (nsIContent::RequiresDoneAddingChildren(nodeInfo->NamespaceID(),
nodeInfo->NameAtom())) {
+ nsAutoScriptBlocker scriptBlocker;
aContent->DoneAddingChildren(HaveNotifiedForCurrentContent());
}
Loading diff…
References
On This Page