[libFuzzer] add one more mutator: Mutate_ChangeASCIIInteger

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@247027 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Kostya Serebryany 2015-09-08 17:19:31 +00:00
parent 3d88beedef
commit 872c556fa8
3 changed files with 67 additions and 0 deletions

View File

@ -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);

View 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()) {
@ -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);

View File

@ -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));