summaryrefslogtreecommitdiff
path: root/src/buildtool
diff options
context:
space:
mode:
authorPaul Cristian Sarbu <paul.cristian.sarbu@huawei.com>2025-05-16 17:30:39 +0200
committerPaul Cristian Sarbu <paul.cristian.sarbu@huawei.com>2025-06-04 14:34:44 +0200
commit3a4dc9753561c70af7a939e5f3d729d8accc52f9 (patch)
tree5e17d77df5af5b1bb7e0bc612af3278b2faf6f88 /src/buildtool
parentd5177881b4df769afcf18ca803f6c2f153285207 (diff)
downloadjustbuild-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.cpp48
-rw-r--r--src/buildtool/execution_api/local/local_cas_reader.hpp8
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_;