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)
53 lines
1.9 KiB
Diff
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;
|