diff --git a/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp b/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp --- a/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp @@ -266,9 +266,9 @@ std::unordered_map> DFTMap; std::unordered_set Cov; Command Cmd; - Cmd.addArgument(DFTBinary); - Cmd.addArgument(F.File); - Cmd.addArgument(OutPath); + Cmd.addArgument(WrapPathArgument(DFTBinary)); + Cmd.addArgument(WrapPathArgument(F.File)); + Cmd.addArgument(WrapPathArgument(OutPath)); Printf("CMD: %s\n", Cmd.toString().c_str()); ExecuteCommand(Cmd); } @@ -276,7 +276,7 @@ auto FunctionsTxtPath = DirPlusFile(DirPath, kFunctionsTxt); if (FileToString(FunctionsTxtPath).empty()) { Command Cmd; - Cmd.addArgument(DFTBinary); + Cmd.addArgument(WrapPathArgument(DFTBinary)); Cmd.setOutputFile(FunctionsTxtPath); ExecuteCommand(Cmd); } diff --git a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp --- a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp @@ -399,7 +399,7 @@ CurrentFilePath.c_str(), U.size()); Command Cmd(BaseCmd); - Cmd.addArgument(CurrentFilePath); + Cmd.addArgument(WrapPathArgument(CurrentFilePath)); Printf("CRASH_MIN: executing: %s\n", Cmd.toString().c_str()); std::string CmdOutput; 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,8 +156,7 @@ Job->CFPath = DirPlusFile(TempDir, std::to_string(JobId) + ".merge"); Job->JobId = JobId; - - Cmd.addArgument(Job->CorpusDir); + Cmd.addArgument(WrapPathArgument(Job->CorpusDir)); Cmd.addFlag("features_dir", Job->FeaturesDir); for (auto &D : {Job->CorpusDir, Job->FeaturesDir}) { @@ -237,7 +236,7 @@ Cmd.removeFlag("fork"); Cmd.removeFlag("runs"); Cmd.addFlag("data_flow_trace", DFTDir); - Cmd.addArgument(InputPath); + Cmd.addArgument(WrapPathArgument(InputPath)); for (auto &C : CorpusDirs) // Remove all corpora from the args. Cmd.removeArgument(C); Cmd.setOutputFile(DirPlusFile(TempDir, "dft.log")); diff --git a/compiler-rt/lib/fuzzer/FuzzerUtil.h b/compiler-rt/lib/fuzzer/FuzzerUtil.h --- a/compiler-rt/lib/fuzzer/FuzzerUtil.h +++ b/compiler-rt/lib/fuzzer/FuzzerUtil.h @@ -106,6 +106,8 @@ return reinterpret_cast(X); } +std::string WrapPathArgument(const std::string &Path); + } // namespace fuzzer #endif // LLVM_FUZZER_UTIL_H diff --git a/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp b/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp --- a/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp @@ -560,6 +560,11 @@ dup2(nullfd, Fd); } +std::string WrapPathArgument(const std::string &Path) { + // Don't do anything as Fuchsia's ExecuteCommand passes arguments as char*[]. + return Path; +} + } // namespace fuzzer #endif // LIBFUZZER_FUCHSIA 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 @@ -180,6 +180,11 @@ return "grep '" + Regex + "'"; } +std::string WrapPathArgument(const std::string &Path) { + // Wrap the path with single quotes to avoid shell injection into system(). + return "'" + Path + "'"; +} + } // namespace fuzzer #endif // LIBFUZZER_POSIX diff --git a/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp b/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp --- a/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp @@ -216,6 +216,11 @@ fclose(Temp); } +std::string WrapPathArgument(const std::string &Path) { + // Wrap the path with double quotes to avoid shell injection into system(). + return "\"" + Path + "\""; +} + } // namespace fuzzer #endif // LIBFUZZER_WINDOWS diff --git a/compiler-rt/test/fuzzer/minimize_crash.test b/compiler-rt/test/fuzzer/minimize_crash.test --- a/compiler-rt/test/fuzzer/minimize_crash.test +++ b/compiler-rt/test/fuzzer/minimize_crash.test @@ -15,3 +15,7 @@ MIN1: Test unit written to {{.*}}exact_minimized_path MIN1: INFO: The input is small enough, exiting MIN1: CRASH_MIN: failed to minimize beyond {{.*}}exact_minimized_path (1 bytes), exiting + +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