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/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,42 @@ 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); + } + + 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; } void DiscardOutput(int Fd) { 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