diff options
author | Rui Ueyama <ruiu@google.com> | 2016-04-26 20:36:46 +0000 |
---|---|---|
committer | Rui Ueyama <ruiu@google.com> | 2016-04-26 20:36:46 +0000 |
commit | 673b609586c1ae7a61108342ec6353989bee1497 (patch) | |
tree | 984ea54596040b05eb18783b7e2ca371d3a7b014 /lld/ELF/Driver.cpp | |
parent | 2f1459cbb7d7c37223ed0a52df11af8425e26599 (diff) | |
download | bcm5719-llvm-673b609586c1ae7a61108342ec6353989bee1497.tar.gz bcm5719-llvm-673b609586c1ae7a61108342ec6353989bee1497.zip |
Handle Windows drive letters and ".." for --reproduce.
When --reproduce <path> is given, then we need to concatenate input
file paths to the given path to save input files to the directory.
Previously, path concatenation didn't handle Windows drive letters
so it could generate invalid paths such as "C:\D:\foo". It also didn't
handle ".." path components, so it could produce some bad paths
such as "foo/../../etc/passwd".
In this patch, Windows drive letters and ".." are removed before
concatenating paths.
Differential Revision: http://reviews.llvm.org/D19551
llvm-svn: 267600
Diffstat (limited to 'lld/ELF/Driver.cpp')
-rw-r--r-- | lld/ELF/Driver.cpp | 56 |
1 files changed, 35 insertions, 21 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 5af45acf48d..8e8ab7f6b47 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -27,6 +27,7 @@ using namespace llvm; using namespace llvm::ELF; using namespace llvm::object; +using namespace llvm::sys; using namespace lld; using namespace lld::elf; @@ -98,18 +99,31 @@ LinkerDriver::getArchiveMembers(MemoryBufferRef MB) { return V; } -static void dumpFile(StringRef SrcPath) { - SmallString<128> DirName; - sys::path::append(DirName, Config->Reproduce, sys::path::parent_path(SrcPath)); - if (std::error_code EC = sys::fs::create_directories(DirName)) { - error(EC, "--reproduce: can't create directory"); +// Concatenates S and T so that the resulting path becomes S/T. +// There are a few exceptions: +// +// 1. The result will never escape from S. Therefore, all ".." +// are removed from T before concatenatig them. +// 2. Windows drive letters are removed from T before concatenation. +static std::string concat(StringRef S, StringRef T) { + // Remove leading '/' or a drive letter, and then remove "..". + SmallString<128> T2(path::relative_path(T)); + path::remove_dots(T2, /*remove_dot_dot=*/true); + + SmallString<128> Res; + path::append(Res, S, T2); + return Res.str(); +} + +static void copyFile(StringRef Src, StringRef Dest) { + SmallString<128> Dir(Dest); + path::remove_filename(Dir); + if (std::error_code EC = sys::fs::create_directories(Dir)) { + error(EC, Dir + ": can't create directory"); return; } - - SmallString<128> DestPathName; - sys::path::append(DestPathName, Config->Reproduce, SrcPath); - if (std::error_code EC = sys::fs::copy_file(SrcPath, DestPathName)) - error(EC, "--reproduce: can't copy file"); + if (std::error_code EC = sys::fs::copy_file(Src, Dest)) + error(EC, "failed to copy file: " + Dest); } // Opens and parses a file. Path has to be resolved already. @@ -119,7 +133,7 @@ void LinkerDriver::addFile(StringRef Path) { if (Config->Verbose) llvm::outs() << Path << "\n"; if (!Config->Reproduce.empty()) - dumpFile(Path); + copyFile(Path, concat(Config->Reproduce, Path)); Optional<MemoryBufferRef> Buffer = readFile(Path); if (!Buffer.hasValue()) @@ -241,21 +255,21 @@ static bool hasZOption(opt::InputArgList &Args, StringRef Key) { return false; } -static void dumpLinkerInvocation(ArrayRef<const char *> Args) { - std::error_code EC = sys::fs::create_directories(Config->Reproduce, - false /* IgnoreExisting */); - if (EC) { - error(EC, "--reproduce: can't create directory"); +static void logCommandline(ArrayRef<const char *> Args) { + if (std::error_code EC = sys::fs::create_directories( + Config->Reproduce, /*IgnoreExisting=*/false)) { + error(EC, Config->Reproduce + ": can't create directory"); return; } - SmallString<128> InvocationPath; - sys::path::append(InvocationPath, Config->Reproduce, "invocation.txt"); - raw_fd_ostream OS(InvocationPath, EC, sys::fs::OpenFlags::F_None); + SmallString<128> Path; + path::append(Path, Config->Reproduce, "invocation.txt"); + std::error_code EC; + raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None); check(EC); OS << Args[0]; - for (unsigned I = 1, E = Args.size(); I < E; ++I) + for (size_t I = 1, E = Args.size(); I < E; ++I) OS << " " << Args[I]; OS << "\n"; } @@ -276,7 +290,7 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr) { readConfigs(Args); if (!Config->Reproduce.empty()) - dumpLinkerInvocation(ArgsArr); + logCommandline(ArgsArr); createFiles(Args); checkOptions(Args); |