java-topology/defects/krita-0001/TICKET.md
russell@unturf.com 7ecd95c4d6 kdenlive+audacity: 5-MOAD rescan; kdenlive-0010 CWE-407 checkConsistency QList::contains O(P*K^2) 500x at K=1000; audacity CLEAN rescan confirmed
kdenlive-0010: KeyframeModelList::checkConsistency() in
src/assets/keyframes/model/keyframemodellist.cpp calls QList<GenTime>::contains()
inside nested loops — O(P*K^2) at clip load for multi-parameter keyframe effects.
Fix: std::set<GenTime> using operator< for O(log K) insert/lookup in both phases.
Speedup: 50x at K=100, 250x at K=500, 500x at K=1000 (P=3 params). 12/12 PASS.

Audacity: full 5-MOAD rescan on fresh clone confirms prior scan results.
No new defects. MOADs 0002/0003/0004/0005 CLEAN.
2026-04-03 14:50:10 -04:00

1.6 KiB

krita-0001 — NodeDelegate togglePropertyRecursive O(N²) QList::contains

Summary

NodeDelegate::Private::togglePropertyRecursive iterates over every node in our layer tree and calls items.contains(idx) on a QList<QModelIndex>. Our items list is built by getChildrenIndex (all descendants) or getParentsIndex + siblings, so it can contain O(N) entries. The recursive traversal visits all N nodes. Total work: O(N²) per shift-click on any visibility or lock property icon.

Location

plugins/dockers/layerdocker/NodeDelegate.cpp

  • togglePropertyRecursive (line ~576): items.contains(idx) inside for-loop that recurses into all children
  • toggleProperty (line ~541): builds items via getChildrenIndex / getParentsIndex

Severity

MEDIUM. Triggered on every shift-click of visibility/lock/alpha-lock in our layer panel. For N=200 layers with items size ~180, this is ~36,000 comparisons per click vs ~380 with a QSet.

Complexity

Before After
O(N²) QList::contains per shift-click O(N) QSet::contains per shift-click

Fix

Convert items from QList<QModelIndex> to QSet<QModelIndex> before passing to togglePropertyRecursive. QModelIndex is hashable in Qt (qHash is defined).

// In toggleProperty, before calling togglePropertyRecursive:
QSet<QModelIndex> itemsSet(items.begin(), items.end());
togglePropertyRecursive(root, clickedProperty, itemsSet, record, mode);

Change togglePropertyRecursive signature to accept const QSet<QModelIndex> &items.

References

  • CWE-407: Inefficient Algorithmic Complexity
  • MOAD-0001: The Sedimentary Defect