Index: tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp =================================================================== --- tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp +++ tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp @@ -65,15 +65,37 @@ 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; + } + + 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 = parseModule( + reinterpret_cast(Buf.data()), Buf.size(), Context); + if (!NewM || verifyModule(*NewM, &errs())) { + errs() << "mutator failed to re-read the module\n"; + M->dump(); + return 0; } -#endif - return writeModule(*M, Data, MaxSize); + memcpy(Data, Buf.data(), Buf.size()); + return Buf.size(); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {