#Centipede Clean up cmp traces on coverage cleanup.

This particularly improves the FuzzTest/Centipede single-process integration, where the fuzzing engine would generate noise to the cmps traces and make the mutation less effective if the noise is not cleaned up.

PiperOrigin-RevId: 596940201
diff --git a/centipede/BUILD b/centipede/BUILD
index 12ebb71..b89a6a8 100644
--- a/centipede/BUILD
+++ b/centipede/BUILD
@@ -1628,6 +1628,7 @@
     srcs = ["centipede_test.cc"],
     data = [
         "@com_google_fuzztest//centipede/testing:abort_fuzz_target",
+        "@com_google_fuzztest//centipede/testing:expensive_startup_fuzz_target",
         "@com_google_fuzztest//centipede/testing:seeded_fuzz_target",
         "@com_google_fuzztest//centipede/testing:test_fuzz_target",
         "@com_google_fuzztest//centipede/testing:test_input_filter",
diff --git a/centipede/centipede_test.cc b/centipede/centipede_test.cc
index d77d42f..21065b6 100644
--- a/centipede/centipede_test.cc
+++ b/centipede/centipede_test.cc
@@ -864,4 +864,22 @@
                          {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}}));
 }
 
+TEST(Centipede, CleansUpMetadataAfterStartup) {
+  Environment env;
+  env.binary = GetDataDependencyFilepath(
+      "centipede/testing/expensive_startup_fuzz_target");
+  CentipedeDefaultCallbacks callbacks(env);
+  BatchResult batch_result;
+  const std::vector<ByteArray> inputs = {{0}};
+  ASSERT_TRUE(callbacks.Execute(env.binary, inputs, batch_result));
+  ASSERT_EQ(batch_result.results().size(), 1);
+  bool found_startup_cmp_entry = false;
+  batch_result.results()[0].metadata().ForEachCmpEntry(
+      [&](ByteSpan a, ByteSpan b) {
+        if (a == ByteArray{'F', 'u', 'z', 'z'}) found_startup_cmp_entry = true;
+        if (b == ByteArray{'F', 'u', 'z', 'z'}) found_startup_cmp_entry = true;
+      });
+  EXPECT_FALSE(found_startup_cmp_entry);
+}
+
 }  // namespace centipede
diff --git a/centipede/runner.cc b/centipede/runner.cc
index 3427bc8..4e1ab3f 100644
--- a/centipede/runner.cc
+++ b/centipede/runner.cc
@@ -378,8 +378,15 @@
       tls.lowest_sp = tls.top_frame_sp;
     });
   }
-  // TODO(kcc): do we need to clear tls.cmp_trace2 and others here?
   if (!full_clear) return;
+  state.ForEachTls([](ThreadLocalRunnerState &tls) {
+    if (state.run_time_flags.use_auto_dictionary) {
+      tls.cmp_trace2.Clear();
+      tls.cmp_trace4.Clear();
+      tls.cmp_trace8.Clear();
+      tls.cmp_traceN.Clear();
+    }
+  });
   state.pc_counter_set.ForEachNonZeroByte([](size_t idx, uint8_t value) {});
   if (state.run_time_flags.use_dataflow_features)
     state.data_flow_feature_set.ForEachNonZeroBit([](size_t idx) {});
diff --git a/centipede/testing/expensive_startup_fuzz_target.cc b/centipede/testing/expensive_startup_fuzz_target.cc
index 354f5e1..61d5b8e 100644
--- a/centipede/testing/expensive_startup_fuzz_target.cc
+++ b/centipede/testing/expensive_startup_fuzz_target.cc
@@ -15,16 +15,20 @@
 #include <cstddef>
 #include <cstdint>
 #include <cstdio>
+#include <cstring>
 
 static int sink;
 
 // Instrumented function that runs at startup. We want it's coverage ignored.
-__attribute__((constructor, noinline)) void Startup() {
+__attribute__((constructor, noinline, optnone)) void Startup() {
   fprintf(stderr, "Startup\n");
   // Function entry: generate a coverage feature.
   sink++;                    // generate data flow feature
   if (sink == (sink == 42))  // generate some cmp features
     Startup();
+  char str[] = {'F', 'u', 'z', 'z'};
+  if (memcmp(str, "Null", 4) == 0)  // generate some cmp traces
+    Startup();
 }
 
 // A fuzz target used for testing Centipede.