# UNDF: UNDF-2026-000000802 # UNDF: (leave blank) # scribus-0001: getSortedStyleList retList.contains O(N²) dedup # # In scribus/scribusdoc.cpp, four identical functions — getSortedStyleList(), # getSortedCharStyleList(), getSortedTableStyleList(), getSortedCellStyleList() # — walk the style parent chain and accumulate indices into retList using # QList::contains() to dedup. QList::contains is O(N) per call, and the # outer loop is O(N) over all styles, making overall complexity O(N²). # # Additionally, the inner while-loop walking up the parent chain accumulates # into retList2 with retList2.contains(pp) — a minor O(depth²) per style. # # For a document with N=500 paragraph styles (plausible in long-form publishing # with inherited house styles), this is ~125,000 linear scans instead of ~500 # hash lookups. # # Fix: maintain a companion QSet for O(1) membership test alongside the # ordered QList retList. # # Severity: MEDIUM — 4 identical defect sites; triggered on style # reorder/display; scales with style count. --- a/scribus/scribusdoc.cpp +++ b/scribus/scribusdoc.cpp @@ -1198,6 +1198,7 @@ QList ScribusDoc::getSortedStyleList() const { QList retList; + QSet retSet; for (int i = 0; i < m_docParagraphStyles.count(); ++i) { if (m_docParagraphStyles[i].parent().isEmpty()) { - if (!retList.contains(i)) + if (!retSet.contains(i)) + { retList.append(i); + retSet.insert(i); + } continue; } QList retList2; + QSet retSet2; ... retList2.prepend(i); + retSet2.insert(i); while ((!par.isEmpty()) && (par != name)) { int pp = m_docParagraphStyles.find(par); - if ((pp >= 0) && (!retList2.contains(pp))) + if ((pp >= 0) && (!retSet2.contains(pp))) + { retList2.prepend(pp); + retSet2.insert(pp); + } par = (pp >= 0) ? m_docParagraphStyles[pp].parent() : QString(); } for (int r = 0; r < retList2.count(); ++r) { - if (!retList.contains(retList2[r])) + if (!retSet.contains(retList2[r])) + { retList.append(retList2[r]); + retSet.insert(retList2[r]); + } } } return retList; } // Same fix applies identically to: // getSortedCharStyleList() (line 1230) // getSortedTableStyleList() (line 1262) // getSortedCellStyleList() (line 1294)