fix: issue 2631 (#2633)

problem occurs because there is no check for duplicate entries in the
paths vector.

The fix is implemented using the combination of two containers; a vector
to ensure the insertion order and a set to ensure the uniqueness the
entries. The set first attempts to insert the new path and uses the
return of insertion to decide if the vector needs to be updated.
This commit is contained in:
paxcut
2026-01-28 16:12:36 -07:00
committed by GitHub
parent fc38c27769
commit d6781e7f93

View File

@@ -5,6 +5,7 @@
#include <hex/api/project_file_manager.hpp> #include <hex/api/project_file_manager.hpp>
#include <ranges> #include <ranges>
#include <set>
#if defined(OS_WINDOWS) #if defined(OS_WINDOWS)
#include <windows.h> #include <windows.h>
@@ -17,6 +18,13 @@ namespace hex::paths {
std::vector<std::fs::path> getDataPaths(bool includeSystemFolders) { std::vector<std::fs::path> getDataPaths(bool includeSystemFolders) {
std::vector<std::fs::path> paths; std::vector<std::fs::path> paths;
std::set<std::fs::path> uniquePaths;
const auto emplaceUniquePath = [&](const std::fs::path &path) {
auto duplicate = uniquePaths.insert(path);
if (duplicate.second)
paths.emplace_back(path);
};
#if defined(OS_WINDOWS) #if defined(OS_WINDOWS)
@@ -25,21 +33,22 @@ namespace hex::paths {
if (!ImHexApi::System::isPortableVersion()) { if (!ImHexApi::System::isPortableVersion()) {
PWSTR wAppDataPath = nullptr; PWSTR wAppDataPath = nullptr;
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &wAppDataPath))) { if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &wAppDataPath))) {
paths.emplace_back(wAppDataPath); emplaceUniquePath(wAppDataPath);
CoTaskMemFree(wAppDataPath); CoTaskMemFree(wAppDataPath);
} }
} }
#elif defined(OS_MACOS) #elif defined(OS_MACOS)
paths.push_back(wolv::io::fs::getApplicationSupportDirectoryPath() / "imhex"); emplaceUniquePath(wolv::io::fs::getApplicationSupportDirectoryPath() / "imhex");
#elif defined(OS_LINUX) || defined(OS_WEB) #elif defined(OS_LINUX) || defined(OS_WEB)
paths.push_back(xdg::DataHomeDir()); emplaceUniquePath(xdg::DataHomeDir());
auto dataDirs = xdg::DataDirs(); auto dataDirs = xdg::DataDirs();
std::ranges::copy(dataDirs, std::back_inserter(paths)); for (const auto &path : dataDirs)
emplaceUniquePath(path);
#endif #endif
@@ -47,18 +56,21 @@ namespace hex::paths {
if (includeSystemFolders) { if (includeSystemFolders) {
if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value()) { if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value()) {
paths.push_back(executablePath->parent_path()); emplaceUniquePath(executablePath->parent_path());
} }
} }
#else #else
for (auto &path : paths) uniquePaths.clear();
for (auto &path : paths) {
path = path / "imhex"; path = path / "imhex";
uniquePaths.insert(path);
}
if (ImHexApi::System::isPortableVersion() || includeSystemFolders) { if (ImHexApi::System::isPortableVersion() || includeSystemFolders) {
if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value()) if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value())
paths.push_back(executablePath->parent_path()); emplaceUniquePath(executablePath->parent_path());
} }
#endif #endif
@@ -66,11 +78,12 @@ namespace hex::paths {
// Add additional data directories to the path // Add additional data directories to the path
auto additionalDirs = ImHexApi::System::getAdditionalFolderPaths(); auto additionalDirs = ImHexApi::System::getAdditionalFolderPaths();
std::ranges::copy(additionalDirs, std::back_inserter(paths)); for (const auto &path : additionalDirs)
emplaceUniquePath(path);
// Add the project file directory to the path, if one is loaded // Add the project file directory to the path, if one is loaded
if (ProjectFile::hasPath()) { if (ProjectFile::hasPath()) {
paths.push_back(ProjectFile::getPath().parent_path()); emplaceUniquePath(ProjectFile::getPath().parent_path());
} }
return paths; return paths;