[libFuzzer] add InsertRepeatedBytes and EraseBytes.

New mutation: InsertRepeatedBytes.
Updated mutation: EraseByte => EraseBytes.

This helps https://github.com/google/sanitizers/issues/710
where libFuzzer was not able to find a known bug.
Now it finds it in minutes.

Hopefully, the change is general enough to help other targets.

llvm-svn: 278687
diff --git a/llvm/lib/Fuzzer/test/CMakeLists.txt b/llvm/lib/Fuzzer/test/CMakeLists.txt
index cbc983e..2164086 100644
--- a/llvm/lib/Fuzzer/test/CMakeLists.txt
+++ b/llvm/lib/Fuzzer/test/CMakeLists.txt
@@ -81,6 +81,7 @@
   OneHugeAllocTest
   OutOfMemoryTest
   RepeatedMemcmp
+  RepeatedBytesTest
   SimpleCmpTest
   SimpleDictionaryTest
   SimpleFnAdapterTest
diff --git a/llvm/lib/Fuzzer/test/FuzzerUnittest.cpp b/llvm/lib/Fuzzer/test/FuzzerUnittest.cpp
index 3fd87e5..bcbd116 100644
--- a/llvm/lib/Fuzzer/test/FuzzerUnittest.cpp
+++ b/llvm/lib/Fuzzer/test/FuzzerUnittest.cpp
@@ -88,7 +88,7 @@
 typedef size_t (MutationDispatcher::*Mutator)(uint8_t *Data, size_t Size,
                                               size_t MaxSize);
 
-void TestEraseByte(Mutator M, int NumIter) {
+void TestEraseBytes(Mutator M, int NumIter) {
   std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
   fuzzer::EF = t.get();
   uint8_t REM0[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
@@ -99,6 +99,16 @@
   uint8_t REM5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x66, 0x77};
   uint8_t REM6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x77};
   uint8_t REM7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+
+  uint8_t REM8[6] = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+  uint8_t REM9[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
+  uint8_t REM10[6] = {0x00, 0x11, 0x22, 0x55, 0x66, 0x77};
+
+  uint8_t REM11[5] = {0x33, 0x44, 0x55, 0x66, 0x77};
+  uint8_t REM12[5] = {0x00, 0x11, 0x22, 0x33, 0x44};
+  uint8_t REM13[5] = {0x00, 0x44, 0x55, 0x66, 0x77};
+
+
   Random Rand(0);
   MutationDispatcher MD(Rand, {});
   int FoundMask = 0;
@@ -113,15 +123,23 @@
     if (NewSize == 7 && !memcmp(REM5, T, 7)) FoundMask |= 1 << 5;
     if (NewSize == 7 && !memcmp(REM6, T, 7)) FoundMask |= 1 << 6;
     if (NewSize == 7 && !memcmp(REM7, T, 7)) FoundMask |= 1 << 7;
+
+    if (NewSize == 6 && !memcmp(REM8, T, 6)) FoundMask |= 1 << 8;
+    if (NewSize == 6 && !memcmp(REM9, T, 6)) FoundMask |= 1 << 9;
+    if (NewSize == 6 && !memcmp(REM10, T, 6)) FoundMask |= 1 << 10;
+
+    if (NewSize == 5 && !memcmp(REM11, T, 5)) FoundMask |= 1 << 11;
+    if (NewSize == 5 && !memcmp(REM12, T, 5)) FoundMask |= 1 << 12;
+    if (NewSize == 5 && !memcmp(REM13, T, 5)) FoundMask |= 1 << 13;
   }
-  EXPECT_EQ(FoundMask, 255);
+  EXPECT_EQ(FoundMask, (1 << 14) - 1);
 }
 
-TEST(FuzzerMutate, EraseByte1) {
-  TestEraseByte(&MutationDispatcher::Mutate_EraseByte, 100);
+TEST(FuzzerMutate, EraseBytes1) {
+  TestEraseBytes(&MutationDispatcher::Mutate_EraseBytes, 200);
 }
-TEST(FuzzerMutate, EraseByte2) {
-  TestEraseByte(&MutationDispatcher::Mutate, 1000);
+TEST(FuzzerMutate, EraseBytes2) {
+  TestEraseBytes(&MutationDispatcher::Mutate, 2000);
 }
 
 void TestInsertByte(Mutator M, int NumIter) {
@@ -160,6 +178,50 @@
   TestInsertByte(&MutationDispatcher::Mutate, 1 << 17);
 }
 
+void TestInsertRepeatedBytes(Mutator M, int NumIter) {
+  std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+  fuzzer::EF = t.get();
+  Random Rand(0);
+  MutationDispatcher MD(Rand, {});
+  int FoundMask = 0;
+  uint8_t INS0[7] = {0x00, 0x11, 0x22, 0x33, 'a', 'a', 'a'};
+  uint8_t INS1[7] = {0x00, 0x11, 0x22, 'a', 'a', 'a', 0x33};
+  uint8_t INS2[7] = {0x00, 0x11, 'a', 'a', 'a', 0x22, 0x33};
+  uint8_t INS3[7] = {0x00, 'a', 'a', 'a', 0x11, 0x22, 0x33};
+  uint8_t INS4[7] = {'a', 'a', 'a', 0x00, 0x11, 0x22, 0x33};
+
+  uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 'b', 'b', 'b', 'b'};
+  uint8_t INS6[8] = {0x00, 0x11, 0x22, 'b', 'b', 'b', 'b', 0x33};
+  uint8_t INS7[8] = {0x00, 0x11, 'b', 'b', 'b', 'b', 0x22, 0x33};
+  uint8_t INS8[8] = {0x00, 'b', 'b', 'b', 'b', 0x11, 0x22, 0x33};
+  uint8_t INS9[8] = {'b', 'b', 'b', 'b', 0x00, 0x11, 0x22, 0x33};
+
+  for (int i = 0; i < NumIter; i++) {
+    uint8_t T[8] = {0x00, 0x11, 0x22, 0x33};
+    size_t NewSize = (MD.*M)(T, 4, 8);
+    if (NewSize == 7 && !memcmp(INS0, T, 7)) FoundMask |= 1 << 0;
+    if (NewSize == 7 && !memcmp(INS1, T, 7)) FoundMask |= 1 << 1;
+    if (NewSize == 7 && !memcmp(INS2, T, 7)) FoundMask |= 1 << 2;
+    if (NewSize == 7 && !memcmp(INS3, T, 7)) FoundMask |= 1 << 3;
+    if (NewSize == 7 && !memcmp(INS4, T, 7)) FoundMask |= 1 << 4;
+
+    if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5;
+    if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6;
+    if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7;
+    if (NewSize == 8 && !memcmp(INS8, T, 8)) FoundMask |= 1 << 8;
+    if (NewSize == 8 && !memcmp(INS9, T, 8)) FoundMask |= 1 << 9;
+
+  }
+  EXPECT_EQ(FoundMask, (1 << 10) - 1);
+}
+
+TEST(FuzzerMutate, InsertRepeatedBytes1) {
+  TestInsertRepeatedBytes(&MutationDispatcher::Mutate_InsertRepeatedBytes, 10000);
+}
+TEST(FuzzerMutate, InsertRepeatedBytes2) {
+  TestInsertRepeatedBytes(&MutationDispatcher::Mutate, 200000);
+}
+
 void TestChangeByte(Mutator M, int NumIter) {
   std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
   fuzzer::EF = t.get();
diff --git a/llvm/lib/Fuzzer/test/RepeatedBytesTest.cpp b/llvm/lib/Fuzzer/test/RepeatedBytesTest.cpp
new file mode 100644
index 0000000..2fa6c78
--- /dev/null
+++ b/llvm/lib/Fuzzer/test/RepeatedBytesTest.cpp
@@ -0,0 +1,29 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find repeated bytes.
+#include <assert.h>
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <iostream>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+  assert(Data);
+  // Looking for AAAAAAAAAAAAAAAAAAAAAA or some such.
+  size_t CurA = 0, MaxA = 0;
+  for (size_t i = 0; i < Size; i++) {
+    // Make sure there are no conditionals in the loop so that
+    // coverage can't help the fuzzer.
+    int EQ = Data[i] == 'A';
+    CurA = EQ * (CurA + 1);
+    int GT = CurA > MaxA;
+    MaxA = GT * CurA + (!GT) * MaxA;
+  }
+  if (MaxA >= 20) {
+    std::cout << "BINGO; Found the target (Max: " << MaxA << "), exiting\n";
+    exit(0);
+  }
+  return 0;
+}
+
diff --git a/llvm/lib/Fuzzer/test/StrcmpTest.cpp b/llvm/lib/Fuzzer/test/StrcmpTest.cpp
index 5a13299..cd91dda 100644
--- a/llvm/lib/Fuzzer/test/StrcmpTest.cpp
+++ b/llvm/lib/Fuzzer/test/StrcmpTest.cpp
@@ -20,9 +20,9 @@
 }
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
-  if (Eq(Data, Size, "AAA") &&
-      Size >= 3 && Eq(Data + 3, Size - 3, "BBBB") &&
-      Size >= 7 && Eq(Data + 7, Size - 7, "CCCCCC") &&
+  if (Eq(Data, Size, "ABC") &&
+      Size >= 3 && Eq(Data + 3, Size - 3, "QWER") &&
+      Size >= 7 && Eq(Data + 7, Size - 7, "ZXCVN") &&
       Size >= 14 && Data[13] == 42
     ) {
     fprintf(stderr, "BINGO\n");
diff --git a/llvm/lib/Fuzzer/test/fuzzer-traces.test b/llvm/lib/Fuzzer/test/fuzzer-traces.test
index 2d77295..13f82ca 100644
--- a/llvm/lib/Fuzzer/test/fuzzer-traces.test
+++ b/llvm/lib/Fuzzer/test/fuzzer-traces.test
@@ -1,9 +1,10 @@
 CHECK: BINGO
 Done1000000: Done 1000000 runs in
+Done2000000: Done 2000000 runs in
 RUN: not LLVMFuzzer-SimpleCmpTest -use_traces=1 -seed=1 -runs=10000001  2>&1 | FileCheck %s
 
 RUN: not LLVMFuzzer-SwitchTest -use_traces=1 -seed=6 -runs=1000002  2>&1 | FileCheck %s
 RUN:     LLVMFuzzer-SwitchTest               -seed=7 -runs=1000000  2>&1 | FileCheck %s --check-prefix=Done1000000
 
-RUN: not LLVMFuzzer-SimpleHashTest -use_traces=1 -seed=8 -runs=1000000 -max_len=16  2>&1 | FileCheck %s
-RUN:     LLVMFuzzer-SimpleHashTest               -seed=9 -runs=1000000 -max_len=16 2>&1 | FileCheck %s --check-prefix=Done1000000
+RUN: not LLVMFuzzer-SimpleHashTest -use_traces=1 -seed=8 -runs=2000000 -max_len=16  2>&1 | FileCheck %s
+RUN:     LLVMFuzzer-SimpleHashTest               -seed=9 -runs=2000000 -max_len=16 2>&1 | FileCheck %s --check-prefix=Done2000000
diff --git a/llvm/lib/Fuzzer/test/repeated-bytes.test b/llvm/lib/Fuzzer/test/repeated-bytes.test
new file mode 100644
index 0000000..edcba83
--- /dev/null
+++ b/llvm/lib/Fuzzer/test/repeated-bytes.test
@@ -0,0 +1,2 @@
+CHECK: BINGO
+RUN: LLVMFuzzer-RepeatedBytesTest -runs=10000 2>&1 | FileCheck %s