blob: d87a370eefa54e8e059fdc828269d6d1cf0fc58f [file] [log] [blame] [edit]
// 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.
#include "llvm-fuzzer.h"
#include <lib/syslog/cpp/macros.h>
#include <string.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include "libfuzzer.h"
namespace fuzzing {
namespace {
// Dummy argv[0] used when invoking |LLVMFuzzerInitialize|. Use it to warn the user-provided that
// argv[0] cannot be modified, or libFuzzer will encounter a fatal error.
const char *kArgv0 = "argv0-cannot-be-modified";
} // namespace
// Public methods
LlvmFuzzerImpl::LlvmFuzzerImpl() : binding_(this) {}
LlvmFuzzerImpl::~LlvmFuzzerImpl() {}
fidl::InterfaceRequestHandler<LlvmFuzzer> LlvmFuzzerImpl::GetHandler(
async_dispatcher_t *dispatcher) {
return [this, dispatcher](fidl::InterfaceRequest<LlvmFuzzer> request) {
if (!binding_.is_bound()) {
binding_.Bind(std::move(request), dispatcher);
}
};
}
void LlvmFuzzerImpl::Initialize(zx::vmo vmo, std::vector<std::string> options,
InitializeCallback callback) {
zx_status_t status = ZX_OK;
if (input_.is_mapped()) {
FX_LOGS(ERROR) << "Already initialized.";
status = ZX_ERR_BAD_STATE;
} else if ((status = input_.Link(std::move(vmo))) != ZX_OK) {
FX_LOGS(ERROR) << "Failed to link shared test input memory: " << zx_status_get_string(status);
} else if (LLVMFuzzerInitialize != nullptr) {
int argc = options.size() + 1;
std::vector<char *> c_strs;
c_strs.reserve(argc);
c_strs.push_back(const_cast<char *>(kArgv0));
std::transform(options.begin(), options.end(), std::back_inserter(c_strs),
[](const std::string &s) { return const_cast<char *>(s.c_str()); });
char **argv = &c_strs[0];
// |LLVMFuzzerInitialize| MUST NOT deallocate any memory passed to it, and is responsible for
// any memory it allocates. This matches the "normal" behavior in a single-process fuzzer, where
// argv would normally refer to stack locations.
status = LLVMFuzzerInitialize(&argc, &argv);
std::vector<std::string> mods;
mods.reserve(argc);
for (int i = 1; i < argc; ++i) {
mods.push_back(std::string(argv[i]));
}
options = std::move(mods);
}
callback(status, std::move(options));
}
void LlvmFuzzerImpl::TestOneInput(TestOneInputCallback callback) {
callback(LLVMFuzzerTestOneInput(input_.data(), input_.size()));
}
void LlvmFuzzerImpl::Reset() { input_.Reset(); }
} // namespace fuzzing