60 lines
2.3 KiB
Diff
60 lines
2.3 KiB
Diff
# UNDF: UNDF-2026-000000054
|
|
--- a/Source/Dry/UI/ListView.h
|
|
+++ b/Source/Dry/UI/ListView.h
|
|
@@ -... ListView class members
|
|
- PODVector<unsigned> selections_;
|
|
+ PODVector<unsigned> selections_; // preserved for ordered iteration
|
|
+ HashSet<unsigned> selections_set_; // O(1) shadow index for Contains checks
|
|
|
|
--- a/Source/Dry/UI/ListView.cpp
|
|
+++ b/Source/Dry/UI/ListView.cpp
|
|
@@ -518,7 +518,8 @@ void ListView::SetSelections(const PODVector<unsigned>& indices)
|
|
unsigned numItems = GetNumItems();
|
|
|
|
+ // FIX dry-0001: build O(1) lookup set from incoming indices — CWE-407
|
|
+ // Both loops below called indices.Contains() or selections_.Contains() which are
|
|
+ // O(n) linear scans on PODVector. At k=1000 selections: O(n²) = 1,000,000 ops.
|
|
+ HashSet<unsigned> indicesSet(indices.Begin(), indices.End());
|
|
+
|
|
// Remove first items that should no longer be selected
|
|
for (PODVector<unsigned>::Iterator i = selections_.Begin(); i != selections_.End();)
|
|
{
|
|
unsigned index = *i;
|
|
- if (!indices.Contains(index)) // O(n) — CWE-407
|
|
+ if (!indicesSet.Contains(index)) // O(1) — fixed
|
|
{
|
|
i = selections_.Erase(i);
|
|
+ selections_set_.Erase(index);
|
|
|
|
using namespace ItemSelected;
|
|
// ... SendEvent(E_ITEMDESELECTED, ...)
|
|
}
|
|
else
|
|
++i;
|
|
}
|
|
|
|
// Then add missing items
|
|
for (PODVector<unsigned>::ConstIterator i = indices.Begin(); i != indices.End(); ++i)
|
|
{
|
|
unsigned index = *i;
|
|
if (index < numItems)
|
|
{
|
|
- bool duplicate = selections_.Contains(index); // O(n) — CWE-407
|
|
+ bool duplicate = selections_set_.Contains(index); // O(1) — fixed
|
|
if (!duplicate || !multiselect_)
|
|
{
|
|
if (!duplicate)
|
|
{
|
|
selections_.Push(index);
|
|
+ selections_set_.Insert(index);
|
|
added = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// All other methods that modify selections_ must also maintain selections_set_:
|
|
// AddSelection(index) → selections_set_.Insert(index)
|
|
// RemoveSelection(index) → selections_set_.Erase(index)
|
|
// ClearSelection() → selections_set_.Clear()
|