llvm.org GIT mirror llvm / a328879
[llvm-opt-fuzzer] Avoid adding incorrect inputs to the fuzzer corpus Differential Revision: https://reviews.llvm.org/D42414 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@324225 91177308-0d34-0410-b5e6-96231b3b80d8 Igor Laevsky 1 year, 6 months ago
4 changed file(s) with 50 addition(s) and 12 deletion(s). Raw diff Collapse all Expand all
6767 /// returns 0 and leaves Dest unchanged.
6868 size_t writeModule(const Module &M, uint8_t *Dest, size_t MaxSize);
6969
70 /// Try to parse module and verify it. May output verification errors to the
71 /// errs().
72 /// \return New module or nullptr in case of error.
73 std::unique_ptr parseAndVerify(const uint8_t *Data, size_t Size,
74 LLVMContext &Context);
75
7076 } // end llvm namespace
7177
7278 #endif // LLVM_FUZZMUTATE_FUZZER_CLI_H
1717 #include "llvm/Support/MemoryBuffer.h"
1818 #include "llvm/Support/SourceMgr.h"
1919 #include "llvm/Support/raw_ostream.h"
20 #include "llvm/IR/Verifier.h"
2021
2122 using namespace llvm;
2223
174175 memcpy(Dest, Buf.data(), Buf.size());
175176 return Buf.size();
176177 }
178
179 std::unique_ptr llvm::parseAndVerify(const uint8_t *Data, size_t Size,
180 LLVMContext &Context) {
181 auto M = parseModule(Data, Size, Context);
182 if (!M || verifyModule(*M, &errs()))
183 return nullptr;
184
185 return M;
186 }
8383 return 0;
8484
8585 LLVMContext Context;
86 auto M = parseModule(Data, Size, Context);
87 if (!M || verifyModule(*M, &errs())) {
86 auto M = parseAndVerify(Data, Size, Context);
87 if (!M) {
8888 errs() << "error: input module is broken!\n";
8989 return 0;
9090 }
5656 "IR mutator should have been created during fuzzer initialization");
5757
5858 LLVMContext Context;
59 auto M = parseModule(Data, Size, Context);
60 if (!M || verifyModule(*M, &errs())) {
59 auto M = parseAndVerify(Data, Size, Context);
60 if (!M) {
6161 errs() << "error: mutator input module is broken!\n";
6262 return 0;
6363 }
6464
6565 Mutator->mutateModule(*M, Seed, Size, MaxSize);
6666
67 #ifndef NDEBUG
6867 if (verifyModule(*M, &errs())) {
6968 errs() << "mutation result doesn't pass verification\n";
7069 M->dump();
71 abort();
72 }
73 #endif
74
75 return writeModule(*M, Data, MaxSize);
70 // Avoid adding incorrect test cases to the corpus.
71 return 0;
72 }
73
74 std::string Buf;
75 {
76 raw_string_ostream OS(Buf);
77 WriteBitcodeToFile(M.get(), OS);
78 }
79 if (Buf.size() > MaxSize)
80 return 0;
81
82 // There are some invariants which are not checked by the verifier in favor
83 // of having them checked by the parser. They may be considered as bugs in the
84 // verifier and should be fixed there. However until all of those are covered
85 // we want to check for them explicitly. Otherwise we will add incorrect input
86 // to the corpus and this is going to confuse the fuzzer which will start
87 // exploration of the bitcode reader error handling code.
88 auto NewM = parseAndVerify(
89 reinterpret_cast(Buf.data()), Buf.size(), Context);
90 if (!NewM) {
91 errs() << "mutator failed to re-read the module\n";
92 M->dump();
93 return 0;
94 }
95
96 memcpy(Data, Buf.data(), Buf.size());
97 return Buf.size();
7698 }
7799
78100 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
86108 //
87109
88110 LLVMContext Context;
89 auto M = parseModule(Data, Size, Context);
90 if (!M || verifyModule(*M, &errs())) {
111 auto M = parseAndVerify(Data, Size, Context);
112 if (!M) {
91113 errs() << "error: input module is broken!\n";
92114 return 0;
93115 }