[libFuzzer] start refactoring the Mutator and adding tests to it
[oota-llvm.git] / lib / Fuzzer / FuzzerMutate.cpp
index f537fa90fd8506f13bdcab44f70fffd3ec78058b..eec6475f9b8464cee515afa0b4af14a2f51e4dd5 100644 (file)
@@ -15,8 +15,8 @@
 
 namespace fuzzer {
 
-static char FlipRandomBit(char X) {
-  int Bit = rand() % 8;
+static char FlipRandomBit(char X, FuzzerRandomBase &Rand) {
+  int Bit = Rand(8);
   char Mask = 1 << Bit;
   char R;
   if (X & (1 << Bit))
@@ -27,41 +27,46 @@ static char FlipRandomBit(char X) {
   return R;
 }
 
-static char RandCh() {
-  if (rand() % 2) return rand();
+static char RandCh(FuzzerRandomBase &Rand) {
+  if (Rand.RandBool()) return Rand(256);
   const char *Special = "!*'();:@&=+$,/?%#[]123ABCxyz-`~.";
-  return Special[rand() % (sizeof(Special) - 1)];
+  return Special[Rand(sizeof(Special) - 1)];
+}
+
+size_t Mutate_EraseByte(uint8_t *Data, size_t Size, size_t MaxSize,
+                        FuzzerRandomBase &Rand) {
+  assert(Size);
+  if (Size == 1) return Size;
+  size_t Idx = Rand(Size);
+  // Erase Data[Idx].
+  memmove(Data + Idx, Data + Idx + 1, Size - Idx - 1);
+  return Size - 1;
 }
 
 // Mutates Data in place, returns new size.
-size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
+size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize,
+              FuzzerRandomBase &Rand) {
   assert(MaxSize > 0);
   assert(Size <= MaxSize);
   if (Size == 0) {
     for (size_t i = 0; i < MaxSize; i++)
-      Data[i] = RandCh();
+      Data[i] = RandCh(Rand);
     return MaxSize;
   }
   assert(Size > 0);
-  size_t Idx = rand() % Size;
-  switch (rand() % 3) {
-  case 0:
-    if (Size > 1) {
-      // Erase Data[Idx].
-      memmove(Data + Idx, Data + Idx + 1, Size - Idx - 1);
-      Size = Size - 1;
-    }
-    [[clang::fallthrough]];
+  size_t Idx = Rand(Size);
+  switch (Rand(3)) {
+  case 0: Size = Mutate_EraseByte(Data, Size, MaxSize, Rand); break;
   case 1:
     if (Size < MaxSize) {
       // Insert new value at Data[Idx].
       memmove(Data + Idx + 1, Data + Idx, Size - Idx);
-      Data[Idx] = RandCh();
+      Data[Idx] = RandCh(Rand);
     }
-    Data[Idx] = RandCh();
+    Data[Idx] = RandCh(Rand);
     break;
   case 2:
-    Data[Idx] = FlipRandomBit(Data[Idx]);
+    Data[Idx] = FlipRandomBit(Data[Idx], Rand);
     break;
   }
   assert(Size > 0);