From 7e30f3f3cf3c1c7042d4c598d86fc5690eb46ae9 Mon Sep 17 00:00:00 2001 From: Leon Styhre Date: Mon, 16 Jan 2023 17:43:02 +0100 Subject: [PATCH] Improved the symlink loop detection on application startup. --- es-app/src/SystemData.cpp | 41 +++++++++++++++++++++++++++++++-------- es-app/src/SystemData.h | 1 + 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/es-app/src/SystemData.cpp b/es-app/src/SystemData.cpp index e35136b35..82019211f 100644 --- a/es-app/src/SystemData.cpp +++ b/es-app/src/SystemData.cpp @@ -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; } } diff --git a/es-app/src/SystemData.h b/es-app/src/SystemData.h index 8edb6d786..41b0e4011 100644 --- a/es-app/src/SystemData.h +++ b/es-app/src/SystemData.h @@ -153,6 +153,7 @@ private: std::string mThemeFolder; std::shared_ptr mTheme; + bool mSymlinkMaxDepthReached; bool mIsCollectionSystem; bool mIsCustomCollectionSystem; bool mIsGroupedCustomCollectionSystem;