mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 11:02:59 +02:00
[libFuzzer] remove UserSuppliedFuzzer from the interface (it was a bad idea).
llvm-svn: 260796
This commit is contained in:
parent
b2451a8b09
commit
1bb500faf8
@ -243,24 +243,14 @@ static bool AllInputsAreFiles() {
|
||||
|
||||
int FuzzerDriver(int argc, char **argv, UserCallback Callback) {
|
||||
FuzzerRandom_mt19937 Rand(0);
|
||||
SimpleUserSuppliedFuzzer SUSF(&Rand, Callback);
|
||||
return FuzzerDriver(argc, argv, SUSF);
|
||||
}
|
||||
|
||||
int FuzzerDriver(int argc, char **argv, UserSuppliedFuzzer &USF) {
|
||||
std::vector<std::string> Args(argv, argv + argc);
|
||||
return FuzzerDriver(Args, USF);
|
||||
return FuzzerDriver(Args, Callback);
|
||||
}
|
||||
|
||||
int FuzzerDriver(const std::vector<std::string> &Args, UserCallback Callback) {
|
||||
FuzzerRandom_mt19937 Rand(0);
|
||||
SimpleUserSuppliedFuzzer SUSF(&Rand, Callback);
|
||||
return FuzzerDriver(Args, SUSF);
|
||||
}
|
||||
|
||||
int FuzzerDriver(const std::vector<std::string> &Args,
|
||||
UserSuppliedFuzzer &USF) {
|
||||
using namespace fuzzer;
|
||||
FuzzerRandom_mt19937 Rand(0);
|
||||
SimpleUserSuppliedFuzzer USF(&Rand, Callback);
|
||||
assert(!Args.empty());
|
||||
ProgName = new std::string(Args[0]);
|
||||
ParseFlags(Args);
|
||||
|
@ -64,6 +64,7 @@ int LLVMFuzzerInitialize(int *argc, char ***argv) {
|
||||
}
|
||||
|
||||
// Implement your own main() or use the one from FuzzerMain.cpp.
|
||||
// *NOT* recommended for most cases.
|
||||
int main(int argc, char **argv) {
|
||||
InitializeMeIfNeeded();
|
||||
return fuzzer::FuzzerDriver(argc, argv, LLVMFuzzerTestOneInput);
|
||||
@ -72,102 +73,13 @@ int main(int argc, char **argv) {
|
||||
*/
|
||||
int FuzzerDriver(int argc, char **argv, UserCallback Callback);
|
||||
|
||||
class FuzzerRandomBase {
|
||||
public:
|
||||
FuzzerRandomBase(){}
|
||||
virtual ~FuzzerRandomBase(){};
|
||||
virtual void ResetSeed(unsigned int seed) = 0;
|
||||
// Return a random number.
|
||||
virtual size_t Rand() = 0;
|
||||
// Return a random number in range [0,n).
|
||||
size_t operator()(size_t n) { return n ? Rand() % n : 0; }
|
||||
bool RandBool() { return Rand() % 2; }
|
||||
};
|
||||
|
||||
// Using libc's stand/rand.
|
||||
class FuzzerRandomLibc : public FuzzerRandomBase {
|
||||
public:
|
||||
FuzzerRandomLibc(unsigned int seed) { ResetSeed(seed); }
|
||||
void ResetSeed(unsigned int seed) override;
|
||||
~FuzzerRandomLibc() override {};
|
||||
size_t Rand() override;
|
||||
};
|
||||
|
||||
// Using std::mt19937
|
||||
class FuzzerRandom_mt19937 : public FuzzerRandomBase {
|
||||
public:
|
||||
FuzzerRandom_mt19937(unsigned int seed) { ResetSeed(seed); }
|
||||
void ResetSeed(unsigned int seed) override;
|
||||
~FuzzerRandom_mt19937() override;
|
||||
size_t Rand() override;
|
||||
private:
|
||||
struct Impl;
|
||||
Impl *R = nullptr;
|
||||
};
|
||||
|
||||
// For backward compatibility only, deprecated.
|
||||
size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize,
|
||||
FuzzerRandomBase &Rand);
|
||||
|
||||
size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed);
|
||||
|
||||
class MutationDispatcher;
|
||||
|
||||
/** An abstract class that allows to use user-supplied mutators with libFuzzer.
|
||||
|
||||
Usage:
|
||||
|
||||
#\code
|
||||
#include "FuzzerInterface.h"
|
||||
class MyFuzzer : public fuzzer::UserSuppliedFuzzer {
|
||||
public:
|
||||
MyFuzzer(fuzzer::FuzzerRandomBase *Rand);
|
||||
// Must define the target function.
|
||||
int TargetFunction(...) { ...; return 0; }
|
||||
// Optionally define the mutator.
|
||||
size_t Mutate(...) { ... }
|
||||
// Optionally define the CrossOver method.
|
||||
size_t CrossOver(...) { ... }
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
MyFuzzer F;
|
||||
fuzzer::FuzzerDriver(argc, argv, F);
|
||||
}
|
||||
#\endcode
|
||||
*/
|
||||
class UserSuppliedFuzzer {
|
||||
public:
|
||||
UserSuppliedFuzzer(FuzzerRandomBase *Rand);
|
||||
/// Executes the target function on 'Size' bytes of 'Data'.
|
||||
virtual int TargetFunction(const uint8_t *Data, size_t Size) = 0;
|
||||
/// Mutates 'Size' bytes of data in 'Data' inplace into up to 'MaxSize' bytes,
|
||||
/// returns the new size of the data, which should be positive.
|
||||
virtual size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize);
|
||||
/// Crosses 'Data1' and 'Data2', writes up to 'MaxOutSize' bytes into Out,
|
||||
/// returns the number of bytes written, which should be positive.
|
||||
virtual size_t CrossOver(const uint8_t *Data1, size_t Size1,
|
||||
const uint8_t *Data2, size_t Size2,
|
||||
uint8_t *Out, size_t MaxOutSize);
|
||||
virtual ~UserSuppliedFuzzer();
|
||||
|
||||
FuzzerRandomBase &GetRand() { return *Rand; }
|
||||
|
||||
MutationDispatcher &GetMD() { return *MD; }
|
||||
|
||||
private:
|
||||
bool OwnRand = false;
|
||||
FuzzerRandomBase *Rand;
|
||||
MutationDispatcher *MD;
|
||||
};
|
||||
|
||||
/// Runs the fuzzing with the UserSuppliedFuzzer.
|
||||
int FuzzerDriver(int argc, char **argv, UserSuppliedFuzzer &USF);
|
||||
|
||||
/// More C++-ish interface.
|
||||
int FuzzerDriver(const std::vector<std::string> &Args, UserSuppliedFuzzer &USF);
|
||||
int FuzzerDriver(const std::vector<std::string> &Args, UserCallback Callback);
|
||||
|
||||
// Same interface as LLVMFuzzerTestOneInput.
|
||||
// Can be used inside the user-supplied LLVMFuzzerTestOneInput.
|
||||
size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed);
|
||||
|
||||
} // namespace fuzzer
|
||||
|
||||
#endif // LLVM_FUZZER_INTERFACE_H
|
||||
|
@ -98,6 +98,41 @@ bool IsASCII(const Unit &U);
|
||||
int NumberOfCpuCores();
|
||||
int GetPid();
|
||||
|
||||
class FuzzerRandomBase {
|
||||
public:
|
||||
FuzzerRandomBase(){}
|
||||
virtual ~FuzzerRandomBase(){};
|
||||
virtual void ResetSeed(unsigned int seed) = 0;
|
||||
// Return a random number.
|
||||
virtual size_t Rand() = 0;
|
||||
// Return a random number in range [0,n).
|
||||
size_t operator()(size_t n) { return n ? Rand() % n : 0; }
|
||||
bool RandBool() { return Rand() % 2; }
|
||||
};
|
||||
|
||||
// Using libc's stand/rand.
|
||||
class FuzzerRandomLibc : public FuzzerRandomBase {
|
||||
public:
|
||||
FuzzerRandomLibc(unsigned int seed) { ResetSeed(seed); }
|
||||
void ResetSeed(unsigned int seed) override;
|
||||
~FuzzerRandomLibc() override {};
|
||||
size_t Rand() override;
|
||||
};
|
||||
|
||||
// Using std::mt19937
|
||||
class FuzzerRandom_mt19937 : public FuzzerRandomBase {
|
||||
public:
|
||||
FuzzerRandom_mt19937(unsigned int seed) { ResetSeed(seed); }
|
||||
void ResetSeed(unsigned int seed) override;
|
||||
~FuzzerRandom_mt19937() override;
|
||||
size_t Rand() override;
|
||||
private:
|
||||
struct Impl;
|
||||
Impl *R = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Dictionary.
|
||||
|
||||
// Parses one dictionary entry.
|
||||
@ -169,6 +204,31 @@ private:
|
||||
Impl *MDImpl;
|
||||
};
|
||||
|
||||
class UserSuppliedFuzzer {
|
||||
public:
|
||||
UserSuppliedFuzzer(FuzzerRandomBase *Rand);
|
||||
/// Executes the target function on 'Size' bytes of 'Data'.
|
||||
virtual int TargetFunction(const uint8_t *Data, size_t Size) = 0;
|
||||
/// Mutates 'Size' bytes of data in 'Data' inplace into up to 'MaxSize' bytes,
|
||||
/// returns the new size of the data, which should be positive.
|
||||
virtual size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize);
|
||||
/// Crosses 'Data1' and 'Data2', writes up to 'MaxOutSize' bytes into Out,
|
||||
/// returns the number of bytes written, which should be positive.
|
||||
virtual size_t CrossOver(const uint8_t *Data1, size_t Size1,
|
||||
const uint8_t *Data2, size_t Size2,
|
||||
uint8_t *Out, size_t MaxOutSize);
|
||||
virtual ~UserSuppliedFuzzer();
|
||||
|
||||
FuzzerRandomBase &GetRand() { return *Rand; }
|
||||
|
||||
MutationDispatcher &GetMD() { return *MD; }
|
||||
|
||||
private:
|
||||
bool OwnRand = false;
|
||||
FuzzerRandomBase *Rand;
|
||||
MutationDispatcher *MD;
|
||||
};
|
||||
|
||||
class Fuzzer {
|
||||
public:
|
||||
struct FuzzingOptions {
|
||||
|
@ -37,7 +37,6 @@ set(Tests
|
||||
)
|
||||
|
||||
set(CustomMainTests
|
||||
UserSuppliedFuzzerTest
|
||||
)
|
||||
|
||||
set(UninstrumentedTests
|
||||
|
@ -1,51 +0,0 @@
|
||||
// Simple test for a fuzzer.
|
||||
// The fuzzer must find the string "Hi!" preceded by a magic value.
|
||||
// Uses UserSuppliedFuzzer which ensures that the magic is present.
|
||||
#include <cstdint>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
#include "FuzzerInterface.h"
|
||||
|
||||
static const uint64_t kMagic = 8860221463604ULL;
|
||||
|
||||
class MyFuzzer : public fuzzer::UserSuppliedFuzzer {
|
||||
public:
|
||||
MyFuzzer(fuzzer::FuzzerRandomBase *Rand)
|
||||
: fuzzer::UserSuppliedFuzzer(Rand) {}
|
||||
int TargetFunction(const uint8_t *Data, size_t Size) {
|
||||
if (Size <= 10) return 0;
|
||||
if (memcmp(Data, &kMagic, sizeof(kMagic))) return 0;
|
||||
// It's hard to get here w/o advanced fuzzing techniques (e.g. cmp tracing).
|
||||
// So, we simply 'fix' the data in the custom mutator.
|
||||
if (Data[8] == 'H') {
|
||||
if (Data[9] == 'i') {
|
||||
if (Data[10] == '!') {
|
||||
std::cout << "BINGO; Found the target, exiting\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// Custom mutator.
|
||||
virtual size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
|
||||
assert(MaxSize > sizeof(kMagic));
|
||||
if (Size < sizeof(kMagic))
|
||||
Size = sizeof(kMagic);
|
||||
// "Fix" the data, then mutate.
|
||||
memcpy(Data, &kMagic, std::min(MaxSize, sizeof(kMagic)));
|
||||
return fuzzer::UserSuppliedFuzzer::Mutate(
|
||||
Data + sizeof(kMagic), Size - sizeof(kMagic), MaxSize - sizeof(kMagic));
|
||||
}
|
||||
// No need to redefine CrossOver() here.
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
fuzzer::FuzzerRandomLibc Rand(0);
|
||||
MyFuzzer F(&Rand);
|
||||
fuzzer::FuzzerDriver(argc, argv, F);
|
||||
}
|
@ -24,8 +24,6 @@ RUN: not LLVMFuzzer-CallerCalleeTest -cross_over=0 -max_len=
|
||||
# LLVMFuzzer-CallerCalleeTest -use_indir_calls=0 -cross_over=0 -max_len=6 -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000
|
||||
|
||||
|
||||
RUN: not LLVMFuzzer-UserSuppliedFuzzerTest -seed=1 -timeout=15 2>&1 | FileCheck %s
|
||||
|
||||
RUN: not LLVMFuzzer-UninstrumentedTest-Uninstrumented 2>&1 | FileCheck %s --check-prefix=UNINSTRUMENTED
|
||||
UNINSTRUMENTED: ERROR: __sanitizer_set_death_callback is not defined. Exiting.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user