
Bug: 343687741 Change-Id: Iedbaee681d585f8c55bf0e9fdd1caa91ace34153 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5581356 Auto-Submit: Paul Semel <paulsemel@chromium.org> Commit-Queue: Adrian Taylor <adetaylor@chromium.org> Reviewed-by: Adrian Taylor <adetaylor@chromium.org> Commit-Queue: Paul Semel <paulsemel@chromium.org> Cr-Commit-Position: refs/heads/main@{#1308014}
106 lines
3.3 KiB
C++
106 lines
3.3 KiB
C++
// Copyright 2024 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// A wrapper which knows to execute a given fuzzer within a fuzztest
|
|
// executable that contains multiple fuzzers.
|
|
// The fuzzer binary is assumed to be in the same directory as this binary.
|
|
|
|
#include <iostream>
|
|
|
|
#include "base/command_line.h"
|
|
#include "base/files/file_path.h"
|
|
#include "base/files/file_util.h"
|
|
#include "base/path_service.h"
|
|
#include "base/process/launch.h"
|
|
#include "base/strings/string_split.h"
|
|
#include "base/strings/stringprintf.h"
|
|
#include "base/strings/utf_string_conversions.h"
|
|
#include "testing/libfuzzer/fuzztest_wrapper_buildflags.h"
|
|
|
|
extern const char* kFuzzerBinary;
|
|
extern const char* kFuzzerArgs;
|
|
|
|
#if BUILDFLAG(USE_CENTIPEDE)
|
|
|
|
namespace {
|
|
void HandleReplayMode(auto& args) {
|
|
// We're handling a centipede based fuzzer. If the last argument is a
|
|
// filepath, we're trying to replay a testcase, since it doesn't make sense
|
|
// to get a filepath when running with the centipede binary.
|
|
if (args.size() <= 1) {
|
|
return;
|
|
}
|
|
base::FilePath test_case(args.back());
|
|
if (!base::PathExists(test_case)) {
|
|
return;
|
|
}
|
|
|
|
auto env = base::Environment::Create();
|
|
#if BUILDFLAG(IS_WIN)
|
|
auto env_value = base::WideToUTF8(args.back());
|
|
#else
|
|
auto env_value = args.back();
|
|
#endif
|
|
env->SetVar("FUZZTEST_REPLAY", env_value);
|
|
env->UnSetVar("CENTIPEDE_RUNNER_FLAGS");
|
|
std::cerr << "FuzzTest wrapper setting env var: FUZZTEST_REPLAY="
|
|
<< args.back() << '\n';
|
|
|
|
// We must not add the testcase to the command line, as this will not be
|
|
// parsed correctly by centipede.
|
|
args.pop_back();
|
|
}
|
|
} // namespace
|
|
|
|
#endif // BUILDFLAG(USE_CENTIPEDE)
|
|
|
|
int main(int argc, const char* const* argv) {
|
|
base::CommandLine::Init(argc, argv);
|
|
base::FilePath fuzzer_path;
|
|
if (!base::PathService::Get(base::DIR_EXE, &fuzzer_path)) {
|
|
return -1;
|
|
}
|
|
fuzzer_path = fuzzer_path.AppendASCII(kFuzzerBinary);
|
|
base::LaunchOptions launch_options;
|
|
base::CommandLine cmdline(fuzzer_path);
|
|
std::vector<std::string_view> additional_args = base::SplitStringPiece(
|
|
kFuzzerArgs, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
|
|
for (auto arg : additional_args) {
|
|
cmdline.AppendArg(arg);
|
|
}
|
|
auto args = base::CommandLine::ForCurrentProcess()->argv();
|
|
#if BUILDFLAG(USE_CENTIPEDE)
|
|
HandleReplayMode(args);
|
|
#endif // BUILDFLAG(USE_CENTIPEDE)
|
|
|
|
bool skipped_first = false;
|
|
for (auto arg : args) {
|
|
if (!skipped_first) {
|
|
skipped_first = true;
|
|
continue;
|
|
}
|
|
// We avoid AppendArguments because it parses switches then reorders things.
|
|
cmdline.AppendArgNative(arg);
|
|
}
|
|
std::cerr << "FuzzTest wrapper launching:" << cmdline.GetCommandLineString()
|
|
<< "\n";
|
|
base::Process p = base::LaunchProcess(cmdline, launch_options);
|
|
int exit_code;
|
|
p.WaitForExit(&exit_code);
|
|
return exit_code;
|
|
}
|
|
|
|
#if defined(WIN32)
|
|
#define ALWAYS_EXPORT __declspec(dllexport)
|
|
#else
|
|
#define ALWAYS_EXPORT __attribute__((visibility("default")))
|
|
#endif
|
|
|
|
ALWAYS_EXPORT extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data,
|
|
size_t size) {
|
|
// No-op. This symbol exists to ensure that this binary is detected as
|
|
// a fuzzer by ClusterFuzz's heuristics. It never actually gets called.
|
|
return -1;
|
|
}
|