| // Copyright 2022 The Centipede Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef THIRD_PARTY_CENTIPEDE_WORKDIR_MGR_H_ |
| #define THIRD_PARTY_CENTIPEDE_WORKDIR_MGR_H_ |
| |
| #include <cstddef> |
| #include <optional> |
| #include <ostream> |
| #include <string> |
| #include <string_view> |
| #include <vector> |
| |
| #include "./centipede/environment.h" |
| #include "./common/logging.h" |
| |
| namespace fuzztest::internal { |
| |
| // The Centipede work directory manager. |
| class WorkDir { |
| public: |
| // Min number of decimal digits in a shard index given `total_shards`. Used to |
| // pad indices with 0's in output file names so the names are sorted by index. |
| static constexpr int kDigitsInShardIndex = 6; |
| |
| // Provides APIs for getting shards of a sharded path. |
| class PathShards { |
| public: |
| // Returns the path of the shard for `shard_index`. |
| std::string Shard(size_t shard_index) const; |
| // Returns the path of the shard for `my_shard_index_`. |
| std::string MyShard() const; |
| // Returns a glob matching all the shards. |
| std::string AllShardsGlob() const; |
| // Returns true if `path` looks like a shard path from this set. Matching is |
| // purely lexicographical: the actual path doesn't have to exist on disk, |
| // but `path` must have the exact `base_dir`/`rel_prefix` prefix, |
| // including any relative "." and ".." path elements. |
| bool IsShard(std::string_view path) const; |
| // Returns the shard index of `path` if it is a shard parth, `nullopt` |
| // otherwise. |
| std::optional<size_t> GetShardIndex(std::string_view path) const; |
| |
| private: |
| friend class WorkDir; |
| |
| PathShards(std::string_view base_dir, std::string_view rel_prefix, |
| size_t my_shard_index); |
| |
| const std::string prefix_; |
| const size_t my_shard_index_; |
| }; |
| |
| // Deduces the workdir properties from a provided corpus shard path and |
| // coverage binary basename and hash. |
| static WorkDir FromCorpusShardPath( // |
| std::string_view corpus_shard_path, // |
| std::string_view binary_name, // |
| std::string_view binary_hash); |
| |
| // Constructs an object from directly provided field values. |
| WorkDir( // |
| std::string_view workdir, // |
| std::string_view binary_name, // |
| std::string_view binary_hash, // |
| size_t my_shard_index); |
| |
| // Constructs an object by recording referenced to the field values in the |
| // passed `env` object. NOTE: `env` must outlive this object. |
| explicit WorkDir(const fuzztest::internal::Environment &env); |
| |
| // Not copyable and not assignable due to dual nature of the reference |
| // members (that reference either the internal value holders or an external |
| // `Environment`'s members). |
| WorkDir(const WorkDir &) = delete; |
| WorkDir &operator=(const WorkDir &) = delete; |
| WorkDir(WorkDir&&) noexcept = delete; |
| WorkDir& operator=(WorkDir&&) noexcept = delete; |
| |
| // Comparisons and debugging I/O (mainly for tests). |
| friend bool operator==(const WorkDir &a, const WorkDir &b) { |
| return a.workdir_ == b.workdir_ && a.binary_name_ == b.binary_name_ && |
| a.binary_hash_ == b.binary_hash_ && |
| a.my_shard_index_ == b.my_shard_index_; |
| } |
| friend bool operator!=(const WorkDir &a, const WorkDir &b) { |
| return !(a == b); |
| } |
| friend std::ostream &operator<<(std::ostream &os, const WorkDir &wd) { |
| return os << VV(wd.workdir_) << VV(wd.binary_name_) << VV(wd.binary_hash_) |
| << VV(wd.my_shard_index_); |
| } |
| |
| // Returns the path to a dir for dumping debug configs, command lines, logs, |
| // and anything else that might aid in debugging issues or understanding the |
| // provenance of the data. |
| std::string DebugInfoDirPath() const; |
| // Returns the path to the coverage dir. |
| std::string CoverageDirPath() const; |
| // Returns the path where the BinaryInfo will be serialized within workdir. |
| std::string BinaryInfoDirPath() const; |
| |
| // Returns the paths for the sharded crash reproducer directory. |
| PathShards CrashReproducerDirPaths() const; |
| // Returns the paths for the sharded crash metadata directory, which contains |
| // the crash metadata file for each crash reproducer. |
| PathShards CrashMetadataDirPaths() const; |
| // Returns the paths for the sharded corpus file. |
| PathShards CorpusFilePaths() const; |
| // Returns the paths for the sharded distilled corpus file. |
| PathShards DistilledCorpusFilePaths() const; |
| // Returns the paths for the sharded features file. |
| PathShards FeaturesFilePaths() const; |
| // Returns the paths for the sharded distilled features file. |
| PathShards DistilledFeaturesFilePaths() const; |
| |
| // Returns the path for the coverage report file for my_shard_index. |
| // Non-default `annotation` becomes a part of the returned filename. |
| // `annotation` must not start with a '.'. |
| std::string CoverageReportPath(std::string_view annotation = "") const; |
| // Returns the path to the source-based coverage report directory. |
| std::string SourceBasedCoverageReportPath( |
| std::string_view annotation = "") const; |
| // Returns the path to the coverage profile for this shard. |
| std::string SourceBasedCoverageRawProfilePath() const; |
| // Returns the path to the indexed code coverage file. |
| std::string SourceBasedCoverageIndexedProfilePath() const; |
| // Returns all shards' raw profile paths by scanning the coverage directory. |
| std::vector<std::string> EnumerateRawCoverageProfiles() const; |
| |
| // Returns the path for the corpus stats report file for my_shard_index. |
| // Non-default `annotation` becomes a part of the returned filename. |
| // `annotation` must not start with a '.'. |
| std::string CorpusStatsPath(std::string_view annotation = "") const; |
| // Returns the path for the fuzzing progress stats report file for |
| // `my_shard_index`. |
| // Non-default `annotation` becomes a part of the returned filename. |
| // `annotation` must not start with a '.'. |
| std::string FuzzingStatsPath(std::string_view annotation = "") const; |
| // Returns the path for the performance report file for my_shard_index. |
| // Non-default `annotation` becomes a part of the returned filename. |
| // `annotation` must not start with a '.'. |
| std::string RUsageReportPath(std::string_view annotation = "") const; |
| |
| private: |
| // Internal value holders for when the object is constructed from direct |
| // values rather than an `Environment` object. |
| std::string workdir_holder_; |
| std::string binary_name_holder_; |
| std::string binary_hash_holder_; |
| size_t my_shard_index_holder_; |
| |
| // The references to either the internal `*_holder_` counterparts or an |
| // externally passed `Environment` object's counterparts. |
| const std::string &workdir_; |
| const std::string &binary_name_; |
| const std::string &binary_hash_; |
| const size_t &my_shard_index_; |
| }; |
| |
| } // namespace fuzztest::internal |
| |
| #endif // THIRD_PARTY_CENTIPEDE_WORKDIR_MGR_H_ |