diff --git a/toolchain/driver/clang_subcommand.cpp b/toolchain/driver/clang_subcommand.cpp index 75bc9bf994e0..2d1b89cc7867 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 b1066b5e0036..508f15c63388 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 3a7315c914a7..5f3c65e9e082 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 ad0966f8d9ad..03a8f36a5d97 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 a5e145aea9a8..592ff2147a46 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`.