diff --git a/compiler-rt/lib/fuzzer/FuzzerFork.cpp b/compiler-rt/lib/fuzzer/FuzzerFork.cpp --- a/compiler-rt/lib/fuzzer/FuzzerFork.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerFork.cpp @@ -156,7 +156,6 @@ Job->CFPath = DirPlusFile(TempDir, std::to_string(JobId) + ".merge"); Job->JobId = JobId; - Cmd.addArgument(Job->CorpusDir); Cmd.addFlag("features_dir", Job->FeaturesDir); diff --git a/compiler-rt/lib/fuzzer/FuzzerUtilDarwin.cpp b/compiler-rt/lib/fuzzer/FuzzerUtilDarwin.cpp --- a/compiler-rt/lib/fuzzer/FuzzerUtilDarwin.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerUtilDarwin.cpp @@ -157,6 +157,20 @@ return ProcessStatus; } +// Return true on success, false otherwise. +bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput) { + FILE *Pipe = popen(Cmd.toString().c_str(), "r"); + if (!Pipe) + return false; + + if (CmdOutput) { + char TmpBuffer[128]; + while (fgets(TmpBuffer, sizeof(TmpBuffer), Pipe)) + CmdOutput->append(TmpBuffer); + } + return pclose(Pipe) == 0; +} + void DiscardOutput(int Fd) { FILE* Temp = fopen("/dev/null", "w"); if (!Temp) diff --git a/compiler-rt/lib/fuzzer/FuzzerUtilLinux.cpp b/compiler-rt/lib/fuzzer/FuzzerUtilLinux.cpp --- a/compiler-rt/lib/fuzzer/FuzzerUtilLinux.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerUtilLinux.cpp @@ -21,11 +21,55 @@ namespace fuzzer { int ExecuteCommand(const Command &Cmd) { - std::string CmdLine = Cmd.toString(); - int exit_code = system(CmdLine.c_str()); - if (WIFEXITED(exit_code)) - return WEXITSTATUS(exit_code); - return exit_code; + int ExitCode, ProcessStatus = 0; + pid_t Pid = fork(); + + if (Pid == 0) { // Child process. Execute the given command here. + auto Args = Cmd.getArguments(); + Vector Argv(Args.size() + 1, nullptr); + std::transform( + Args.begin(), Args.end(), Argv.begin(), + [](const std::string &S) -> auto { return S.c_str(); }); + + if (Cmd.hasOutputFile()) { + FILE *OutputFile = fopen(Cmd.getOutputFile().c_str(), "w"); + if (!OutputFile) + return -1; + + dup2(fileno(OutputFile), 1); + + if (Cmd.isOutAndErrCombined()) + dup2(fileno(OutputFile), 2); + + fclose(OutputFile); + } else if (Cmd.isOutAndErrCombined()) + dup2(1, 2); + + exit(execvp(Argv[0], const_cast(Argv.data()))); + } else if (Pid > 0) { // Parent process. Wait for the child's exit code. + Pid = waitpid(Pid, &ProcessStatus, 0); + if (Pid == -1) + ExitCode = -1; + else + ExitCode = ProcessStatus; + } else { + ExitCode = -1; + } + + if (WIFEXITED(ExitCode)) + return WEXITSTATUS(ExitCode); + return ExitCode; +} + +// Return true on success, false otherwise. +bool ExecuteCommand(const Command &BaseCmd, std::string *CmdOutput) { + auto LogFilePath = TempPath("SimPopenOut", ".txt"); + Command Cmd(BaseCmd); + Cmd.setOutputFile(LogFilePath); + int Ret = ExecuteCommand(Cmd); + *CmdOutput = FileToString(LogFilePath); + RemoveFile(LogFilePath); + return Ret == 0; } void DiscardOutput(int Fd) { diff --git a/compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp b/compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp --- a/compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp @@ -86,20 +86,6 @@ } } -// Return true on success, false otherwise. -bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput) { - FILE *Pipe = popen(Cmd.toString().c_str(), "r"); - if (!Pipe) - return false; - - if (CmdOutput) { - char TmpBuffer[128]; - while (fgets(TmpBuffer, sizeof(TmpBuffer), Pipe)) - CmdOutput->append(TmpBuffer); - } - return pclose(Pipe) == 0; -} - void SetTimer(int Seconds) { struct itimerval T { {Seconds, 0}, { Seconds, 0 } diff --git a/compiler-rt/test/fuzzer/minimize_crash_with_bad_filename.test b/compiler-rt/test/fuzzer/minimize_crash_with_bad_filename.test new file mode 100644 --- /dev/null +++ b/compiler-rt/test/fuzzer/minimize_crash_with_bad_filename.test @@ -0,0 +1,9 @@ +// Test verifies that libFuzzer handles filenames that may break shell commands. +UNSUPPORTED: darwin, windows + +RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest +RUN: mkdir -p %t.dir + +RUN: echo -n 'Hi!AAA' > '%t.dir/bad;(%file)name' +RUN: %run %t-NullDerefTest -minimize_crash=1 '%t.dir/bad;(%file)name' -max_total_time=2 2>&1 | FileCheck %s --check-prefix=BAD_FILENAME +BAD_FILENAME: failed to minimize beyond