#Centipede Add a flag to skip triaging inputs other than the suspect in a batch. This makes the crash reporting faster when running a batch (of a single input) is very slow. PiperOrigin-RevId: 639788747
diff --git a/centipede/centipede.cc b/centipede/centipede.cc index fcc9827..812cc6e 100644 --- a/centipede/centipede.cc +++ b/centipede/centipede.cc
@@ -833,17 +833,6 @@ << log_prefix << "Reached --max_num_crash_reports: further reports will be suppressed"; - // Determine the optimal order of the inputs to try to maximize the chances of - // finding the reproducer fast. - // TODO(b/274705740): When the bug is fixed, set `input_idxs_to_try`'s size to - // `suspect_input_idx + 1`. - std::vector<size_t> input_idxs_to_try(input_vec.size() + 1); - // Prioritize the presumed crasher by inserting it in front of everything - // else. However, do keep it at the old location, too, in case the target was - // primed for a crash by the sequence of inputs that preceded the crasher. - input_idxs_to_try.front() = suspect_input_idx; - std::iota(input_idxs_to_try.begin() + 1, input_idxs_to_try.end(), 0); - if (batch_result.failure_description() == kExecutionFailurePerBatchTimeout) { LOG(INFO) << log_prefix << "Failure applies to entire batch: not executing inputs " @@ -851,6 +840,25 @@ return; } + // Determine the optimal order of the inputs to try to maximize the chances of + // finding the reproducer fast. + std::vector<size_t> input_idxs_to_try; + // Prioritize the presumed crasher by inserting it in front of everything + // else. + input_idxs_to_try.push_back(suspect_input_idx); + if (!env_.batch_triage_suspect_only) { + // TODO(b/274705740): When the bug is fixed, set `input_idxs_to_try`'s size + // to `suspect_input_idx + 1`. + input_idxs_to_try.resize(input_vec.size() + 1); + // Keep the suspect at the old location, too, in case the target was + // primed for a crash by the sequence of inputs that preceded the crasher. + std::iota(input_idxs_to_try.begin() + 1, input_idxs_to_try.end(), 0); + } else { + LOG(INFO) + << log_prefix + << "Skip finding the reproducer from the inputs other than the suspect"; + } + // Try inputs one-by-one in the determined order. LOG(INFO) << log_prefix << "Executing inputs one-by-one, trying to find the reproducer";
diff --git a/centipede/centipede_test.cc b/centipede/centipede_test.cc index d4d1adb..afc2e6c 100644 --- a/centipede/centipede_test.cc +++ b/centipede/centipede_test.cc
@@ -696,11 +696,15 @@ } // Doesn't execute anything. - // Crash when 0th char of input to binary b1 equals 10, but only on 1st exec. + // Crash when 0th char of input to binary b1 equals `crashing_input_idx_`, but + // only on 1st exec. bool Execute(std::string_view binary, const std::vector<ByteArray> &inputs, BatchResult &batch_result) override { batch_result.ClearAndResize(inputs.size()); bool res = true; + if (!first_pass_) { + num_inputs_triaged_ += inputs.size(); + } for (const auto &input : inputs) { CHECK_EQ(input.size(), 1); // By construction in `Mutate()`. // The contents of each mutant is its sequential number. @@ -739,9 +743,12 @@ // Gets the input that triggered the crash. ByteArray crashing_input() const { return crashing_input_; } + size_t num_inputs_triaged() const { return num_inputs_triaged_; } + private: const size_t crashing_input_idx_; size_t curr_input_idx_ = 0; + size_t num_inputs_triaged_ = 0; ByteArray crashing_input_ = {}; bool first_pass_ = true; }; @@ -768,6 +775,7 @@ env.batch_size = kBatchSize; // No real binary: prevent attempts by Centipede to read a PCtable from it. env.require_pc_table = false; + env.exit_on_crash = true; UndetectedCrashingInputMock mock(env, kCrashingInputIdx); MockFactory factory(mock); @@ -783,14 +791,28 @@ .append("crashes") .append("crashing_batch-") .concat(crashing_input_hash); - ASSERT_TRUE(std::filesystem::exists(crashes_dir_path)) << crashes_dir_path; + EXPECT_TRUE(std::filesystem::exists(crashes_dir_path)) << crashes_dir_path; std::vector<std::string> found_crash_file_names; for (auto const &dir_ent : std::filesystem::directory_iterator(crashes_dir_path)) { found_crash_file_names.push_back(dir_ent.path().filename()); } // TODO(ussuri): Verify exact names/contents of the files, not just count. - ASSERT_EQ(found_crash_file_names.size(), kCrashingInputIdxInBatch + 1); + EXPECT_EQ(found_crash_file_names.size(), kCrashingInputIdxInBatch + 1); + // Suspected input first, then every input in the batch (including the + // suspected input again). + EXPECT_EQ(mock.num_inputs_triaged(), kBatchSize + 1); + + // Verify that when `env.batch_triage_suspect_only` is set, only triage the + // suspect. + TempDir suspect_only_temp_dir{test_info_->name()}; + env.workdir = suspect_only_temp_dir.path(); + env.batch_triage_suspect_only = true; + UndetectedCrashingInputMock suspect_only_mock(env, kCrashingInputIdx); + MockFactory suspect_only_factory(suspect_only_mock); + CentipedeMain(env, suspect_only_factory); + + EXPECT_EQ(suspect_only_mock.num_inputs_triaged(), 1); } TEST(Centipede, GetsSeedInputs) {
diff --git a/centipede/environment.h b/centipede/environment.h index 391ded1..47f4db6 100644 --- a/centipede/environment.h +++ b/centipede/environment.h
@@ -96,6 +96,7 @@ bool exit_on_crash = false; size_t max_num_crash_reports = 5; std::string minimize_crash_file_path; + bool batch_triage_suspect_only = false; size_t shmem_size_mb = 1024; bool use_posix_shmem = false; bool dry_run = false;
diff --git a/centipede/environment_flags.cc b/centipede/environment_flags.cc index a571d4c..8e3701a 100644 --- a/centipede/environment_flags.cc +++ b/centipede/environment_flags.cc
@@ -311,6 +311,10 @@ " inputs in workdir/crashes/." " --num_runs and --num_threads apply. " " Assumes local workdir."); +ABSL_FLAG(bool, batch_triage_suspect_only, + default_env->batch_triage_suspect_only, + "If set, triage the crash on only the suspected input in a crashing " + "batch. Otherwise, triage on all the executed inputs"); ABSL_FLAG(std::string, input_filter, default_env->input_filter, "Path to a tool that filters bad inputs. The tool is invoked as " "`input_filter INPUT_FILE` and should return 0 if the input is good " @@ -506,6 +510,8 @@ .exit_on_crash = absl::GetFlag(FLAGS_exit_on_crash), .max_num_crash_reports = absl::GetFlag(FLAGS_num_crash_reports), .minimize_crash_file_path = absl::GetFlag(FLAGS_minimize_crash), + .batch_triage_suspect_only = + absl::GetFlag(FLAGS_batch_triage_suspect_only), .shmem_size_mb = absl::GetFlag(FLAGS_shmem_size_mb), .use_posix_shmem = absl::GetFlag(FLAGS_use_posix_shmem), .dry_run = absl::GetFlag(FLAGS_dry_run),