diff --git a/fuzztest/internal/centipede_adaptor.cc b/fuzztest/internal/centipede_adaptor.cc index 26a3cb12..853963d8 100644 --- a/fuzztest/internal/centipede_adaptor.cc +++ b/fuzztest/internal/centipede_adaptor.cc @@ -165,6 +165,13 @@ class CentipedeAdaptorRunnerCallbacks : public centipede::RunnerCallbacks { prng_(GetRandomSeed()) {} bool Execute(centipede::ByteSpan input) override { + if (!domain_setup_is_checked_) { + // Create a new domain input to trigger any domain setup + // failures here. (e.g. Ineffective Filter) + fuzzer_impl_.params_domain_.Init(prng_); + domain_setup_is_checked_ = true; + } + auto parsed_input = fuzzer_impl_.TryParse({(char*)input.data(), input.size()}); if (parsed_input.ok()) { @@ -300,6 +307,7 @@ class CentipedeAdaptorRunnerCallbacks : public centipede::RunnerCallbacks { Runtime& runtime_; FuzzTestFuzzerImpl& fuzzer_impl_; const Configuration& configuration_; + bool domain_setup_is_checked_ = false; std::unique_ptr cmp_tables_; absl::BitGen prng_; }; @@ -518,15 +526,16 @@ CentipedeFuzzerAdaptor::CentipedeFuzzerAdaptor( "Invalid fixture driver!"); } -void CentipedeFuzzerAdaptor::RunInUnitTestMode( +bool CentipedeFuzzerAdaptor::RunInUnitTestMode( const Configuration& configuration) { centipede_fixture_driver_->set_configuration(&configuration); CentipedeBeginExecutionBatch(); fuzzer_impl_.RunInUnitTestMode(configuration); CentipedeEndExecutionBatch(); + return true; } -int CentipedeFuzzerAdaptor::RunInFuzzingMode( +bool CentipedeFuzzerAdaptor::RunInFuzzingMode( int* argc, char*** argv, const Configuration& configuration) { centipede_fixture_driver_->set_configuration(&configuration); runtime_.SetRunMode(RunMode::kFuzz); @@ -535,10 +544,6 @@ int CentipedeFuzzerAdaptor::RunInFuzzingMode( if (IsSilenceTargetEnabled()) SilenceTargetStdoutAndStderr(); runtime_.EnableReporter(&fuzzer_impl_.stats_, [] { return absl::Now(); }); fuzzer_impl_.fixture_driver_->SetUpFuzzTest(); - // Always create a new domain input to trigger any domain setup - // failures here. (e.g. Ineffective Filter) - FuzzTestFuzzerImpl::PRNG prng; - fuzzer_impl_.params_domain_.Init(prng); bool print_final_stats = true; // When the CENTIPEDE_RUNNER_FLAGS env var exists, the current process is // considered a child process spawned by the Centipede binary as the runner, @@ -623,13 +628,12 @@ int CentipedeFuzzerAdaptor::RunInFuzzingMode( return centipede::CentipedeMain(env, factory); })(); fuzzer_impl_.fixture_driver_->TearDownFuzzTest(); - if (result) std::exit(result); if (print_final_stats) { absl::FPrintF(GetStderr(), "\n[.] Fuzzing was terminated.\n"); runtime_.PrintFinalStatsOnDefaultSink(); absl::FPrintF(GetStderr(), "\n"); } - return 0; + return result == 0; } } // namespace fuzztest::internal diff --git a/fuzztest/internal/centipede_adaptor.h b/fuzztest/internal/centipede_adaptor.h index f64bd652..6ca4c815 100644 --- a/fuzztest/internal/centipede_adaptor.h +++ b/fuzztest/internal/centipede_adaptor.h @@ -30,9 +30,9 @@ class CentipedeFuzzerAdaptor : public FuzzTestFuzzer { public: CentipedeFuzzerAdaptor(const FuzzTest& test, std::unique_ptr fixture_driver); - void RunInUnitTestMode(const Configuration& configuration) override; - int RunInFuzzingMode(int* argc, char*** argv, - const Configuration& configuration) override; + bool RunInUnitTestMode(const Configuration& configuration) override; + bool RunInFuzzingMode(int* argc, char*** argv, + const Configuration& configuration) override; private: Runtime& runtime_ = Runtime::instance(); diff --git a/fuzztest/internal/googletest_adaptor.h b/fuzztest/internal/googletest_adaptor.h index 7286a449..3e7f2d4e 100644 --- a/fuzztest/internal/googletest_adaptor.h +++ b/fuzztest/internal/googletest_adaptor.h @@ -78,13 +78,14 @@ class GTest_TestAdaptor : public ::testing::Test { EXPECT_TRUE(false) << "Death test is not supported."; #endif } else { - test->RunInUnitTestMode(configuration_); + EXPECT_TRUE(test->RunInUnitTestMode(configuration_)) + << "Failure(s) found in the unit-test mode."; } } else { // TODO(b/245753736): Consider using `tolerate_failure` when FuzzTest can // tolerate crashes in fuzzing mode. - ASSERT_EQ(0, test->RunInFuzzingMode(argc_, argv_, configuration_)) - << "Fuzzing failure."; + EXPECT_TRUE(test->RunInFuzzingMode(argc_, argv_, configuration_)) + << "Failure(s) found in the fuzzing mode."; } } diff --git a/fuzztest/internal/runtime.cc b/fuzztest/internal/runtime.cc index ecdf0200..18ed8df7 100644 --- a/fuzztest/internal/runtime.cc +++ b/fuzztest/internal/runtime.cc @@ -933,7 +933,7 @@ void PopulateLimits(const Configuration& configuration, #endif } -void FuzzTestFuzzerImpl::RunInUnitTestMode(const Configuration& configuration) { +bool FuzzTestFuzzerImpl::RunInUnitTestMode(const Configuration& configuration) { runtime_.SetSkippingRequested(false); fixture_driver_->SetUpFuzzTest(); [&] { @@ -1014,6 +1014,7 @@ void FuzzTestFuzzerImpl::RunInUnitTestMode(const Configuration& configuration) { runtime_.SetCurrentTest(nullptr, nullptr); }(); fixture_driver_->TearDownFuzzTest(); + return true; } FuzzTestFuzzerImpl::RunResult FuzzTestFuzzerImpl::RunOneInput( @@ -1102,16 +1103,16 @@ void FuzzTestFuzzerImpl::MinimizeNonFatalFailureLocally(absl::BitGenRef prng) { } } -int FuzzTestFuzzerImpl::RunInFuzzingMode(int* /*argc*/, char*** /*argv*/, - const Configuration& configuration) { +bool FuzzTestFuzzerImpl::RunInFuzzingMode(int* /*argc*/, char*** /*argv*/, + const Configuration& configuration) { runtime_.SetSkippingRequested(false); fixture_driver_->SetUpFuzzTest(); - const int exit_code = [&] { + const bool success = [&] { if (runtime_.skipping_requested()) { absl::FPrintF(GetStderr(), "[.] Skipping %s per request from the test setup.\n", test_.full_name()); - return 0; + return true; } runtime_.StartWatchdog(); PopulateLimits(configuration, execution_coverage_); @@ -1125,14 +1126,14 @@ int FuzzTestFuzzerImpl::RunInFuzzingMode(int* /*argc*/, char*** /*argv*/, if (ReplayInputsIfAvailable(configuration)) { // If ReplayInputs returns, it means the replay didn't crash. // We don't want to actually run the fuzzer so exit now. - return 0; + return true; } if (execution_coverage_ == nullptr) { absl::FPrintF( GetStderr(), "\n\n[!] To fuzz, please build with --config=fuzztest.\n\n\n"); - return 1; + return false; } stats_.total_edges = execution_coverage_->GetCounterMap().size(); @@ -1144,7 +1145,7 @@ int FuzzTestFuzzerImpl::RunInFuzzingMode(int* /*argc*/, char*** /*argv*/, GetStderr(), "[*] Selected %d corpus inputs in minimization mode - exiting.\n", stats_.useful_inputs); - return 0; + return true; } CorpusDatabase corpus_database(configuration); @@ -1238,10 +1239,10 @@ int FuzzTestFuzzerImpl::RunInFuzzingMode(int* /*argc*/, char*** /*argv*/, absl::FPrintF(GetStderr(), "\n[.] Fuzzing was terminated.\n"); runtime_.PrintFinalStatsOnDefaultSink(); absl::FPrintF(GetStderr(), "\n"); - return 0; + return true; }(); fixture_driver_->TearDownFuzzTest(); - return exit_code; + return success; } } // namespace fuzztest::internal diff --git a/fuzztest/internal/runtime.h b/fuzztest/internal/runtime.h index 89fd494a..491fe704 100644 --- a/fuzztest/internal/runtime.h +++ b/fuzztest/internal/runtime.h @@ -63,10 +63,11 @@ namespace internal { class FuzzTestFuzzer { public: virtual ~FuzzTestFuzzer() = default; - virtual void RunInUnitTestMode(const Configuration& configuration) = 0; - // Returns fuzzing mode's exit code. Zero indicates success. - virtual int RunInFuzzingMode(int* argc, char*** argv, - const Configuration& configuration) = 0; + // Returns ture if no error were detected by the FuzzTest, false otherwise. + virtual bool RunInUnitTestMode(const Configuration& configuration) = 0; + // Returns ture if no error were detected by the FuzzTest, false otherwise. + virtual bool RunInFuzzingMode(int* argc, char*** argv, + const Configuration& configuration) = 0; }; class FuzzTest; @@ -280,11 +281,11 @@ class FuzzTestFuzzerImpl : public FuzzTestFuzzer { private: // TODO(fniksic): Refactor to reduce code complexity and improve readability. - void RunInUnitTestMode(const Configuration& configuration) override; + bool RunInUnitTestMode(const Configuration& configuration) override; // TODO(fniksic): Refactor to reduce code complexity and improve readability. - int RunInFuzzingMode(int* argc, char*** argv, - const Configuration& configuration) override; + bool RunInFuzzingMode(int* argc, char*** argv, + const Configuration& configuration) override; // Use the standard PRNG instead of absl::BitGen because Abseil doesn't // guarantee seed stability