diff options
| author | Liam Mitchell <[email protected]> | 2026-01-21 17:43:07 -0800 |
|---|---|---|
| committer | Liam Mitchell <[email protected]> | 2026-01-21 17:43:07 -0800 |
| commit | ca3ac81799f5192c96b964c5aacf8ef36efb6adb (patch) | |
| tree | d5269fd311b1101fa49553df8e5392672cd9dffb | |
| parent | Restrict filesystem reads in snapshot to paths under project root (diff) | |
| download | zen-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.cpp | 31 |
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; |