diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2023-06-05 15:43:12 +0200 |
---|---|---|
committer | Eelco Dolstra <edolstra@gmail.com> | 2023-06-06 11:24:10 +0200 |
commit | f5c6b299407e2ad5d05670bf4e89e18ebb113070 (patch) | |
tree | d937cc46b6cbdf4785839574c94c8feb8466dc88 /src/libfetchers | |
parent | 9c6ede85fc3cd822b5c6b56045ff231a61fcd55f (diff) |
Fix SourcePath::resolveSymlinks()
This fixes handling of symlinks that start with '..', and symlink
targets that contain symlinks themselves.
Diffstat (limited to 'src/libfetchers')
-rw-r--r-- | src/libfetchers/input-accessor.cc | 30 |
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, "/")); + } } } |