f537fa90fd8506f13bdcab44f70fffd3ec78058b
[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) {
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() {
31   if (rand() % 2) return rand();
32   const char *Special = "!*'();:@&=+$,/?%#[]123ABCxyz-`~.";
33   return Special[rand() % (sizeof(Special) - 1)];
34 }
35
36 // Mutates Data in place, returns new size.
37 size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
38   assert(MaxSize > 0);
39   assert(Size <= MaxSize);
40   if (Size == 0) {
41     for (size_t i = 0; i < MaxSize; i++)
42       Data[i] = RandCh();
43     return MaxSize;
44   }
45   assert(Size > 0);
46   size_t Idx = rand() % Size;
47   switch (rand() % 3) {
48   case 0:
49     if (Size > 1) {
50       // Erase Data[Idx].
51       memmove(Data + Idx, Data + Idx + 1, Size - Idx - 1);
52       Size = Size - 1;
53     }
54     [[clang::fallthrough]];
55   case 1:
56     if (Size < MaxSize) {
57       // Insert new value at Data[Idx].
58       memmove(Data + Idx + 1, Data + Idx, Size - Idx);
59       Data[Idx] = RandCh();
60     }
61     Data[Idx] = RandCh();
62     break;
63   case 2:
64     Data[Idx] = FlipRandomBit(Data[Idx]);
65     break;
66   }
67   assert(Size > 0);
68   return Size;
69 }
70
71 }  // namespace fuzzer