java-topology/defects/libreoffice/patch/libreoffice-0005-outlview-selectedparas-linear-scan.patch

45 lines
1.8 KiB
Diff

# UNDF: UNDF-2026-000000790
# UNDF: (leave blank)
# LibreOffice CWE-407: OutlineView selected paragraphs O(P*S) linear scan
#
# In sd/source/ui/view/outlview.cxx, two methods scan maSelectedParas
# (a vector) via std::find() inside a while-loop over all paragraphs:
#
# 1. BeginMovingHdl (line 1003): for each page-paragraph, std::find in
# maSelectedParas to determine selection state — O(P*S)
# 2. SetSelectedPages (line 1476): same pattern — O(P*S)
#
# Where P = total paragraphs, S = selected paragraphs.
#
# Fix: build an unordered_set from maSelectedParas before the loop
# for O(1) membership test.
#
# Severity: MEDIUM — Impress presentations with hundreds of slides
# trigger this during slide reordering and selection operations.
# At P=500, S=100: 50,000 comparisons reduced to 500.
--- a/sd/source/ui/view/outlview.cxx
+++ b/sd/source/ui/view/outlview.cxx
@@ -990,6 +990,8 @@
// select the pages belonging to the paragraphs on level 0 to select
sal_uInt16 nPos = 0;
sal_Int32 nParaPos = 0;
Paragraph* pPara = pOutliner->GetParagraph( 0 );
- std::vector<Paragraph*>::const_iterator fiter;
+ // Build set for O(1) lookup instead of O(S) linear scan per paragraph
+ std::unordered_set<Paragraph*> aSelectedSet(maSelectedParas.begin(),
+ maSelectedParas.end());
while(pPara)
{
if( ::Outliner::HasParaFlag(pPara, ParaFlag::ISPAGE) ) // one page?
{
maOldParaOrder.push_back(pPara);
SdPage* pPage = mrDoc.GetSdPage(nPos, PageKind::Standard);
- fiter = std::find(maSelectedParas.begin(),maSelectedParas.end(),pPara);
-
- pPage->SetSelected(fiter != maSelectedParas.end());
+ pPage->SetSelected(aSelectedSet.count(pPara) > 0);
++nPos;
}