44 lines
1.9 KiB
Diff
44 lines
1.9 KiB
Diff
# UNDF: UNDF-2026-000000788
|
|
# UNDF: (leave blank)
|
|
# LibreOffice CWE-407: SfxSlotPool group dedup O(F*G)
|
|
#
|
|
# In sfx2/source/control/msgpool.cxx, when registering a new interface
|
|
# the code iterates over all slots (nFunc loop) and for each slot checks
|
|
# whether its GroupId is already in _vGroups via std::find(). This is
|
|
# O(F*G) where F=number of slots and G=number of groups.
|
|
#
|
|
# Fix: use an unordered_set for O(1) membership test during registration,
|
|
# keeping _vGroups as the canonical ordered list.
|
|
#
|
|
# Severity: LOW-MEDIUM — called once per interface registration at startup.
|
|
# With many modules loaded (Writer+Calc+Impress+Draw) the slot count
|
|
# can reach hundreds per interface. At F=300 slots, G=50 groups:
|
|
# 15,000 comparisons reduced to 300.
|
|
--- a/sfx2/source/control/msgpool.cxx
|
|
+++ b/sfx2/source/control/msgpool.cxx
|
|
@@ -124,14 +124,18 @@
|
|
// possibly add Interface-id and group-ids of funcs to the list of groups
|
|
if ( _pParentPool )
|
|
{
|
|
// The Groups in parent Slotpool are also known here
|
|
_vGroups.insert( _vGroups.end(), _pParentPool->_vGroups.begin(), _pParentPool->_vGroups.end() );
|
|
}
|
|
|
|
+ // Build a set for O(1) dedup during slot registration
|
|
+ std::unordered_set<SfxGroupId> aGroupSet(_vGroups.begin(), _vGroups.end());
|
|
+
|
|
for ( size_t nFunc = 0; nFunc < rInterface.Count(); ++nFunc )
|
|
{
|
|
const SfxSlot &rDef = rInterface.pSlots[nFunc];
|
|
if ( rDef.GetGroupId() != SfxGroupId::NONE &&
|
|
- std::find(_vGroups.begin(), _vGroups.end(), rDef.GetGroupId()) == _vGroups.end() )
|
|
+ aGroupSet.find(rDef.GetGroupId()) == aGroupSet.end() )
|
|
{
|
|
+ aGroupSet.insert(rDef.GetGroupId());
|
|
if (rDef.GetGroupId() == SfxGroupId::Intern)
|
|
_vGroups.insert(_vGroups.begin(), rDef.GetGroupId());
|
|
else
|
|
_vGroups.push_back(rDef.GetGroupId());
|
|
}
|
|
}
|
|
}
|