Improved the symlink loop detection on application startup.

This commit is contained in:
Leon Styhre 2023-01-16 17:43:02 +01:00
parent cc8dfe20ca
commit 7e30f3f3cf
2 changed files with 34 additions and 8 deletions

View file

@ -196,6 +196,7 @@ SystemData::SystemData(const std::string& name,
, mSortName {sortName}
, mEnvData {envData}
, mThemeFolder {themeFolder}
, mSymlinkMaxDepthReached {false}
, mIsCollectionSystem {CollectionSystem}
, mIsCustomCollectionSystem {CustomCollectionSystem}
, mIsGroupedCustomCollectionSystem {false}
@ -265,6 +266,9 @@ void SystemData::setIsGameSystemStatus()
bool SystemData::populateFolder(FileData* folder)
{
if (mSymlinkMaxDepthReached)
return false;
std::string filePath;
std::string extension;
const std::string& folderPath {folder->getPath()};
@ -345,22 +349,43 @@ bool SystemData::populateFolder(FileData* folder)
// Add directories that also do not match an extension as folders.
if (!isGame && isDirectory) {
// Make sure that it's not a recursive symlink pointing to a location higher in the
// hierarchy as the application would run forever trying to resolve the link.
// Make sure that it's not a recursive symlink as the application would run into a
// loop trying to resolve the link.
if (Utils::FileSystem::isSymlink(filePath)) {
bool recursiveSymlink {false};
const std::string& canonicalPath {Utils::FileSystem::getCanonicalPath(filePath)};
const std::string& canonicalStartPath {
Utils::FileSystem::getCanonicalPath(mEnvData->mStartPath)};
if (canonicalPath.size() >= canonicalStartPath.size()) {
// Last resort hack to prevent recursive symlinks in some really unusual situations.
if (filePath.length() > canonicalStartPath.length() + 100) {
int folderDepth {0};
const std::string& path {filePath.substr(canonicalStartPath.length())};
for (char character : path) {
if (character == '/') {
++folderDepth;
if (folderDepth == 20) {
LOG(LogWarning) << "Skipped \"" << filePath
<< "\" as it seems to be a recursive symlink";
mSymlinkMaxDepthReached = true;
return false;
}
}
}
}
if (canonicalStartPath.find(canonicalPath) != std::string::npos)
recursiveSymlink = true;
else if (canonicalPath.size() >= canonicalStartPath.size() &&
canonicalPath.find(canonicalStartPath) != std::string::npos) {
const std::string& combinedPath {
mEnvData->mStartPath +
canonicalPath.substr(canonicalStartPath.size(),
canonicalStartPath.size() - canonicalPath.size())};
if (filePath.find(combinedPath) == 0) {
LOG(LogWarning)
<< "Skipped \"" << filePath << "\" as it's a recursive symlink";
continue;
if (Utils::FileSystem::getParent(filePath).find(combinedPath) == 0)
recursiveSymlink = true;
}
if (recursiveSymlink) {
LOG(LogWarning) << "Skipped \"" << filePath << "\" as it's a recursive symlink";
continue;
}
}

View file

@ -153,6 +153,7 @@ private:
std::string mThemeFolder;
std::shared_ptr<ThemeData> mTheme;
bool mSymlinkMaxDepthReached;
bool mIsCollectionSystem;
bool mIsCustomCollectionSystem;
bool mIsGroupedCustomCollectionSystem;