#Centipede Skip re-executing inputs one-by-one when there is only one input executed in a batch. PiperOrigin-RevId: 558442322
diff --git a/centipede/centipede.cc b/centipede/centipede.cc index 889d6f6..e581a84 100644 --- a/centipede/centipede.cc +++ b/centipede/centipede.cc
@@ -745,6 +745,23 @@ } } +void Centipede::ReportCrashInput(const ByteArray &input, + const BatchResult &crash_result) { + const auto hash = Hash(input); + const auto crash_dir = env_.MakeCrashReproducerDirPath(); + RemoteMkdir(crash_dir); + const std::string file_path = std::filesystem::path(crash_dir).append(hash); + LOG(INFO) << "Detected crash-reproducing input:" + << "\nInput bytes : " << AsString(input, /*max_len=*/32) + << "\nExit code : " << crash_result.exit_code() + << "\nFailure : " << crash_result.failure_description() + << "\nSaving input to: " << file_path; + auto *file = RemoteFileOpen(file_path, "w"); // overwrites existing file. + CHECK(file != nullptr) << __FUNCTION__ << ": Failed to open " << file_path; + RemoteFileAppend(file, input); + RemoteFileClose(file); +} + void Centipede::ReportCrash(std::string_view binary, const std::vector<ByteArray> &input_vec, const BatchResult &batch_result) { @@ -752,6 +769,10 @@ if (EarlyExitRequested()) return; if (++num_crashes_ > env_.max_num_crash_reports) return; + if (input_vec.size() == 1) { + ReportCrashInput(input_vec[0], batch_result); + return; + } const size_t suspect_input_idx = std::clamp<size_t>( batch_result.num_outputs_read(), 0, input_vec.size() - 1); @@ -803,21 +824,8 @@ const auto &one_input = input_vec[input_idx]; BatchResult one_input_batch_result; if (!user_callbacks_.Execute(binary, {one_input}, one_input_batch_result)) { - auto hash = Hash(one_input); - auto crash_dir = env_.MakeCrashReproducerDirPath(); - RemoteMkdir(crash_dir); - std::string file_path = std::filesystem::path(crash_dir).append(hash); - LOG(INFO) << log_prefix << "Detected crash-reproducing input:" - << "\nInput index : " << input_idx - << "\nInput bytes : " << AsString(one_input, /*max_len=*/32) - << "\nExit code : " << one_input_batch_result.exit_code() - << "\nFailure : " - << one_input_batch_result.failure_description() - << "\nSaving input to: " << file_path; - auto *file = RemoteFileOpen(file_path, "w"); // overwrites existing file. - CHECK(file != nullptr) << log_prefix << "Failed to open " << file_path; - RemoteFileAppend(file, one_input); - RemoteFileClose(file); + LOG(INFO) << log_prefix << "Found reproducer at index " << input_idx; + ReportCrashInput(one_input, one_input_batch_result); return; } }
diff --git a/centipede/centipede.h b/centipede/centipede.h index 42ae886..007f267 100644 --- a/centipede/centipede.h +++ b/centipede/centipede.h
@@ -130,13 +130,16 @@ bool ExecuteAndReportCrash(std::string_view binary, const std::vector<ByteArray> &input_vec, BatchResult &batch_result); - // Reports a crash and saves the reproducer to workdir/crashes, if possible. - // `binary` is the binary causing the crash. - // Prints the first `env_.max_num_crash_reports` logs. - // `input_vec` is the batch of inputs that caused a crash. - // `batch_result` contains the features computed for `input_vec` - // (batch_result.results().size() == input_vec.size()). `batch_result` is used - // as a hint when choosing which input to try first. + // Reports the crash of `input` with `crash_result` and saves the input to + // workdir/crashes. + void ReportCrashInput(const ByteArray &input, + const BatchResult &crash_result); + // Reports a crash from a batch and saves the reproducer to workdir/crashes, + // if possible. `binary` is the binary causing the crash. Prints the first + // `env_.max_num_crash_reports` logs. `input_vec` is the batch of inputs that + // caused a crash. `batch_result` contains the features computed for + // `input_vec` (batch_result.results().size() == input_vec.size()). + // `batch_result` is used as a hint when choosing which input to try first. // Stops early if `EarlyExitRequested()`. void ReportCrash(std::string_view binary, const std::vector<ByteArray> &input_vec,