aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2023-06-05 15:43:12 +0200
committerEelco Dolstra <edolstra@gmail.com>2023-06-06 11:24:10 +0200
commitf5c6b299407e2ad5d05670bf4e89e18ebb113070 (patch)
treed937cc46b6cbdf4785839574c94c8feb8466dc88 /src
parent9c6ede85fc3cd822b5c6b56045ff231a61fcd55f (diff)
Fix SourcePath::resolveSymlinks()
This fixes handling of symlinks that start with '..', and symlink targets that contain symlinks themselves.
Diffstat (limited to 'src')
-rw-r--r--src/libfetchers/input-accessor.cc30
1 files changed, 18 insertions, 12 deletions
diff --git a/src/libfetchers/input-accessor.cc b/src/libfetchers/input-accessor.cc
index f9909c218..f37a8058b 100644
--- a/src/libfetchers/input-accessor.cc
+++ b/src/libfetchers/input-accessor.cc
@@ -75,22 +75,28 @@ SourcePath SourcePath::resolveSymlinks() const
int linksAllowed = 1024;
- for (auto & component : path) {
- res.path.push(component);
- while (true) {
- if (auto st = res.maybeLstat()) {
+ std::list<std::string> todo;
+ for (auto & c : path)
+ todo.push_back(std::string(c));
+
+ while (!todo.empty()) {
+ auto c = *todo.begin();
+ todo.pop_front();
+ if (c == "" || c == ".")
+ ;
+ else if (c == "..")
+ res.path.pop();
+ else {
+ res.path.push(c);
+ if (auto st = res.maybeLstat(); st && st->type == InputAccessor::tSymlink) {
if (!linksAllowed--)
throw Error("infinite symlink recursion in path '%s'", path);
- if (st->type != InputAccessor::tSymlink) break;
auto target = res.readLink();
+ res.path.pop();
if (hasPrefix(target, "/"))
- res = CanonPath(target);
- else {
- res.path.pop();
- res.path.extend(CanonPath(target));
- }
- } else
- break;
+ res.path = CanonPath::root;
+ todo.splice(todo.begin(), tokenizeString<std::list<std::string>>(target, "/"));
+ }
}
}