[lld] r267600 - Handle Windows drive letters and ".." for --reproduce.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 26 13:36:46 PDT 2016


Author: ruiu
Date: Tue Apr 26 15:36:46 2016
New Revision: 267600

URL: http://llvm.org/viewvc/llvm-project?rev=267600&view=rev
Log:
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

Modified:
    lld/trunk/ELF/Driver.cpp
    lld/trunk/test/ELF/reproduce.s

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=267600&r1=267599&r2=267600&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Tue Apr 26 15:36:46 2016
@@ -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(MemoryBu
   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 Pat
   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
   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 c
   readConfigs(Args);
 
   if (!Config->Reproduce.empty())
-    dumpLinkerInvocation(ArgsArr);
+    logCommandline(ArgsArr);
 
   createFiles(Args);
   checkOptions(Args);

Modified: lld/trunk/test/ELF/reproduce.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/reproduce.s?rev=267600&r1=267599&r2=267600&view=diff
==============================================================================
--- lld/trunk/test/ELF/reproduce.s (original)
+++ lld/trunk/test/ELF/reproduce.s Tue Apr 26 15:36:46 2016
@@ -1,21 +1,27 @@
 # REQUIRES: x86
 
-# RUN: rm -rf %t.dir1
-# RUN: mkdir -p %t.dir1/build
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.dir1/build/foo.o
-# RUN: cd %t.dir1
-# RUN: ld.lld build/foo.o -o bar -shared --as-needed --reproduce repro
-# RUN: diff build/foo.o repro/build/foo.o
+# RUN: rm -rf %t.dir
+# RUN: mkdir -p %t.dir/build1
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.dir/build1/foo.o
+# RUN: cd %t.dir
+# RUN: ld.lld build1/foo.o -o bar -shared --as-needed --reproduce repro
+# RUN: diff build1/foo.o repro/build1/foo.o
+
+# RUN: FileCheck %s --check-prefix=INVOCATION < repro/invocation.txt
+# INVOCATION: lld{{[^\s]*}} build1/foo.o -o bar -shared --as-needed --reproduce repro
+
+# RUN: mkdir -p %t.dir/build2/a/b/c
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.dir/build2/foo.o
+# RUN: cd %t.dir/build2/a/b/c
+# RUN: ld.lld ./../../../foo.o -o bar -shared --as-needed --reproduce repro
+# RUN: diff %t.dir/build2/foo.o repro/foo.o
+
+# RUN: not ld.lld build1/foo.o -o bar -shared --as-needed --reproduce . 2>&1 \
+# RUN:   | FileCheck --check-prefix=ERROR %s
+# ERROR: can't create directory
 
 .globl _start
 _start:
   mov $60, %rax
   mov $42, %rdi
   syscall
-
-# RUN: FileCheck %s --check-prefix=INVOCATION < repro/invocation.txt
-# INVOCATION: lld{{[^\s]*}} build/foo.o -o bar -shared --as-needed --reproduce repro
-
-# RUN: not ld.lld build/foo.o -o bar -shared --as-needed --reproduce repro 2>&1 \
-# RUN:   | FileCheck --check-prefix=ERROR %s
-# ERROR: --reproduce: can't create directory




More information about the llvm-commits mailing list