#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,