java-topology/defects/audacity/patch/audacity-0002-wavetrack-canoffsetclips-linear.patch

38 lines
1.6 KiB
Diff

# UNDF: UNDF-2026-000000703
# UNDF: (leave blank)
# Audacity CWE-407: WaveTrack::CanOffsetClips() O(I*M) moving clip scan
#
# In au3/libraries/au3-wave-track/WaveTrack.cpp, CanOffsetClips() iterates
# over all intervals and for each one checks whether it's in the movingClips
# vector via std::find(). The source code itself acknowledges this:
# "linear search might be improved, but expecting few moving clips"
#
# This is O(I*M) where I=total intervals (clips) and M=moving clips.
# In projects with many clips per track (podcast editing, sample slicing,
# beat detection results), both I and M can be large.
#
# Fix: build an unordered_set<Interval*> from movingClips before the loop
# for O(1) membership test.
#
# Severity: MEDIUM — triggered during every clip drag/offset operation.
# At I=200 clips, M=50 moving: 10,000 comparisons reduced to 200.
--- a/au3/libraries/au3-wave-track/WaveTrack.cpp
+++ b/au3/libraries/au3-wave-track/WaveTrack.cpp
@@ -3186,10 +3186,9 @@
*allowedAmount = amount;
}
- const auto& moving = [&](Interval* clip){
- // linear search might be improved, but expecting few moving clips
- // compared with the fixed clips
- return movingClips.end()
- != std::find(movingClips.begin(), movingClips.end(), clip);
- };
+ // Use a set for O(1) membership test instead of O(M) linear search
+ std::unordered_set<Interval*> movingSet(movingClips.begin(), movingClips.end());
+ const auto& moving = [&](Interval* clip){
+ return movingSet.count(clip) > 0;
+ };
for (const auto& c: Intervals()) {
if (moving(c.get())) {