diff options
author | Paul Cristian Sarbu <paul.cristian.sarbu@huawei.com> | 2025-05-16 17:30:39 +0200 |
---|---|---|
committer | Paul Cristian Sarbu <paul.cristian.sarbu@huawei.com> | 2025-06-04 14:34:44 +0200 |
commit | 3a4dc9753561c70af7a939e5f3d729d8accc52f9 (patch) | |
tree | 5e17d77df5af5b1bb7e0bc612af3278b2faf6f88 /src/buildtool | |
parent | d5177881b4df769afcf18ca803f6c2f153285207 (diff) | |
download | justbuild-3a4dc9753561c70af7a939e5f3d729d8accc52f9.tar.gz |
LocalCasReader: Add validity check for bazel directories
This will check if directories contain upwards symlinks.
Diffstat (limited to 'src/buildtool')
-rw-r--r-- | src/buildtool/execution_api/local/local_cas_reader.cpp | 48 | ||||
-rw-r--r-- | src/buildtool/execution_api/local/local_cas_reader.hpp | 8 |
2 files changed, 54 insertions, 2 deletions
diff --git a/src/buildtool/execution_api/local/local_cas_reader.cpp b/src/buildtool/execution_api/local/local_cas_reader.cpp index 9af9650a..d3b08d14 100644 --- a/src/buildtool/execution_api/local/local_cas_reader.cpp +++ b/src/buildtool/execution_api/local/local_cas_reader.cpp @@ -18,6 +18,7 @@ #include <compare> #include <cstddef> #include <deque> +#include <exception> #include <memory> #include <stack> #include <type_traits> @@ -25,8 +26,8 @@ #include <utility> #include <vector> +#include "fmt/core.h" #include "google/protobuf/repeated_ptr_field.h" -#include "gsl/gsl" #include "src/buildtool/common/artifact_digest_factory.hpp" #include "src/buildtool/common/protocol_traits.hpp" #include "src/buildtool/crypto/hash_function.hpp" @@ -35,7 +36,6 @@ #include "src/buildtool/file_system/object_type.hpp" #include "src/buildtool/logging/log_level.hpp" #include "src/buildtool/logging/logger.hpp" -#include "src/utils/cpp/expected.hpp" #include "src/utils/cpp/incremental_reader.hpp" #include "src/utils/cpp/path.hpp" @@ -180,6 +180,50 @@ auto LocalCasReader::IsNativeProtocol() const noexcept -> bool { return ProtocolTraits::IsNative(cas_.GetHashFunction().GetType()); } +auto LocalCasReader::IsDirectoryValid(ArtifactDigest const& digest) + const noexcept -> expected<bool, std::string> { + try { + auto const hash_type = cas_.GetHashFunction().GetType(); + // read directory + if (auto const path = cas_.TreePath(digest)) { + if (auto const content = FileSystemManager::ReadFile(*path)) { + auto dir = + BazelMsgFactory::MessageFromString<bazel_re::Directory>( + *content); + // check symlinks + for (auto const& l : dir->symlinks()) { + if (not PathIsNonUpwards(l.target())) { + return false; + } + } + // traverse subdirs + for (auto const& d : dir->directories()) { + auto subdir_digest = + ArtifactDigestFactory::FromBazel(hash_type, d.digest()); + if (not subdir_digest) { + return unexpected{std::move(subdir_digest).error()}; + } + auto subdir_result = + IsDirectoryValid(*std::move(subdir_digest)); + if (not subdir_result) { + return unexpected{std::move(subdir_result).error()}; + } + if (not std::move(subdir_result).value()) { + return false; + } + } + return true; + } + } + return unexpected{ + fmt::format("Directory {} not found in CAS", digest.hash())}; + } catch (std::exception const& ex) { + return unexpected{fmt::format( + "An error occurred checking validity of bazel directory:\n{}", + ex.what())}; + } +} + namespace { [[nodiscard]] auto AssembleTree( bazel_re::Directory root, diff --git a/src/buildtool/execution_api/local/local_cas_reader.hpp b/src/buildtool/execution_api/local/local_cas_reader.hpp index 090aa9d1..3ac47f64 100644 --- a/src/buildtool/execution_api/local/local_cas_reader.hpp +++ b/src/buildtool/execution_api/local/local_cas_reader.hpp @@ -26,6 +26,7 @@ #include "src/buildtool/common/bazel_types.hpp" #include "src/buildtool/file_system/git_repo.hpp" #include "src/buildtool/storage/local_cas.hpp" +#include "src/utils/cpp/expected.hpp" class LocalCasReader final { public: @@ -58,6 +59,13 @@ class LocalCasReader final { [[nodiscard]] auto IsNativeProtocol() const noexcept -> bool; + /// \brief Check recursively if Directory contains any invalid entries + /// (i.e., upwards symlinks). + /// \returns True if Directory is ok, false if at least on upwards symlink + /// has been found, error message on other failures. + [[nodiscard]] auto IsDirectoryValid(ArtifactDigest const& digest) + const noexcept -> expected<bool, std::string>; + private: LocalCAS<true> const& cas_; |