blob: c425ae0c1cdd970f6316d0aa46dac7d41b89e062 [file] [log] [blame]
Aaron Ballmanef116982015-01-29 16:58:29 +00001//===- 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
Kostya Serebryanyf3424592015-05-22 22:35:31 +000012#include <cstring>
13
Aaron Ballmanef116982015-01-29 16:58:29 +000014#include "FuzzerInternal.h"
15
Kostya Serebryanybf29ff22015-08-06 01:29:13 +000016#include <algorithm>
17
Aaron Ballmanef116982015-01-29 16:58:29 +000018namespace fuzzer {
19
Kostya Serebryany404c69f2015-07-24 01:06:40 +000020static char FlipRandomBit(char X, FuzzerRandomBase &Rand) {
21 int Bit = Rand(8);
Aaron Ballmanef116982015-01-29 16:58:29 +000022 char Mask = 1 << Bit;
23 char R;
24 if (X & (1 << Bit))
25 R = X & ~Mask;
26 else
27 R = X | Mask;
28 assert(R != X);
29 return R;
30}
31
Kostya Serebryany404c69f2015-07-24 01:06:40 +000032static char RandCh(FuzzerRandomBase &Rand) {
33 if (Rand.RandBool()) return Rand(256);
Aaron Ballmanef116982015-01-29 16:58:29 +000034 const char *Special = "!*'();:@&=+$,/?%#[]123ABCxyz-`~.";
Kostya Serebryany404c69f2015-07-24 01:06:40 +000035 return Special[Rand(sizeof(Special) - 1)];
Aaron Ballmanef116982015-01-29 16:58:29 +000036}
37
Kostya Serebryanybf29ff22015-08-06 01:29:13 +000038size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize,
39 FuzzerRandomBase &Rand) {
40 assert(Size);
41 size_t ShuffleAmount = Rand(std::min(Size, 8UL)) + 1; // [1,8] and <= Size.
42 size_t ShuffleStart = Rand(Size - ShuffleAmount);
43 assert(ShuffleStart + ShuffleAmount <= Size);
44 std::random_shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount,
45 Rand);
46 return Size;
47}
48
Kostya Serebryany8ce74242015-08-01 01:42:51 +000049size_t Mutate_EraseByte(uint8_t *Data, size_t Size, size_t MaxSize,
50 FuzzerRandomBase &Rand) {
51 assert(Size);
52 if (Size == 1) return Size;
53 size_t Idx = Rand(Size);
54 // Erase Data[Idx].
55 memmove(Data + Idx, Data + Idx + 1, Size - Idx - 1);
56 return Size - 1;
57}
58
Kostya Serebryany86a5fba2015-08-01 02:23:06 +000059size_t Mutate_InsertByte(uint8_t *Data, size_t Size, size_t MaxSize,
60 FuzzerRandomBase &Rand) {
61 if (Size == MaxSize) return Size;
62 size_t Idx = Rand(Size + 1);
63 // Insert new value at Data[Idx].
64 memmove(Data + Idx + 1, Data + Idx, Size - Idx);
65 Data[Idx] = RandCh(Rand);
66 return Size + 1;
67}
68
69size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize,
70 FuzzerRandomBase &Rand) {
71 size_t Idx = Rand(Size);
72 Data[Idx] = RandCh(Rand);
73 return Size;
74}
75
76size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize,
77 FuzzerRandomBase &Rand) {
78 size_t Idx = Rand(Size);
79 Data[Idx] = FlipRandomBit(Data[Idx], Rand);
80 return Size;
81}
82
Kostya Serebryanyf3424592015-05-22 22:35:31 +000083// Mutates Data in place, returns new size.
Kostya Serebryany404c69f2015-07-24 01:06:40 +000084size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize,
85 FuzzerRandomBase &Rand) {
Kostya Serebryanyf3424592015-05-22 22:35:31 +000086 assert(MaxSize > 0);
87 assert(Size <= MaxSize);
88 if (Size == 0) {
89 for (size_t i = 0; i < MaxSize; i++)
Kostya Serebryany404c69f2015-07-24 01:06:40 +000090 Data[i] = RandCh(Rand);
Kostya Serebryanyf3424592015-05-22 22:35:31 +000091 return MaxSize;
Kostya Serebryany5b266a82015-02-04 19:10:20 +000092 }
Kostya Serebryanyf3424592015-05-22 22:35:31 +000093 assert(Size > 0);
Kostya Serebryanybf29ff22015-08-06 01:29:13 +000094 switch (Rand(5)) {
Kostya Serebryany8ce74242015-08-01 01:42:51 +000095 case 0: Size = Mutate_EraseByte(Data, Size, MaxSize, Rand); break;
Kostya Serebryany86a5fba2015-08-01 02:23:06 +000096 case 1: Size = Mutate_InsertByte(Data, Size, MaxSize, Rand); break;
97 case 2: Size = Mutate_ChangeByte(Data, Size, MaxSize, Rand); break;
98 case 3: Size = Mutate_ChangeBit(Data, Size, MaxSize, Rand); break;
Kostya Serebryanybf29ff22015-08-06 01:29:13 +000099 case 4: Size = Mutate_ShuffleBytes(Data, Size, MaxSize, Rand); break;
Aaron Ballmanef116982015-01-29 16:58:29 +0000100 }
Kostya Serebryanyf3424592015-05-22 22:35:31 +0000101 assert(Size > 0);
102 return Size;
Aaron Ballmanef116982015-01-29 16:58:29 +0000103}
104
105} // namespace fuzzer