blob: f54bdffbdde2f66f263a0cbde3bfbed34a520525 [file] [log] [blame]
// Copyright 2020 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_LIB_FUZZING_FIDL_ENGINE_H_
#define SRC_LIB_FUZZING_FIDL_ENGINE_H_
#include <fuchsia/fuzzer/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/fxl/macros.h>
#include <lib/sync/completion.h>
#include <lib/sys/cpp/component_context.h>
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include "data-provider.h"
#include "proxy.h"
namespace fuzzing {
namespace {
using ::fuchsia::fuzzer::Engine;
using ::fuchsia::fuzzer::LlvmFuzzerPtr;
} // namespace
// This class integrates the Proxy, DataProvider, and LlvmFuzzer FIDL services into a single
// object that can perform fuzzing iterations. See also libfuzzer.cc, which integrates the
// libFuzzer compiler runtime with this class.
class EngineImpl : public Engine {
public:
// Singleton. Tests can avoid the engine starting a dispatch loop by calling this with
// |autoconnect| set to false before any other calls, preferably by using |UseContext| below.
static EngineImpl *GetInstance(bool autoconnect = true);
virtual ~EngineImpl();
// Helper for getting a test instance of Engine that uses the test's |context| and |dispatcher|.
static void UseContext(std::unique_ptr<sys::ComponentContext> context) {
GetInstance(false)->UseContextImpl(std::move(context));
}
// Accessors
AggregatedProxy &coverage() { return coverage_; }
DataProviderImpl &data_provider() { return data_provider_; }
// Sets the LlvmFuzzer service this engine is connected to. Used for testing (autoconnect=false).
zx_status_t SetLlvmFuzzer(LlvmFuzzerPtr fuzzer);
// FIDL methods
void Start(std::vector<std::string> options, StartCallback callback) override;
// LLVM C ABI functions
// See https://github.com/llvm/llvm-project/blob/HEAD/compiler-rt/lib/fuzzer/FuzzerInterface.h
int Initialize(int *argc, char ***argv);
int TestOneInput(const uint8_t *data, size_t size);
// Stops the engine and invokes the callback passed to |Start|.
void Stop(zx_status_t status);
private:
explicit EngineImpl(bool autoconnect);
void UseContextImpl(std::unique_ptr<sys::ComponentContext> context);
// FIDL dispatcher loop. Null when testing.
std::unique_ptr<async::Loop> loop_;
std::unique_ptr<sys::ComponentContext> context_;
async_dispatcher_t *dispatcher_;
AggregatedProxy coverage_;
DataProviderImpl data_provider_;
LlvmFuzzerPtr llvm_fuzzer_;
// LibFuzzer options and a command line used for passing them to libFuzzer.
// See https://llvm.org/docs/LibFuzzer.html#options
std::vector<std::string> options_;
std::vector<char *> argv_;
// Blocks |Initialize| and |TestOneInput|| until |Start| has been called.
sync_completion_t sync_;
// Callback used to return status when the engine stops.
StartCallback callback_;
FXL_DISALLOW_COPY_ASSIGN_AND_MOVE(EngineImpl);
};
} // namespace fuzzing
#endif // SRC_LIB_FUZZING_FIDL_ENGINE_H_