[PGO] Define value profiling updater API signature in InstrProfData.inc (NFC)
[oota-llvm.git] / lib / Fuzzer / FuzzerMutate.cpp
index 70fa88da30a3391ef7f67badb0c3003e4c04ef0f..74ae0cbb75a3a8bca543574892ff38ad4b7488c3 100644 (file)
@@ -29,6 +29,7 @@ struct MutationDispatcher::Impl {
     Mutators.push_back(&MutationDispatcher::Mutate_ChangeByte);
     Mutators.push_back(&MutationDispatcher::Mutate_ChangeBit);
     Mutators.push_back(&MutationDispatcher::Mutate_ShuffleBytes);
+    Mutators.push_back(&MutationDispatcher::Mutate_ChangeASCIIInteger);
   }
   void AddWordToDictionary(const uint8_t *Word, size_t Size) {
     if (Dictionary.empty()) {
@@ -60,7 +61,7 @@ static char RandCh(FuzzerRandomBase &Rand) {
 size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size,
                                                size_t MaxSize) {
   assert(Size);
-  size_t ShuffleAmount = Rand(std::min(Size, 8UL)) + 1;  // [1,8] and <= Size.
+  size_t ShuffleAmount = Rand(std::min(Size, (size_t)8)) + 1;  // [1,8] and <= Size.
   size_t ShuffleStart = Rand(Size - ShuffleAmount);
   assert(ShuffleStart + ShuffleAmount <= Size);
   std::random_shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount,
@@ -71,7 +72,7 @@ size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size,
 size_t MutationDispatcher::Mutate_EraseByte(uint8_t *Data, size_t Size,
                                             size_t MaxSize) {
   assert(Size);
-  if (Size == 1) return Size;
+  if (Size == 1) return 0;
   size_t Idx = Rand(Size);
   // Erase Data[Idx].
   memmove(Data + Idx, Data + Idx + 1, Size - Idx - 1);
@@ -80,7 +81,7 @@ size_t MutationDispatcher::Mutate_EraseByte(uint8_t *Data, size_t Size,
 
 size_t MutationDispatcher::Mutate_InsertByte(uint8_t *Data, size_t Size,
                                              size_t MaxSize) {
-  if (Size == MaxSize) return Size;
+  if (Size == MaxSize) return 0;
   size_t Idx = Rand(Size + 1);
   // Insert new value at Data[Idx].
   memmove(Data + Idx + 1, Data + Idx, Size - Idx);
@@ -106,15 +107,49 @@ size_t MutationDispatcher::Mutate_AddWordFromDictionary(uint8_t *Data,
                                                         size_t Size,
                                                         size_t MaxSize) {
   auto &D = MDImpl->Dictionary;
-  if (D.empty()) return Size;  // FIXME: indicate failure.
+  assert(!D.empty());
+  if (D.empty()) return 0;
   const Unit &Word = D[Rand(D.size())];
-  if (Size + Word.size() > MaxSize) return Size;
+  if (Size + Word.size() > MaxSize) return 0;
   size_t Idx = Rand(Size + 1);
   memmove(Data + Idx + Word.size(), Data + Idx, Size - Idx);
   memcpy(Data + Idx, Word.data(), Word.size());
   return Size + Word.size();
 }
 
+size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size,
+                                                     size_t MaxSize) {
+  size_t B = Rand(Size);
+  while (B < Size && !isdigit(Data[B])) B++;
+  if (B == Size) return 0;
+  size_t E = B;
+  while (E < Size && isdigit(Data[E])) E++;
+  assert(B < E);
+  // now we have digits in [B, E).
+  // strtol and friends don't accept non-zero-teminated data, parse it manually.
+  uint64_t Val = Data[B] - '0';
+  for (size_t i = B + 1; i < E; i++)
+    Val = Val * 10 + Data[i] - '0';
+
+  // Mutate the integer value.
+  switch(Rand(5)) {
+    case 0: Val++; break;
+    case 1: Val--; break;
+    case 2: Val /= 2; break;
+    case 3: Val *= 2; break;
+    case 4: Val = Rand(Val * Val); break;
+    default: assert(0);
+  }
+  // Just replace the bytes with the new ones, don't bother moving bytes.
+  for (size_t i = B; i < E; i++) {
+    size_t Idx = E + B - i - 1;
+    assert(Idx >= B && Idx < E);
+    Data[Idx] = (Val % 10) + '0';
+    Val /= 10;
+  }
+  return Size;
+}
+
 // Mutates Data in place, returns new size.
 size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
   assert(MaxSize > 0);
@@ -125,9 +160,15 @@ size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
     return MaxSize;
   }
   assert(Size > 0);
-  size_t MutatorIdx = Rand(MDImpl->Mutators.size());
-  Size = (this->*(MDImpl->Mutators[MutatorIdx]))(Data, Size, MaxSize);
-  assert(Size > 0);
+  // Some mutations may fail (e.g. can't insert more bytes if Size == MaxSize),
+  // in which case they will return 0.
+  // Try several times before returning un-mutated data.
+  for (int Iter = 0; Iter < 10; Iter++) {
+    size_t MutatorIdx = Rand(MDImpl->Mutators.size());
+    size_t NewSize =
+        (this->*(MDImpl->Mutators[MutatorIdx]))(Data, Size, MaxSize);
+    if (NewSize) return NewSize;
+  }
   return Size;
 }