FSInputAccessor: Implement filtering

This commit is contained in:
Eelco Dolstra 2022-02-16 20:59:56 +01:00
parent 3ec83565b1
commit 38c665847a
2 changed files with 37 additions and 6 deletions

View file

@ -90,10 +90,19 @@ void InputAccessor::dumpPath(
struct FSInputAccessor : InputAccessor struct FSInputAccessor : InputAccessor
{ {
Path root; Path root;
std::optional<PathSet> allowedPaths;
FSInputAccessor(const Path & root) FSInputAccessor(const Path & root, std::optional<PathSet> && allowedPaths)
: root(root) : root(root)
{ } , allowedPaths(allowedPaths)
{
if (allowedPaths) {
for (auto & p : *allowedPaths) {
assert(!hasPrefix(p, "/"));
assert(!hasSuffix(p, "/"));
}
}
}
std::string readFile(PathView path) override std::string readFile(PathView path) override
{ {
@ -139,7 +148,8 @@ struct FSInputAccessor : InputAccessor
case DT_LNK: type = Type::tSymlink; break; case DT_LNK: type = Type::tSymlink; break;
case DT_DIR: type = Type::tDirectory; break; case DT_DIR: type = Type::tDirectory; break;
} }
res.emplace(entry.name, type); if (isAllowed(absPath + "/" + entry.name))
res.emplace(entry.name, type);
} }
return res; return res;
} }
@ -161,6 +171,8 @@ struct FSInputAccessor : InputAccessor
void checkAllowed(PathView absPath) void checkAllowed(PathView absPath)
{ {
if (!isAllowed(absPath)) if (!isAllowed(absPath))
// FIXME: for Git trees, show a custom error message like
// "file is not under version control or does not exist"
throw Error("access to path '%s' is not allowed", absPath); throw Error("access to path '%s' is not allowed", absPath);
} }
@ -168,13 +180,30 @@ struct FSInputAccessor : InputAccessor
{ {
if (!isDirOrInDir(absPath, root)) if (!isDirOrInDir(absPath, root))
return false; return false;
if (allowedPaths) {
// FIXME: make isDirOrInDir return subPath
auto subPath = absPath.substr(root.size());
if (hasPrefix(subPath, "/"))
subPath = subPath.substr(1);
if (subPath != "") {
auto lb = allowedPaths->lower_bound((std::string) subPath);
if (lb == allowedPaths->end()
|| !isDirOrInDir("/" + *lb, "/" + (std::string) subPath))
return false;
}
}
return true; return true;
} }
}; };
ref<InputAccessor> makeFSInputAccessor(const Path & root) ref<InputAccessor> makeFSInputAccessor(
const Path & root,
std::optional<PathSet> && allowedPaths)
{ {
return make_ref<FSInputAccessor>(root); return make_ref<FSInputAccessor>(root, std::move(allowedPaths));
} }
std::ostream & operator << (std::ostream & str, const SourcePath & path) std::ostream & operator << (std::ostream & str, const SourcePath & path)

View file

@ -44,7 +44,9 @@ struct InputAccessor
PathFilter & filter = defaultPathFilter); PathFilter & filter = defaultPathFilter);
}; };
ref<InputAccessor> makeFSInputAccessor(const Path & root); ref<InputAccessor> makeFSInputAccessor(
const Path & root,
std::optional<PathSet> && allowedPaths = {});
struct MemoryInputAccessor : InputAccessor struct MemoryInputAccessor : InputAccessor
{ {