diff --git a/llvm/lib/Fuzzer/FuzzerDriver.cpp b/llvm/lib/Fuzzer/FuzzerDriver.cpp index a4e16bad9164..0fb83ca64de6 100644 --- a/llvm/lib/Fuzzer/FuzzerDriver.cpp +++ b/llvm/lib/Fuzzer/FuzzerDriver.cpp @@ -278,6 +278,17 @@ static bool AllInputsAreFiles() { return true; } +static std::string GetDedupTokenFromFile(const std::string &Path) { + auto S = FileToString(Path); + auto Beg = S.find("DEDUP_TOKEN:"); + if (Beg == std::string::npos) + return ""; + auto End = S.find('\n', Beg); + if (End == std::string::npos) + return ""; + return S.substr(Beg, End - Beg); +} + int MinimizeCrashInput(const std::vector &Args, const FuzzingOptions &Options) { if (Inputs->size() != 1) { @@ -296,7 +307,10 @@ int MinimizeCrashInput(const std::vector &Args, "INFO: defaulting to -max_total_time=600\n"); BaseCmd += " -max_total_time=600"; } - // BaseCmd += " > /dev/null 2>&1 "; + + auto LogFilePath = DirPlusFile( + TmpDir(), "libFuzzerTemp." + std::to_string(GetPid()) + ".txt"); + auto LogFileRedirect = " > " + LogFilePath + " 2>&1 "; std::string CurrentFilePath = InputFilePath; while (true) { @@ -304,7 +318,7 @@ int MinimizeCrashInput(const std::vector &Args, Printf("CRASH_MIN: minimizing crash input: '%s' (%zd bytes)\n", CurrentFilePath.c_str(), U.size()); - auto Cmd = BaseCmd + " " + CurrentFilePath; + auto Cmd = BaseCmd + " " + CurrentFilePath + LogFileRedirect; Printf("CRASH_MIN: executing: %s\n", Cmd.c_str()); int ExitCode = ExecuteCommand(Cmd); @@ -315,6 +329,9 @@ int MinimizeCrashInput(const std::vector &Args, Printf("CRASH_MIN: '%s' (%zd bytes) caused a crash. Will try to minimize " "it further\n", CurrentFilePath.c_str(), U.size()); + auto DedupToken1 = GetDedupTokenFromFile(LogFilePath); + if (!DedupToken1.empty()) + Printf("CRASH_MIN: DedupToken1: %s\n", DedupToken1.c_str()); std::string ArtifactPath = Flags.exact_artifact_path @@ -324,6 +341,7 @@ int MinimizeCrashInput(const std::vector &Args, ArtifactPath; Printf("CRASH_MIN: executing: %s\n", Cmd.c_str()); ExitCode = ExecuteCommand(Cmd); + CopyFileToErr(LogFilePath); if (ExitCode == 0) { if (Flags.exact_artifact_path) { CurrentFilePath = Flags.exact_artifact_path; @@ -331,11 +349,26 @@ int MinimizeCrashInput(const std::vector &Args, } Printf("CRASH_MIN: failed to minimize beyond %s (%d bytes), exiting\n", CurrentFilePath.c_str(), U.size()); - return 0; + break; } + auto DedupToken2 = GetDedupTokenFromFile(LogFilePath); + if (!DedupToken2.empty()) + Printf("CRASH_MIN: DedupToken2: %s\n", DedupToken2.c_str()); + + if (DedupToken1 != DedupToken2) { + if (Flags.exact_artifact_path) { + CurrentFilePath = Flags.exact_artifact_path; + WriteToFile(U, CurrentFilePath); + } + Printf("CRASH_MIN: mismatch in dedup tokens" + " (looks like a different bug). Won't minimize further\n"); + break; + } + CurrentFilePath = ArtifactPath; - Printf("\n\n\n\n\n\n*********************************\n"); + Printf("*********************************\n"); } + RemoveFile(LogFilePath); return 0; } diff --git a/llvm/lib/Fuzzer/test/minimize_two_crashes.test b/llvm/lib/Fuzzer/test/minimize_two_crashes.test new file mode 100644 index 000000000000..1fdffb809ded --- /dev/null +++ b/llvm/lib/Fuzzer/test/minimize_two_crashes.test @@ -0,0 +1,16 @@ +# Test that the minimizer stops when it sees a differe bug. + +RUN: rm -rf %t && mkdir %t +RUN: echo H12345678901234667888090 > %t/long_crash +RUN: ASAN_OPTIONS=dedup_token_length=3 LLVMFuzzer-TwoDifferentBugsTest -seed=1 -minimize_crash=1 %t/long_crash -exact_artifact_path=%t/result 2>&1 | FileCheck %s + +CHECK: DedupToken1: DEDUP_TOKEN: Bar +CHECK: DedupToken2: DEDUP_TOKEN: Bar +CHECK: DedupToken1: DEDUP_TOKEN: Bar +CHECK: DedupToken2: DEDUP_TOKEN: Foo +CHECK: CRASH_MIN: mismatch in dedup tokens + +RUN: not LLVMFuzzer-TwoDifferentBugsTest %t/result 2>&1 | FileCheck %s --check-prefix=VERIFY + +VERIFY: ERROR: AddressSanitizer: +VERIFY: in Bar