java-topology/defects/libtorrent/patch/libtorrent-0001-file-storage-get-or-add-path-linear-dedup.patch
russell@unturf.com 0b5409ff95 libtorrent-0001/qbittorrent: CWE-407 scan — 1 defect, 1 CLEAN
libtorrent-0001: file_storage::get_or_add_path std::find on m_paths vector O(F*P) MEDIUM 250x
qBittorrent: CLEAN (QSet/QHash throughout for membership tests)
2026-03-30 10:39:32 -04:00

53 lines
1.9 KiB
Diff

# UNDF: UNDF-2026-000000777
# UNDF: (leave blank)
# CWE-407: file_storage::get_or_add_path uses std::find on m_paths vector O(F*P)
#
# file_storage::get_or_add_path() is called once per file added to a torrent.
# For each call it does a linear scan of m_paths (vector<string>) to check for
# duplicate directory paths. For a torrent with F files and P unique paths, the
# total cost of building the file_storage is O(F*P).
#
# Large torrents with 50,000+ files across hundreds of directories hit this on
# every .torrent parse and metadata exchange. At P=500, F=50000, that's 25M
# string comparisons.
#
# Fix: maintain an unordered_map<string, path_index_t> alongside m_paths for
# O(1) lookup. The vector is retained for index-based access.
#
# Severity: MEDIUM (torrent load/parse path, not per-packet)
# Speedup: ~250x at P=500
--- a/src/file_storage.cpp
+++ b/src/file_storage.cpp
@@ -210,7 +210,7 @@
aux::path_index_t file_storage::get_or_add_path(string_view const path)
{
- // do we already have this path in the path list?
- auto const p = std::find(m_paths.rbegin(), m_paths.rend(), path);
+ // O(1) lookup via hash map instead of O(P) linear scan
+ auto const it = m_path_index.find(std::string(path));
- if (p == m_paths.rend())
+ if (it == m_path_index.end())
{
// no, we don't. add it
auto const ret = m_paths.end_index();
TORRENT_ASSERT(path.size() == 0 || path[0] != '/');
m_paths.emplace_back(path.data(), path.size());
+ m_path_index.emplace(std::string(path), ret);
return ret;
}
else
{
- // yes we do. use it
- return aux::path_index_t{aux::numeric_cast<std::uint32_t>(
- p.base() - m_paths.begin() - 1)};
+ return it->second;
}
}
--- a/include/libtorrent/file_storage.hpp
+++ b/include/libtorrent/file_storage.hpp
@@ (add to private members, near m_paths declaration)
+ // O(1) path deduplication index (path string -> path_index_t)
+ std::unordered_map<std::string, aux::path_index_t> m_path_index;