// 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. // Blob is a sequence of bytes, a BlobFile is a sequence of blobs. // BlobFileReader reads blobs from a BlobFile. // BlobFileWriter writes blobs to a BlobFile. // Only one active BlobFileWriter is allowed for a given file. // Multiple BlobFileReader objects can open the same file, concurrently // with up to one BlobFileWriter. // BlobFileReader/BlobFileWriter should have some level of protection against // failed operations (may vary depending on the implementation). // Different implementations of BlobFileReader/BlobFileWriter don't have to // be file-format compatible. #ifndef FUZZTEST_COMMON_BLOB_FILE_H_ #define FUZZTEST_COMMON_BLOB_FILE_H_ #include #include #include #include "absl/base/nullability.h" #include "absl/status/status.h" #include "./common/defs.h" namespace fuzztest::internal { // Reads blobs from a BlobFile. See the top file comment. class BlobFileReader { public: BlobFileReader() = default; // Implementations must take care to call their Close() in the dtor, unless // the client has already explicitly called it. virtual ~BlobFileReader() = default; // Not copyable or movable. BlobFileReader(const BlobFileReader &) = delete; BlobFileReader &operator=(const BlobFileReader &) = delete; BlobFileReader(BlobFileReader &&) = delete; BlobFileReader &operator=(BlobFileReader &&) = delete; // Opens the file `path`. virtual absl::Status Open(std::string_view path) = 0; // Reads one `blob` from an open file. // Implementations must ensure that the memory wrapped by `blob` remains valid // until the next Read() or Close() call. // Returns absl::OutOfRangeError when there are no more blobs to read. virtual absl::Status Read(ByteSpan &blob) = 0; // Closes the previously opened file, if any. virtual absl::Status Close() = 0; }; // Writes blobs to a BlobFile. See the top file comment. class BlobFileWriter { public: BlobFileWriter() = default; // Implementations must take care to call their Close() in the dtor, unless // the client has already explicitly called it. virtual ~BlobFileWriter() = default; // Not copyable or movable. BlobFileWriter(const BlobFileWriter &) = delete; BlobFileWriter &operator=(const BlobFileWriter &) = delete; BlobFileWriter(BlobFileWriter &&) = delete; BlobFileWriter &operator=(BlobFileWriter &&) = delete; // Opens the file `path` with mode `mode` (which must be either "w" or "a" at // the moment). Implementations must ensure that this is called only once. virtual absl::Status Open(std::string_view path, std::string_view mode) = 0; // Writes `blob` to this file. Implementations must ensure that the file has // been opened. virtual absl::Status Write(ByteSpan blob) = 0; // Same as above, but for `ByteArray`. absl::Status Write(const ByteArray &bytes) { return Write(ByteSpan{bytes}); } // Closes the file, which was previously opened and never closed. virtual absl::Status Close() = 0; }; // Creates a new object of a default implementation of BlobFileReader. // The current default implementation supports reading files in the bespoke // legacy or Riegeli (https://github.com/google/riegeli) format. std::unique_ptr DefaultBlobFileReaderFactory(); // Creates a new object of a default implementation of BlobFileWriter. // If `riegeli` is `true`, the implementation uses Riegeli // (https://github.com/google/riegeli). std::unique_ptr DefaultBlobFileWriterFactory( #ifdef CENTIPEDE_DISABLE_RIEGELI bool riegeli = false #else bool riegeli = true #endif // CENTIPEDE_DISABLE_RIEGELI ); // Adds a prefix and a postfix to `data` such that the result can be // appended to another such packed data and then the operation can be reversed. // The purpose is to allow appending blobs of data to a (possibly remote) file // such that when reading this file we can separate the blobs. // NOTE: The now-default blob file format (Riegeli) doesn't need this, but some // external clients continue to use plain blob files and are unlikely to switch // (e.g. Chromium). ByteArray PackBytesForAppendFile(ByteSpan blob); // Unpacks `packed_data` into `unpacked` and `hashes`. // `packed_data` is multiple data packed by PackBytesForAppendFile() // and merged together. // `unpacked` or `hashes` can be nullptr. void UnpackBytesFromAppendFile( const ByteArray &packed_data, std::vector *absl_nullable unpacked, std::vector *absl_nullable hashes = nullptr); } // namespace fuzztest::internal #endif // FUZZTEST_COMMON_BLOB_FILE_H_