[libFuzzer] one more mutation: ChangeBinaryInteger; also fix the breakage from r278970

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278982 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Kostya Serebryany 2016-08-17 21:30:30 +00:00
parent 0a6e4fd5d3
commit 9744bb48e4
3 changed files with 77 additions and 2 deletions

View File

@ -290,6 +290,8 @@ public:
/// Tries to find an ASCII integer in Data, changes it to another ASCII int. /// Tries to find an ASCII integer in Data, changes it to another ASCII int.
size_t Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, size_t MaxSize); size_t Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, size_t MaxSize);
/// Change a 1-, 2-, 4-, or 8-byte integer in interesting ways.
size_t Mutate_ChangeBinaryInteger(uint8_t *Data, size_t Size, size_t MaxSize);
/// CrossOver Data with some other element of the corpus. /// CrossOver Data with some other element of the corpus.
size_t Mutate_CrossOver(uint8_t *Data, size_t Size, size_t MaxSize); size_t Mutate_CrossOver(uint8_t *Data, size_t Size, size_t MaxSize);

View File

@ -32,6 +32,7 @@ MutationDispatcher::MutationDispatcher(Random &Rand,
{&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"}, {&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"},
{&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"}, {&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"},
{&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"}, {&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"},
{&MutationDispatcher::Mutate_ChangeBinaryInteger, "ChangeBinInt"},
{&MutationDispatcher::Mutate_CopyPart, "CopyPart"}, {&MutationDispatcher::Mutate_CopyPart, "CopyPart"},
{&MutationDispatcher::Mutate_CrossOver, "CrossOver"}, {&MutationDispatcher::Mutate_CrossOver, "CrossOver"},
{&MutationDispatcher::Mutate_AddWordFromManualDictionary, {&MutationDispatcher::Mutate_AddWordFromManualDictionary,
@ -269,6 +270,42 @@ size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size,
return Size; return Size;
} }
uint8_t Bswap(uint8_t x) { return x; }
uint16_t Bswap(uint16_t x) { return __builtin_bswap16(x); }
uint32_t Bswap(uint32_t x) { return __builtin_bswap32(x); }
uint64_t Bswap(uint64_t x) { return __builtin_bswap64(x); }
template<class T>
size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand) {
if (Size < sizeof(T)) return 0;
size_t Off = Rand(Size - sizeof(T) + 1);
assert(Off + sizeof(T) <= Size);
T Val;
memcpy(&Val, Data + Off, sizeof(Val));
T Add = Rand(21);
Add -= 10;
if (Rand.RandBool())
Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endiannes.
else
Val = Val + Add; // Add assuming current endiannes.
if (Add == 0 || Rand.RandBool()) // Maybe negate.
Val = -Val;
memcpy(Data + Off, &Val, sizeof(Val));
return Size;
}
size_t MutationDispatcher::Mutate_ChangeBinaryInteger(uint8_t *Data,
size_t Size,
size_t MaxSize) {
switch (Rand(4)) {
case 3: return ChangeBinaryInteger<uint64_t>(Data, Size, Rand);
case 2: return ChangeBinaryInteger<uint32_t>(Data, Size, Rand);
case 1: return ChangeBinaryInteger<uint16_t>(Data, Size, Rand);
case 0: return ChangeBinaryInteger<uint8_t>(Data, Size, Rand);
default: assert(0);
}
}
size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size, size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size,
size_t MaxSize) { size_t MaxSize) {
if (!Corpus || Corpus->size() < 2 || Size == 0) return 0; if (!Corpus || Corpus->size() < 2 || Size == 0) return 0;
@ -286,7 +323,7 @@ size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size,
NewSize = InsertPartOf(O.data(), O.size(), U.data(), U.size(), MaxSize); NewSize = InsertPartOf(O.data(), O.size(), U.data(), U.size(), MaxSize);
if (NewSize) if (NewSize)
break; break;
LLVM_FALLTHROUGH; // LLVM_FALLTHROUGH;
case 2: case 2:
NewSize = CopyPartOf(O.data(), O.size(), U.data(), U.size()); NewSize = CopyPartOf(O.data(), O.size(), U.data(), U.size());
break; break;

View File

@ -219,7 +219,7 @@ TEST(FuzzerMutate, InsertRepeatedBytes1) {
TestInsertRepeatedBytes(&MutationDispatcher::Mutate_InsertRepeatedBytes, 10000); TestInsertRepeatedBytes(&MutationDispatcher::Mutate_InsertRepeatedBytes, 10000);
} }
TEST(FuzzerMutate, InsertRepeatedBytes2) { TEST(FuzzerMutate, InsertRepeatedBytes2) {
TestInsertRepeatedBytes(&MutationDispatcher::Mutate, 200000); TestInsertRepeatedBytes(&MutationDispatcher::Mutate, 300000);
} }
void TestChangeByte(Mutator M, int NumIter) { void TestChangeByte(Mutator M, int NumIter) {
@ -475,6 +475,42 @@ TEST(FuzzerMutate, ChangeASCIIInteger2) {
TestChangeASCIIInteger(&MutationDispatcher::Mutate, 1 << 15); TestChangeASCIIInteger(&MutationDispatcher::Mutate, 1 << 15);
} }
void TestChangeBinaryInteger(Mutator M, int NumIter) {
std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
fuzzer::EF = t.get();
Random Rand(0);
MutationDispatcher MD(Rand, {});
uint8_t CH0[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x79};
uint8_t CH1[8] = {0x00, 0x11, 0x22, 0x31, 0x44, 0x55, 0x66, 0x77};
uint8_t CH2[8] = {0xff, 0x10, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
uint8_t CH3[8] = {0x00, 0x11, 0x2a, 0x33, 0x44, 0x55, 0x66, 0x77};
uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x4f, 0x66, 0x77};
uint8_t CH5[8] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88};
int FoundMask = 0;
for (int i = 0; i < NumIter; i++) {
uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
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 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4;
else if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
}
EXPECT_EQ(FoundMask, 63);
}
TEST(FuzzerMutate, ChangeBinaryInteger1) {
TestChangeBinaryInteger(&MutationDispatcher::Mutate_ChangeBinaryInteger,
1 << 12);
}
TEST(FuzzerMutate, ChangeBinaryInteger2) {
TestChangeBinaryInteger(&MutationDispatcher::Mutate, 1 << 15);
}
TEST(FuzzerDictionary, ParseOneDictionaryEntry) { TEST(FuzzerDictionary, ParseOneDictionaryEntry) {
Unit U; Unit U;