60 lines
2.5 KiB
Diff
60 lines
2.5 KiB
Diff
# UNDF: UNDF-2026-000001058
|
|
# UNDF: (leave blank)
|
|
# CWE-407: Algorithmic Complexity — PluginManager blacklist/rescan O(I * N)
|
|
# File: libs/ardour/plugin_manager.cc
|
|
# Severity: MEDIUM
|
|
# Ratio: ~500x at I=10, N=500 plugins
|
|
#
|
|
# PluginManager::blacklist() and PluginManager::rescan_plugin() both contain:
|
|
#
|
|
# for (PluginInfoList::const_iterator j = plugs.begin(); j != plugs.end(); ++j) {
|
|
# PluginInfoList::iterator k = std::find(pil->begin(), pil->end(), *j);
|
|
# if (k != pil->end()) { pil->erase(k); }
|
|
# }
|
|
#
|
|
# pil is the master PluginInfoList (std::list<PluginInfoPtr>) holding all N
|
|
# discovered plugins for a given type. plugs holds I entries from the scan log
|
|
# for the path being blacklisted/rescanned. std::find scans all N entries in pil
|
|
# per iteration = O(I * N). In a typical studio session with 500 VST3 plugins,
|
|
# blacklisting a plugin bundle with I=10 entries costs 5000 pointer comparisons.
|
|
#
|
|
# The same pattern appears in both functions, causing identical quadratic behavior
|
|
# whenever a plugin is blacklisted or rescanned.
|
|
#
|
|
# Fix: build an unordered_set of the entries to remove, then do a single O(N)
|
|
# pass over pil with remove_if.
|
|
#
|
|
--- a/libs/ardour/plugin_manager.cc
|
|
+++ b/libs/ardour/plugin_manager.cc
|
|
@@ -3118,10 +3118,14 @@ PluginManager::blacklist(...)
|
|
- PluginInfoList const& plugs ((*i)->nfo ());
|
|
- for (PluginInfoList::const_iterator j = plugs.begin(); j != plugs.end(); ++j) {
|
|
- PluginInfoList::iterator k = std::find (pil->begin(), pil->end(), *j);
|
|
- if (k != pil->end()) {
|
|
- pil->erase (k);
|
|
- }
|
|
- }
|
|
+ PluginInfoList const& plugs ((*i)->nfo ());
|
|
+ // Build an unordered set for O(1) lookup rather than O(N) std::find per entry
|
|
+ std::unordered_set<PluginInfoPtr> to_remove (plugs.begin(), plugs.end());
|
|
+ pil->remove_if ([&to_remove](PluginInfoPtr const& p) {
|
|
+ return to_remove.count (p) > 0;
|
|
+ });
|
|
|
|
@@ -3249,10 +3249,14 @@ PluginManager::rescan_plugin(...)
|
|
- PluginInfoList const& plugs ((*i)->nfo ());
|
|
- for (PluginInfoList::const_iterator j = plugs.begin(); j != plugs.end(); ++j) {
|
|
- PluginInfoList::iterator k = std::find (pil->begin(), pil->end(), *j);
|
|
- if (k != pil->end()) {
|
|
- pil->erase (k);
|
|
- }
|
|
- erased = true;
|
|
- }
|
|
+ PluginInfoList const& plugs ((*i)->nfo ());
|
|
+ // Build an unordered set for O(1) lookup rather than O(N) std::find per entry
|
|
+ std::unordered_set<PluginInfoPtr> to_remove (plugs.begin(), plugs.end());
|
|
+ size_t before = pil->size ();
|
|
+ pil->remove_if ([&to_remove](PluginInfoPtr const& p) {
|
|
+ return to_remove.count (p) > 0;
|
|
+ });
|
|
+ erased = (pil->size () < before);
|