blob: 21c1aff60129a05596edccfd2898a03ddfc78be7 [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_LIBFUZZER_RUNNER_H_
#define SRC_SYS_FUZZING_LIBFUZZER_RUNNER_H_
#include <fuchsia/fuzzer/cpp/fidl.h>
#include <lib/fdio/spawn.h>
#include <lib/fit/function.h>
#include <lib/zx/process.h>
#include <zircon/compiler.h>
#include <memory>
#include <string_view>
#include <re2/re2.h>
#include "src/sys/fuzzing/common/async-types.h"
#include "src/sys/fuzzing/common/input.h"
#include "src/sys/fuzzing/common/runner.h"
#include "src/sys/fuzzing/libfuzzer/process.h"
namespace fuzzing {
using ::fuchsia::fuzzer::Status;
// The concrete implementation of |Runner| for the libfuzzer engine.
class LibFuzzerRunner : public Runner {
public:
~LibFuzzerRunner() override = default;
// Factory method.
static RunnerPtr MakePtr(ExecutorPtr executor);
void set_cmdline(const std::vector<std::string>& cmdline) { cmdline_ = cmdline; }
void set_verbose(bool verbose) { verbose_ = verbose; }
// |Runner| methods.
void AddDefaults(Options* options) override;
__WARN_UNUSED_RESULT zx_status_t AddToCorpus(CorpusType corpus_type, Input input) override;
Input ReadFromCorpus(CorpusType corpus_type, size_t offset) override;
__WARN_UNUSED_RESULT zx_status_t ParseDictionary(const Input& input) override;
Input GetDictionaryAsInput() const override;
ZxPromise<> Configure(const OptionsPtr& options) override;
ZxPromise<FuzzResult> Execute(Input input) override;
ZxPromise<Input> Minimize(Input input) override;
ZxPromise<Input> Cleanse(Input input) override;
ZxPromise<Artifact> Fuzz() override;
ZxPromise<> Merge() override;
ZxPromise<> Stop() override;
Status CollectStatus() override;
protected:
// Creates the list of actions to perform when spawning libFuzzer. Returns pipes to |stdin| and
// from |stderr|.
std::vector<fdio_spawn_action_t> MakeSpawnActions(int* stdin_fd, int* stderr_fd);
private:
explicit LibFuzzerRunner(ExecutorPtr executor);
// Construct a set of libFuzzer command-line arguments for the current options.
std::vector<std::string> MakeArgs();
// Returns a promise that runs a libFuzzer process asynchronously and returns the fuzzing result
// and the input that caused it.
ZxPromise<Artifact> RunAsync(std::vector<std::string> args);
// Returns a promise that reads the output of the process run by |RunAsync|. The promise will
// update the fuzzer status accordingly, and return the fuzzing result when idenitifed.
ZxPromise<FuzzResult> ParseOutput();
// Attempts to interpret the line as containing information from libFuzzer.
// Returns the fuzzing result or error detected in libFuzzer's output, or |fpromise:ok(NO_ERRORS)|
// if neither is found.
ZxResult<FuzzResult> ParseLine(const std::string& line);
// Attempts to interpret the line as containing status information from libFuzzer.
// Returns true if |line| is status, false otherwise.
void ParseStatus(re2::StringPiece* input);
// Attempts to interpret the line as containing error information from libFuzzer.
ZxResult<FuzzResult> ParseError(re2::StringPiece* input);
// Update the list of input files in the live corpus.
void ReloadLiveCorpus();
std::vector<std::string> cmdline_;
OptionsPtr options_;
// Immutable set of inputs. These will be kept on merge.
std::vector<std::string> seed_corpus_;
// Dynamic set of inputs. Inputs may be added during fuzzing, and/or may be removed when merging.
std::vector<std::string> live_corpus_;
bool has_dictionary_ = false;
zx::time start_;
// If true, eachoes the piped stderr to this process's stderr.
bool verbose_ = true;
Status status_;
std::string result_input_pathname_;
bool minimized_ = false;
// Asynchronous process used to run libFuzzer instances.
Process process_;
Barrier barrier_;
Workflow workflow_;
FXL_DISALLOW_COPY_ASSIGN_AND_MOVE(LibFuzzerRunner);
};
} // namespace fuzzing
#endif // SRC_SYS_FUZZING_LIBFUZZER_RUNNER_H_