aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiam Mitchell <[email protected]>2026-01-21 17:43:07 -0800
committerLiam Mitchell <[email protected]>2026-01-21 17:43:07 -0800
commitca3ac81799f5192c96b964c5aacf8ef36efb6adb (patch)
treed5269fd311b1101fa49553df8e5392672cd9dffb
parentRestrict filesystem reads in snapshot to paths under project root (diff)
downloadzen-ca3ac81799f5192c96b964c5aacf8ef36efb6adb.tar.xz
zen-ca3ac81799f5192c96b964c5aacf8ef36efb6adb.zip
Use std::mismatch to compare paths and hoist project root canonicalization out of loop
-rw-r--r--src/zenserver/storage/projectstore/httpprojectstore.cpp31
1 files changed, 18 insertions, 13 deletions
diff --git a/src/zenserver/storage/projectstore/httpprojectstore.cpp b/src/zenserver/storage/projectstore/httpprojectstore.cpp
index 8742ed75f..0ff628d43 100644
--- a/src/zenserver/storage/projectstore/httpprojectstore.cpp
+++ b/src/zenserver/storage/projectstore/httpprojectstore.cpp
@@ -2880,6 +2880,8 @@ HttpProjectService::HandleRpcRequest(HttpRouterRequest& Req)
};
tsl::robin_map<IoHash, AddedChunk, IoHash::Hasher> AddedChunks;
+ const std::filesystem::path CanonicalRoot = std::filesystem::canonical(Project->RootDir);
+
Oplog->IterateOplog(
[&](CbObjectView Op) {
bool OpRewritten = false;
@@ -2898,33 +2900,36 @@ HttpProjectService::HandleRpcRequest(HttpRouterRequest& Req)
if (DataHash == IoHash::Zero)
{
- std::string_view ServerPath = View["serverpath"sv].AsString();
- std::filesystem::path FilePath = Project->RootDir / ServerPath;
- if (!std::filesystem::exists(FilePath))
+ std::string_view ServerPath = View["serverpath"sv].AsString();
+ std::error_code Ec;
+ const std::filesystem::path CanonicalPath =
+ std::filesystem::canonical(Project->RootDir / ServerPath, Ec);
+ if (Ec)
{
- ZEN_WARN("Attempted to read non-existent file '{}' in 'snapshot'", FilePath);
+ ZEN_WARN("Failed to find file '{}' in project root '{}' for 'snapshot'. Reason: '{}'",
+ ServerPath,
+ Project->RootDir,
+ Ec.message());
AllOk = false;
continue;
}
- std::filesystem::path CanonicalRoot = std::filesystem::canonical(Project->RootDir);
-
- if (!std::filesystem::canonical(FilePath).string().starts_with(CanonicalRoot.string()))
+ if (std::mismatch(CanonicalRoot.begin(), CanonicalRoot.end(), CanonicalPath.begin()).first !=
+ CanonicalRoot.end())
{
- ZEN_WARN("Unable to read file '{}' outside of project root '{}'", FilePath, CanonicalRoot);
+ ZEN_WARN("Unable to read file '{}' outside of project root '{}'", CanonicalPath, CanonicalRoot);
AllOk = false;
continue;
}
- BasicFile DataFile;
- std::error_code Ec;
- DataFile.Open(FilePath, BasicFile::Mode::kRead, Ec);
+ BasicFile DataFile;
+ DataFile.Open(CanonicalPath, BasicFile::Mode::kRead, Ec);
if (Ec)
{
// Error...
- ZEN_ERROR("unable to read data from file '{}': {}", FilePath, Ec.message());
+ ZEN_ERROR("unable to read data from file '{}': {}", CanonicalPath, Ec.message());
AllOk = false;
}
@@ -2945,7 +2950,7 @@ HttpProjectService::HandleRpcRequest(HttpRouterRequest& Req)
{
Oid ChunkId = View["id"sv].AsObjectId();
ZEN_ERROR("unable to write external file as compressed chunk '{}', id {}: {}",
- FilePath,
+ CanonicalPath,
ChunkId,
Ec.message());
AllOk = false;