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()) {
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);
TestAddWordFromDictionary(&MutationDispatcher::Mutate, 1 << 15);
}
+void TestChangeASCIIInteger(Mutator M, int NumIter) {
+ FuzzerRandomLibc Rand(0);
+ MutationDispatcher MD(Rand);
+
+ uint8_t CH0[8] = {'1', '2', '3', '4', '5', '6', '7', '7'};
+ uint8_t CH1[8] = {'1', '2', '3', '4', '5', '6', '7', '9'};
+ uint8_t CH2[8] = {'2', '4', '6', '9', '1', '3', '5', '6'};
+ uint8_t CH3[8] = {'0', '6', '1', '7', '2', '8', '3', '9'};
+ int FoundMask = 0;
+ for (int i = 0; i < NumIter; i++) {
+ uint8_t T[8] = {'1', '2', '3', '4', '5', '6', '7', '8'};
+ size_t NewSize = (MD.*M)(T, 8, 8);
+ /**/ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
+ else if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
+ else if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
+ else if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
+ else if (NewSize == 8) FoundMask |= 1 << 4;
+ }
+ EXPECT_EQ(FoundMask, 31);
+}
+
+TEST(FuzzerMutate, ChangeASCIIInteger1) {
+ TestChangeASCIIInteger(&MutationDispatcher::Mutate_ChangeASCIIInteger,
+ 1 << 15);
+}
+
+TEST(FuzzerMutate, ChangeASCIIInteger2) {
+ TestChangeASCIIInteger(&MutationDispatcher::Mutate, 1 << 15);
+}
+
+
TEST(FuzzerDictionary, ParseOneDictionaryEntry) {
Unit U;
EXPECT_FALSE(ParseOneDictionaryEntry("", &U));