blob: fc3176299c9144a9146f71e56933b3d79868ae57 [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
16namespace fuzzer {
17
Kostya Serebryany404c69f2015-07-24 01:06:40 +000018static char FlipRandomBit(char X, FuzzerRandomBase &Rand) {
19 int Bit = Rand(8);
Aaron Ballmanef116982015-01-29 16:58:29 +000020 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
Kostya Serebryany404c69f2015-07-24 01:06:40 +000030static char RandCh(FuzzerRandomBase &Rand) {
31 if (Rand.RandBool()) return Rand(256);
Aaron Ballmanef116982015-01-29 16:58:29 +000032 const char *Special = "!*'();:@&=+$,/?%#[]123ABCxyz-`~.";
Kostya Serebryany404c69f2015-07-24 01:06:40 +000033 return Special[Rand(sizeof(Special) - 1)];
Aaron Ballmanef116982015-01-29 16:58:29 +000034}
35
Kostya Serebryany8ce74242015-08-01 01:42:51 +000036size_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
Kostya Serebryany86a5fba2015-08-01 02:23:06 +000046size_t Mutate_InsertByte(uint8_t *Data, size_t Size, size_t MaxSize,
47 FuzzerRandomBase &Rand) {
48 if (Size == MaxSize) return Size;
49 size_t Idx = Rand(Size + 1);
50 // Insert new value at Data[Idx].
51 memmove(Data + Idx + 1, Data + Idx, Size - Idx);
52 Data[Idx] = RandCh(Rand);
53 return Size + 1;
54}
55
56size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize,
57 FuzzerRandomBase &Rand) {
58 size_t Idx = Rand(Size);
59 Data[Idx] = RandCh(Rand);
60 return Size;
61}
62
63size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize,
64 FuzzerRandomBase &Rand) {
65 size_t Idx = Rand(Size);
66 Data[Idx] = FlipRandomBit(Data[Idx], Rand);
67 return Size;
68}
69
Kostya Serebryanyf3424592015-05-22 22:35:31 +000070// Mutates Data in place, returns new size.
Kostya Serebryany404c69f2015-07-24 01:06:40 +000071size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize,
72 FuzzerRandomBase &Rand) {
Kostya Serebryanyf3424592015-05-22 22:35:31 +000073 assert(MaxSize > 0);
74 assert(Size <= MaxSize);
75 if (Size == 0) {
76 for (size_t i = 0; i < MaxSize; i++)
Kostya Serebryany404c69f2015-07-24 01:06:40 +000077 Data[i] = RandCh(Rand);
Kostya Serebryanyf3424592015-05-22 22:35:31 +000078 return MaxSize;
Kostya Serebryany5b266a82015-02-04 19:10:20 +000079 }
Kostya Serebryanyf3424592015-05-22 22:35:31 +000080 assert(Size > 0);
Kostya Serebryany86a5fba2015-08-01 02:23:06 +000081 switch (Rand(4)) {
Kostya Serebryany8ce74242015-08-01 01:42:51 +000082 case 0: Size = Mutate_EraseByte(Data, Size, MaxSize, Rand); break;
Kostya Serebryany86a5fba2015-08-01 02:23:06 +000083 case 1: Size = Mutate_InsertByte(Data, Size, MaxSize, Rand); break;
84 case 2: Size = Mutate_ChangeByte(Data, Size, MaxSize, Rand); break;
85 case 3: Size = Mutate_ChangeBit(Data, Size, MaxSize, Rand); break;
Aaron Ballmanef116982015-01-29 16:58:29 +000086 }
Kostya Serebryanyf3424592015-05-22 22:35:31 +000087 assert(Size > 0);
88 return Size;
Aaron Ballmanef116982015-01-29 16:58:29 +000089}
90
91} // namespace fuzzer