From 872c556fa864f7314d97bad9b32db89496b6919e Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Tue, 8 Sep 2015 17:19:31 +0000 Subject: [PATCH] [libFuzzer] add one more mutator: Mutate_ChangeASCIIInteger git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@247027 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Fuzzer/FuzzerInterface.h | 2 ++ lib/Fuzzer/FuzzerMutate.cpp | 34 ++++++++++++++++++++++++++++++ lib/Fuzzer/test/FuzzerUnittest.cpp | 31 +++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/lib/Fuzzer/FuzzerInterface.h b/lib/Fuzzer/FuzzerInterface.h index 8798b650383..d5af308be76 100644 --- a/lib/Fuzzer/FuzzerInterface.h +++ b/lib/Fuzzer/FuzzerInterface.h @@ -81,6 +81,8 @@ class MutationDispatcher { size_t Mutate_AddWordFromDictionary(uint8_t *Data, size_t Size, size_t MaxSize); + size_t Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, size_t MaxSize); + /// Applies one of the above mutations. /// Returns the new size of data which could be up to MaxSize. size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize); diff --git a/lib/Fuzzer/FuzzerMutate.cpp b/lib/Fuzzer/FuzzerMutate.cpp index 9b2015be869..0e8429bcb27 100644 --- a/lib/Fuzzer/FuzzerMutate.cpp +++ b/lib/Fuzzer/FuzzerMutate.cpp @@ -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()) { @@ -116,6 +117,39 @@ size_t MutationDispatcher::Mutate_AddWordFromDictionary(uint8_t *Data, 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); diff --git a/lib/Fuzzer/test/FuzzerUnittest.cpp b/lib/Fuzzer/test/FuzzerUnittest.cpp index 1a88aef3e1e..4a96468f8d7 100644 --- a/lib/Fuzzer/test/FuzzerUnittest.cpp +++ b/lib/Fuzzer/test/FuzzerUnittest.cpp @@ -282,6 +282,37 @@ TEST(FuzzerMutate, AddWordFromDictionary2) { 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)); -- 2.34.1