mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[llvm-opt-fuzzer] Avoid adding incorrect inputs to the fuzzer corpus
Differential Revision: https://reviews.llvm.org/D42414 llvm-svn: 324225
This commit is contained in:
parent
213729c26a
commit
4f2f540e75
@ -68,6 +68,12 @@ std::unique_ptr<Module> parseModule(const uint8_t *Data, size_t Size,
|
||||
/// returns 0 and leaves Dest unchanged.
|
||||
size_t writeModule(const Module &M, uint8_t *Dest, size_t MaxSize);
|
||||
|
||||
/// Try to parse module and verify it. May output verification errors to the
|
||||
/// errs().
|
||||
/// \return New module or nullptr in case of error.
|
||||
std::unique_ptr<Module> parseAndVerify(const uint8_t *Data, size_t Size,
|
||||
LLVMContext &Context);
|
||||
|
||||
} // end llvm namespace
|
||||
|
||||
#endif // LLVM_FUZZMUTATE_FUZZER_CLI_H
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/IR/Verifier.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -175,3 +176,12 @@ size_t llvm::writeModule(const Module &M, uint8_t *Dest, size_t MaxSize) {
|
||||
memcpy(Dest, Buf.data(), Buf.size());
|
||||
return Buf.size();
|
||||
}
|
||||
|
||||
std::unique_ptr<Module> llvm::parseAndVerify(const uint8_t *Data, size_t Size,
|
||||
LLVMContext &Context) {
|
||||
auto M = parseModule(Data, Size, Context);
|
||||
if (!M || verifyModule(*M, &errs()))
|
||||
return nullptr;
|
||||
|
||||
return M;
|
||||
}
|
||||
|
@ -84,8 +84,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
return 0;
|
||||
|
||||
LLVMContext Context;
|
||||
auto M = parseModule(Data, Size, Context);
|
||||
if (!M || verifyModule(*M, &errs())) {
|
||||
auto M = parseAndVerify(Data, Size, Context);
|
||||
if (!M) {
|
||||
errs() << "error: input module is broken!\n";
|
||||
return 0;
|
||||
}
|
||||
|
@ -57,23 +57,45 @@ extern "C" LLVM_ATTRIBUTE_USED size_t LLVMFuzzerCustomMutator(
|
||||
"IR mutator should have been created during fuzzer initialization");
|
||||
|
||||
LLVMContext Context;
|
||||
auto M = parseModule(Data, Size, Context);
|
||||
if (!M || verifyModule(*M, &errs())) {
|
||||
auto M = parseAndVerify(Data, Size, Context);
|
||||
if (!M) {
|
||||
errs() << "error: mutator input module is broken!\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
Mutator->mutateModule(*M, Seed, Size, MaxSize);
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (verifyModule(*M, &errs())) {
|
||||
errs() << "mutation result doesn't pass verification\n";
|
||||
M->dump();
|
||||
abort();
|
||||
// Avoid adding incorrect test cases to the corpus.
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return writeModule(*M, Data, MaxSize);
|
||||
std::string Buf;
|
||||
{
|
||||
raw_string_ostream OS(Buf);
|
||||
WriteBitcodeToFile(M.get(), OS);
|
||||
}
|
||||
if (Buf.size() > MaxSize)
|
||||
return 0;
|
||||
|
||||
// There are some invariants which are not checked by the verifier in favor
|
||||
// of having them checked by the parser. They may be considered as bugs in the
|
||||
// verifier and should be fixed there. However until all of those are covered
|
||||
// we want to check for them explicitly. Otherwise we will add incorrect input
|
||||
// to the corpus and this is going to confuse the fuzzer which will start
|
||||
// exploration of the bitcode reader error handling code.
|
||||
auto NewM = parseAndVerify(
|
||||
reinterpret_cast<const uint8_t*>(Buf.data()), Buf.size(), Context);
|
||||
if (!NewM) {
|
||||
errs() << "mutator failed to re-read the module\n";
|
||||
M->dump();
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(Data, Buf.data(), Buf.size());
|
||||
return Buf.size();
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
@ -87,8 +109,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
//
|
||||
|
||||
LLVMContext Context;
|
||||
auto M = parseModule(Data, Size, Context);
|
||||
if (!M || verifyModule(*M, &errs())) {
|
||||
auto M = parseAndVerify(Data, Size, Context);
|
||||
if (!M) {
|
||||
errs() << "error: input module is broken!\n";
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user