38 lines
1.6 KiB
Diff
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())) {
|