Fix a crash when all corpus inputs have no feature.

This can occur when features become "frequent" enough that they get removed from the corpus inputs' feature lists.

PiperOrigin-RevId: 834769613
diff --git a/centipede/corpus.cc b/centipede/corpus.cc
index 4363b24..c274691 100644
--- a/centipede/corpus.cc
+++ b/centipede/corpus.cc
@@ -175,6 +175,13 @@
       max_corpus_size, std::max(1UL, records_.size() - num_zero_weights));
   auto subset_to_remove =
       weighted_distribution_.RemoveRandomWeightedSubset(target_size, rng);
+  if (subset_to_remove.size() == records_.size()) {
+    // This can happen only when all inputs have zero weights - keep random one.
+    FUZZTEST_CHECK(num_zero_weights == records_.size());
+    subset_to_remove.erase(
+        subset_to_remove.begin() +
+        absl::Uniform<size_t>(rng, 0, subset_to_remove.size()));
+  }
   RemoveSubset(subset_to_remove, records_);
 
   weighted_distribution_.RecomputeInternalState();
diff --git a/centipede/corpus_test.cc b/centipede/corpus_test.cc
index a75ddb0..f816f46 100644
--- a/centipede/corpus_test.cc
+++ b/centipede/corpus_test.cc
@@ -194,6 +194,24 @@
   EXPECT_GT(freq[1], freq[2] + 100);
 }
 
+TEST(Corpus, PruneCorpusWithAllEmptyFeatureInputs) {
+  PCTable pc_table(100);
+  CFTable cf_table(100);
+  BinaryInfo bin_info{pc_table, {}, cf_table, {}, {}, {}};
+  CoverageFrontier coverage_frontier(bin_info);
+  FeatureSet fs(1, {});
+  Corpus corpus;
+  Rng rng;
+  size_t max_corpus_size = 1000;
+
+  corpus.Add(/*data=*/{1}, /*fv=*/{}, /*metadata=*/{}, /*stats=*/{}, fs,
+             coverage_frontier);
+  corpus.Add(/*data=*/{2}, /*fv=*/{}, /*metadata=*/{}, /*stats=*/{}, fs,
+             coverage_frontier);
+  // Should not crash.
+  corpus.Prune(fs, coverage_frontier, max_corpus_size, rng);
+}
+
 // Regression test for a crash in Corpus::Prune().
 TEST(Corpus, PruneRegressionTest1) {
   PCTable pc_table(100);