[libFuzzer] start refactoring the Mutator and adding tests to it
[oota-llvm.git] / lib / Fuzzer / FuzzerMutate.cpp
1 //===- FuzzerMutate.cpp - Mutate a test input -----------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 // Mutate a test input.
10 //===----------------------------------------------------------------------===//
11
12 #include <cstring>
13
14 #include "FuzzerInternal.h"
15
16 namespace fuzzer {
17
18 static char FlipRandomBit(char X, FuzzerRandomBase &Rand) {
19   int Bit = Rand(8);
20   char Mask = 1 << Bit;
21   char R;
22   if (X & (1 << Bit))
23     R = X & ~Mask;
24   else
25     R = X | Mask;
26   assert(R != X);
27   return R;
28 }
29
30 static char RandCh(FuzzerRandomBase &Rand) {
31   if (Rand.RandBool()) return Rand(256);
32   const char *Special = "!*'();:@&=+$,/?%#[]123ABCxyz-`~.";
33   return Special[Rand(sizeof(Special) - 1)];
34 }
35
36 size_t Mutate_EraseByte(uint8_t *Data, size_t Size, size_t MaxSize,
37                         FuzzerRandomBase &Rand) {
38   assert(Size);
39   if (Size == 1) return Size;
40   size_t Idx = Rand(Size);
41   // Erase Data[Idx].
42   memmove(Data + Idx, Data + Idx + 1, Size - Idx - 1);
43   return Size - 1;
44 }
45
46 // Mutates Data in place, returns new size.
47 size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize,
48               FuzzerRandomBase &Rand) {
49   assert(MaxSize > 0);
50   assert(Size <= MaxSize);
51   if (Size == 0) {
52     for (size_t i = 0; i < MaxSize; i++)
53       Data[i] = RandCh(Rand);
54     return MaxSize;
55   }
56   assert(Size > 0);
57   size_t Idx = Rand(Size);
58   switch (Rand(3)) {
59   case 0: Size = Mutate_EraseByte(Data, Size, MaxSize, Rand); break;
60   case 1:
61     if (Size < MaxSize) {
62       // Insert new value at Data[Idx].
63       memmove(Data + Idx + 1, Data + Idx, Size - Idx);
64       Data[Idx] = RandCh(Rand);
65     }
66     Data[Idx] = RandCh(Rand);
67     break;
68   case 2:
69     Data[Idx] = FlipRandomBit(Data[Idx], Rand);
70     break;
71   }
72   assert(Size > 0);
73   return Size;
74 }
75
76 }  // namespace fuzzer