diff options
author | Kostya Serebryany <kcc@google.com> | 2017-04-17 20:58:21 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@google.com> | 2017-04-17 20:58:21 +0000 |
commit | ac7a9eae0bff0067f7e89f31c6d9be85bbbae828 (patch) | |
tree | ede5b08f193d3d6f419aff6c49551126ead11f99 /llvm/lib/Fuzzer/FuzzerDriver.cpp | |
parent | dcb52b167ae374b23d3f0e37cac6249257927c9d (diff) | |
download | bcm5719-llvm-ac7a9eae0bff0067f7e89f31c6d9be85bbbae828.tar.gz bcm5719-llvm-ac7a9eae0bff0067f7e89f31c6d9be85bbbae828.zip |
[libFuzzer] experimental option -cleanse_crash: tries to replace all bytes in a crash reproducer with garbage, while still preserving the crash
llvm-svn: 300498
Diffstat (limited to 'llvm/lib/Fuzzer/FuzzerDriver.cpp')
-rw-r--r-- | llvm/lib/Fuzzer/FuzzerDriver.cpp | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/llvm/lib/Fuzzer/FuzzerDriver.cpp b/llvm/lib/Fuzzer/FuzzerDriver.cpp index 0fb83ca64de..e085e65fd83 100644 --- a/llvm/lib/Fuzzer/FuzzerDriver.cpp +++ b/llvm/lib/Fuzzer/FuzzerDriver.cpp @@ -289,6 +289,66 @@ static std::string GetDedupTokenFromFile(const std::string &Path) { return S.substr(Beg, End - Beg); } +int CleanseCrashInput(const std::vector<std::string> &Args, + const FuzzingOptions &Options) { + if (Inputs->size() != 1 || !Flags.exact_artifact_path) { + Printf("ERROR: -cleanse_crash should be given one input file and" + " -exact_artifact_path\n"); + exit(1); + } + std::string InputFilePath = Inputs->at(0); + std::string OutputFilePath = Flags.exact_artifact_path; + std::string BaseCmd = + CloneArgsWithoutX(Args, "cleanse_crash", "cleanse_crash"); + + auto InputPos = BaseCmd.find(" " + InputFilePath + " "); + assert(InputPos != std::string::npos); + BaseCmd.erase(InputPos, InputFilePath.size() + 1); + + auto LogFilePath = DirPlusFile( + TmpDir(), "libFuzzerTemp." + std::to_string(GetPid()) + ".txt"); + auto TmpFilePath = DirPlusFile( + TmpDir(), "libFuzzerTemp." + std::to_string(GetPid()) + ".repro"); + auto LogFileRedirect = " > " + LogFilePath + " 2>&1 "; + + auto Cmd = BaseCmd + " " + TmpFilePath + LogFileRedirect; + + std::string CurrentFilePath = InputFilePath; + auto U = FileToVector(CurrentFilePath); + size_t Size = U.size(); + + const std::vector<uint8_t> ReplacementBytes = {' ', 0xff}; + for (int NumAttempts = 0; NumAttempts < 5; NumAttempts++) { + bool Changed = false; + for (size_t Idx = 0; Idx < Size; Idx++) { + Printf("CLEANSE[%d]: Trying to replace byte %zd of %zd\n", NumAttempts, + Idx, Size); + uint8_t OriginalByte = U[Idx]; + if (ReplacementBytes.end() != std::find(ReplacementBytes.begin(), + ReplacementBytes.end(), + OriginalByte)) + continue; + for (auto NewByte : ReplacementBytes) { + U[Idx] = NewByte; + WriteToFile(U, TmpFilePath); + auto ExitCode = ExecuteCommand(Cmd); + RemoveFile(TmpFilePath); + if (!ExitCode) { + U[Idx] = OriginalByte; + } else { + Changed = true; + Printf("CLEANSE: Replaced byte %zd with 0x%x\n", Idx, NewByte); + WriteToFile(U, OutputFilePath); + break; + } + } + } + if (!Changed) break; + } + RemoveFile(LogFilePath); + return 0; +} + int MinimizeCrashInput(const std::vector<std::string> &Args, const FuzzingOptions &Options) { if (Inputs->size() != 1) { @@ -583,6 +643,9 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { if (Flags.minimize_crash_internal_step) return MinimizeCrashInputInternalStep(F, Corpus); + if (Flags.cleanse_crash) + return CleanseCrashInput(Args, Options); + if (auto Name = Flags.run_equivalence_server) { SMR.Destroy(Name); if (!SMR.Create(Name)) { |