From 954441c358d1b7df5515ab2728953bce0eb690d4 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Fri, 1 Nov 2024 08:35:29 -0700 Subject: [PATCH] Exempt the `clang` subcommand when fuzzing. (#4468) This teaches the driver library to track when its being used with fuzzing and disables the `clang` subcommand from actually running Clang. The Clang libraries have a large backlog of fuzzer-found issues that isn't being actively reduced, so we can't productively fuzz into it. This lets us more productively fuzz at the top level. This is also available on the command line itself, which should be useful if anyone wants to fuzz Carbon from the command line using tools like AFL -- they can inject this flag to avoid getting noise from the fuzzer hitting known issues in Clang. --- toolchain/driver/clang_subcommand.cpp | 9 +++++++++ toolchain/driver/driver.cpp | 14 ++++++++++++++ toolchain/driver/driver.h | 4 ++++ toolchain/driver/driver_env.h | 3 +++ toolchain/driver/driver_fuzzer.cpp | 1 + 5 files changed, 31 insertions(+) diff --git a/toolchain/driver/clang_subcommand.cpp b/toolchain/driver/clang_subcommand.cpp index 75bc9bf994e06..2d1b89cc78677 100644 --- a/toolchain/driver/clang_subcommand.cpp +++ b/toolchain/driver/clang_subcommand.cpp @@ -44,6 +44,15 @@ Arguments passed to Clang. auto ClangSubcommand::Run(DriverEnv& driver_env) -> DriverResult { std::string target = llvm::sys::getDefaultTargetTriple(); ClangRunner runner(driver_env.installation, target, driver_env.vlog_stream); + + // Don't run Clang when fuzzing, it is known to not be reliable under fuzzing + // due to many unfixed issues. + if (driver_env.fuzzing) { + driver_env.error_stream + << "error: cannot run `clang` subcommand productively when fuzzing\n"; + return {.success = false}; + } + return {.success = runner.Run(options_.args)}; } diff --git a/toolchain/driver/driver.cpp b/toolchain/driver/driver.cpp index b1066b5e00361..508f15c63388e 100644 --- a/toolchain/driver/driver.cpp +++ b/toolchain/driver/driver.cpp @@ -24,6 +24,7 @@ struct Options { auto Build(CommandLine::CommandBuilder& b) -> void; bool verbose; + bool fuzzing; ClangSubcommand clang; CompileSubcommand compile; @@ -63,6 +64,13 @@ auto Options::Build(CommandLine::CommandBuilder& b) -> void { }, [&](CommandLine::FlagBuilder& arg_b) { arg_b.Set(&verbose); }); + b.AddFlag( + { + .name = "fuzzing", + .help = "Configure the command line for fuzzing.", + }, + [&](CommandLine::FlagBuilder& arg_b) { arg_b.Set(&fuzzing); }); + b.AddSubcommand(ClangOptions::Info, [&](CommandLine::CommandBuilder& sub_b) { clang.BuildOptions(sub_b); sub_b.Do([&] { subcommand = &clang; }); @@ -109,8 +117,14 @@ auto Driver::RunCommand(llvm::ArrayRef args) -> DriverResult { // Note this implies streamed output in order to interleave. driver_env_.vlog_stream = &driver_env_.error_stream; } + if (options.fuzzing) { + SetFuzzing(); + } + CARBON_CHECK(options.subcommand != nullptr); return options.subcommand->Run(driver_env_); } +auto Driver::SetFuzzing() -> void { driver_env_.fuzzing = true; } + } // namespace Carbon diff --git a/toolchain/driver/driver.h b/toolchain/driver/driver.h index 3a7315c914a75..5f3c65e9e082a 100644 --- a/toolchain/driver/driver.h +++ b/toolchain/driver/driver.h @@ -38,6 +38,10 @@ class Driver { // error stream (stderr by default). auto RunCommand(llvm::ArrayRef args) -> DriverResult; + // Configure the driver for fuzzing. This allows specific commands to error + // rather than perform operations that aren't well behaved during fuzzing. + auto SetFuzzing() -> void; + private: DriverEnv driver_env_; }; diff --git a/toolchain/driver/driver_env.h b/toolchain/driver/driver_env.h index ad0966f8d9adb..03a8f36a5d97a 100644 --- a/toolchain/driver/driver_env.h +++ b/toolchain/driver/driver_env.h @@ -25,6 +25,9 @@ struct DriverEnv { // For CARBON_VLOG. llvm::raw_pwrite_stream* vlog_stream = nullptr; + + // Tracks when the driver is being fuzzed. + bool fuzzing = false; }; } // namespace Carbon diff --git a/toolchain/driver/driver_fuzzer.cpp b/toolchain/driver/driver_fuzzer.cpp index a5e145aea9a8e..592ff2147a46c 100644 --- a/toolchain/driver/driver_fuzzer.cpp +++ b/toolchain/driver/driver_fuzzer.cpp @@ -82,6 +82,7 @@ extern "C" auto LLVMFuzzerTestOneInput(const unsigned char* data, size_t size) TestRawOstream error_stream; llvm::raw_null_ostream dest; Driver d(fs, install_paths, dest, error_stream); + d.SetFuzzing(); if (!d.RunCommand(args).success) { auto str = error_stream.TakeStr(); // TODO: Fix command_line to use `error`, switch back to `find`.