blob: 655743ba5ce81a2193c02872fc816809819b9e7b [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_SYS_FUZZING_FRAMEWORK_ENGINE_CORPUS_H_
#define SRC_SYS_FUZZING_FRAMEWORK_ENGINE_CORPUS_H_
#include <stddef.h>
#include <zircon/compiler.h>
#include <memory>
#include <random>
#include <vector>
#include "src/lib/fxl/macros.h"
#include "src/sys/fuzzing/common/input.h"
#include "src/sys/fuzzing/common/options.h"
namespace fuzzing {
// An alias to simplify passing around the shared corpora.
class Corpus;
using CorpusPtr = std::shared_ptr<Corpus>;
// Represents a set of fuzzing inputs. All inputs are held in memory, since writing them out to
// "disk" within the test runner framework would only write them to memfs, and lead to the same
// overall memory pressure. A corpus always includes an empty input, and so is never completely
// empty.
class Corpus final {
public:
Corpus();
Corpus(Corpus&& other) noexcept { *this = std::move(other); }
~Corpus() = default;
Corpus& operator=(Corpus&& other) noexcept;
size_t num_inputs() const { return inputs_.size(); }
size_t total_size() const { return total_size_; }
static CorpusPtr MakePtr() { return std::make_shared<Corpus>(); }
// Adds default values to unspecified options that are needed by objects of this class.
static void AddDefaults(Options* options);
// Sets options. This will reset the PRNG.
void Configure(const OptionsPtr& options);
// Recusively walks the |root|-relative directories given by |dirs| and |Add|s the contents of the
// files they contain.
__WARN_UNUSED_RESULT zx_status_t LoadAt(const std::string& root,
const std::vector<std::string>& dirs);
// Like |LoadAt| with |root| defaulting to "/pkg".
__WARN_UNUSED_RESULT zx_status_t Load(const std::vector<std::string>& dirs);
// Adds the input to the corpus. Returns ZX_ERR_BUFFER_TOO_SMALL if the input exceeds the max size
// specified by the options; ZX_OK otherwise.
__WARN_UNUSED_RESULT zx_status_t Add(Input input);
// Adds all inputs from the given |corpus| to this corpus. Returns ZX_ERR_INVALID_ARGS if |corpus|
// is null, and ZX_ERR_BUFFER_TOO_SMALL if any/ input exceeds the max size specified by the
// options. Otherwise, returns ZX_OK.
zx_status_t Add(CorpusPtr corpus);
// Returns true and the input at |offset| in the corpus via |out| if |offset| is less than the
// number of inputs; otherwise returns false and sets |out| to an empty input.
bool At(size_t offset, Input* out);
// Returns a random element from the corpus via |out| This will always succeed, as this method
// can pick the implicitly included empty element.
void Pick(Input* out);
private:
// Reads the directory at |dirname| recursively and |Add|s the contents of each file.
zx_status_t ReadDir(const std::string& dirname);
// Reads the file at |filename| and |Add|s its contents.
zx_status_t ReadFile(const std::string& filename);
OptionsPtr options_;
std::minstd_rand prng_;
// TODO(fxbug.dev/84361): Currently, all inputs are held in memory. It may be desirable to store
// some inputs on local storage when the corpus grows too large.
std::vector<Input> inputs_;
size_t total_size_ = 0;
FXL_DISALLOW_COPY_AND_ASSIGN(Corpus);
};
} // namespace fuzzing
#endif // SRC_SYS_FUZZING_FRAMEWORK_ENGINE_CORPUS_H_