Prevent infinite symlink loop in followLinksToStore()
The followLinksToStore() function could hang indefinitely when encountering symlink cycles outside the Nix store, causing 100% CPU usage and blocking any operations that use this function. This affects multiple commands including nix-store --query, --delete, --verify, nix-env, and nix-copy-closure when given paths with symlink cycles. The fix adds a maximum limit of 1024 symlink follows (matching the limit used by canonPath) and throws an error when exceeded, preventing the infinite loop while preserving the original semantics of stopping at the first path inside the store.
This commit is contained in:
@@ -58,12 +58,22 @@ std::pair<StorePath, Path> StoreDirConfig::toStorePath(PathView path) const
|
||||
Path Store::followLinksToStore(std::string_view _path) const
|
||||
{
|
||||
Path path = absPath(std::string(_path));
|
||||
|
||||
// Limit symlink follows to prevent infinite loops
|
||||
unsigned int followCount = 0;
|
||||
const unsigned int maxFollow = 1024;
|
||||
|
||||
while (!isInStore(path)) {
|
||||
if (!std::filesystem::is_symlink(path))
|
||||
break;
|
||||
|
||||
if (++followCount >= maxFollow)
|
||||
throw Error("too many symbolic links encountered while resolving '%s'", _path);
|
||||
|
||||
auto target = readLink(path);
|
||||
path = absPath(target, dirOf(path));
|
||||
}
|
||||
|
||||
if (!isInStore(path))
|
||||
throw BadStorePath("path '%1%' is not in the Nix store", path);
|
||||
return path;
|
||||
|
||||
Reference in New Issue
Block a user