# UNDF: UNDF-2026-000000112 # UNDF: (leave blank) # Audacity CWE-407: TrackeditActionsController selectedTracks O(T*S) linear scan # # In src/trackedit/internal/trackeditactionscontroller.cpp, at least 7 # methods iterate over all tracks and for each track perform # std::find(selectedTracks.begin(), selectedTracks.end(), track.id) to # check if the track is selected. This is O(T*S) per method call where # T=total tracks and S=selected tracks. # # Affected methods (all with identical pattern): # - multiClipCopy() line 965 # - multiClipCut_copy_part() line 1036 # - rangeSelectionCopy() line 1062 # - splitStereoToLRMono() line 1466 # - splitStereoToCenter() line 1491 # - trimAudioOutsideSelection() line 1511 # - silenceAudioSelection() line 1535 # # Fix: convert selectedTracks (TrackIdList/std::vector) to an # unordered_set before the loop for O(1) membership test per track. # # Severity: MEDIUM — projects with hundreds of tracks (podcast # multitrack, film scoring, large orchestral templates) hit this # on every copy/cut/split/trim/silence operation. # At T=200, S=50: 10,000 comparisons per op reduced to 200. --- a/src/trackedit/internal/trackeditactionscontroller.cpp +++ b/src/trackedit/internal/trackeditactionscontroller.cpp @@ -958,8 +958,9 @@ secs_t offset = 0.0; // ... + std::unordered_set selectedSet(selectedTracks.begin(), selectedTracks.end()); for (const auto& track : tracks) { - if (std::find(selectedTracks.begin(), selectedTracks.end(), track.id) == selectedTracks.end()) { + if (selectedSet.find(track.id) == selectedSet.end()) { continue; } // ... (same fix applied to all 7 loop instances) }