[compiler-rt] r230723 - [compiler-rt] Allow suppression file to be relative to the location of the executable

Anna Zaks ganna at apple.com
Thu Feb 26 19:12:20 PST 2015


Author: zaks
Date: Thu Feb 26 21:12:19 2015
New Revision: 230723

URL: http://llvm.org/viewvc/llvm-project?rev=230723&view=rev
Log:
[compiler-rt] Allow suppression file to be relative to the location of the executable

The ASanified executable could be launched from different locations. When we
cannot find the suppression file relative to the current directory, try to
see if the specified path is relative to the location of the executable.

Added:
    compiler-rt/trunk/test/asan/TestCases/suppressions-exec-relative-location.cc
Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_suppressions.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h?rev=230723&r1=230722&r2=230723&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h Thu Feb 26 21:12:19 2015
@@ -216,6 +216,11 @@ const char *GetEnv(const char *name);
 bool SetEnv(const char *name, const char *value);
 const char *GetPwd();
 char *FindPathToBinary(const char *name);
+bool IsPathSeparator(const char c);
+bool IsAbsolutePath(const char *path);
+
+// Returns the path to the main executable.
+uptr ReadBinaryName(/*out*/char *buf, uptr buf_len);
 u32 GetUid();
 void ReExec();
 bool StackSizeIsUnlimited();

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h?rev=230723&r1=230722&r2=230723&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h Thu Feb 26 21:12:19 2015
@@ -80,8 +80,6 @@ uptr ThreadSelfOffset();
 // information).
 bool LibraryNameIs(const char *full_name, const char *base_name);
 
-// Read the name of the current binary from /proc/self/exe.
-uptr ReadBinaryName(/*out*/char *buf, uptr buf_len);
 // Cache the value of /proc/self/exe.
 void CacheBinaryName();
 

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc?rev=230723&r1=230722&r2=230723&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc Thu Feb 26 21:12:19 2015
@@ -31,9 +31,11 @@
 
 #include <crt_externs.h>  // for _NSGetEnviron
 #include <fcntl.h>
+#include <mach-o/dyld.h>
 #include <pthread.h>
 #include <sched.h>
 #include <signal.h>
+#include <stdlib.h>
 #include <sys/mman.h>
 #include <sys/resource.h>
 #include <sys/stat.h>
@@ -203,6 +205,21 @@ const char *GetEnv(const char *name) {
   }
   return 0;
 }
+
+uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
+  CHECK_LE(kMaxPathLength, buf_len);
+
+  // On OS X the executable path is saved to the stack by dyld. Reading it
+  // from there is much faster than calling dladdr, especially for large
+  // binaries with symbols.
+  InternalScopedString exe_path(kMaxPathLength);
+  uint32_t size = exe_path.size();
+  if (_NSGetExecutablePath(exe_path.data(), &size) == 0 &&
+      realpath(exe_path.data(), buf) != 0) {
+    return internal_strlen(buf);
+  }
+  return 0;
+}
 
 void ReExec() {
   UNIMPLEMENTED();

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc?rev=230723&r1=230722&r2=230723&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc Thu Feb 26 21:12:19 2015
@@ -293,6 +293,14 @@ char *FindPathToBinary(const char *name)
   return 0;
 }
 
+bool IsPathSeparator(const char c) {
+  return c == '/';
+}
+
+bool IsAbsolutePath(const char *path) {
+  return path != nullptr && IsPathSeparator(path[0]);
+}
+
 void ReportFile::Write(const char *buffer, uptr length) {
   SpinMutexLock l(mu);
   static const char *kWriteError =

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_suppressions.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_suppressions.cc?rev=230723&r1=230722&r2=230723&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_suppressions.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_suppressions.cc Thu Feb 26 21:12:19 2015
@@ -30,18 +30,50 @@ SuppressionContext::SuppressionContext(c
   internal_memset(has_suppression_type_, 0, suppression_types_num_);
 }
 
+static bool GetPathAssumingFileIsRelativeToExec(const char *file_path,
+                                                /*out*/char *new_file_path,
+                                                uptr new_file_path_size) {
+  InternalScopedString exec(kMaxPathLength);
+  if (ReadBinaryName(exec.data(), exec.size())) {
+    const char *file_name_pos = StripModuleName(exec.data());
+    uptr path_to_exec_len = file_name_pos - exec.data();
+    internal_strncat(new_file_path, exec.data(),
+                     Min(path_to_exec_len, new_file_path_size - 1));
+    internal_strncat(new_file_path, file_path,
+                     new_file_path_size - internal_strlen(new_file_path) - 1);
+    return true;
+  }
+  return false;
+}
+
 void SuppressionContext::ParseFromFile(const char *filename) {
   if (filename[0] == '\0')
     return;
+
+  // If we cannot find the file, check if its location is relative to
+  // the location of the executable.
+  InternalScopedString new_file_path(kMaxPathLength);
+  if (!FileExists(filename) && !IsAbsolutePath(filename) &&
+      GetPathAssumingFileIsRelativeToExec(filename, new_file_path.data(),
+                                          new_file_path.size())) {
+    filename = new_file_path.data();
+  }
+
+  // Read the file.
   char *file_contents;
   uptr buffer_size;
-  uptr contents_size = ReadFileToBuffer(filename, &file_contents, &buffer_size,
-                                        1 << 26 /* max_len */);
+  const uptr max_len = 1 << 26;
+  uptr contents_size =
+    ReadFileToBuffer(filename, &file_contents, &buffer_size, max_len);
+  VPrintf(1, "%s: reading suppressions file at %s\n",
+          SanitizerToolName, filename);
+
   if (contents_size == 0) {
     Printf("%s: failed to read suppressions file '%s'\n", SanitizerToolName,
            filename);
     Die();
   }
+
   Parse(file_contents);
 }
 

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc?rev=230723&r1=230722&r2=230723&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc Thu Feb 26 21:12:19 2015
@@ -313,6 +313,19 @@ char *FindPathToBinary(const char *name)
   return 0;
 }
 
+uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
+  // Nothing here for now.
+  return 0;
+}
+
+bool IsPathSeparator(const char c) {
+  return c == '\\' || c == '/';
+}
+
+bool IsAbsolutePath(const char *path) {
+  UNIMPLEMENTED();
+}
+
 void SleepForSeconds(int seconds) {
   Sleep(seconds * 1000);
 }

Added: compiler-rt/trunk/test/asan/TestCases/suppressions-exec-relative-location.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/suppressions-exec-relative-location.cc?rev=230723&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/suppressions-exec-relative-location.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/suppressions-exec-relative-location.cc Thu Feb 26 21:12:19 2015
@@ -0,0 +1,47 @@
+// Check that without suppressions, we catch the issue.
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %run %t 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s
+
+// If the executable is started from a different location, we should still
+// find the suppression file located relative to the location of the executable.
+// RUN: rm -rf %T/suppressions-exec-relative-location
+// RUN: mkdir -p %T/suppressions-exec-relative-location
+// RUN: %clangxx_asan -O0 %s -o %T/suppressions-exec-relative-location/exec
+// RUN: echo "interceptor_via_fun:crash_function" > \
+// RUN:   %T/suppressions-exec-relative-location/supp.txt
+// RUN: ASAN_OPTIONS="suppressions=supp.txt" \
+// RUN:   %run %T/suppressions-exec-relative-location/exec 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK-IGNORE %s
+// RUN: rm -rf %T/suppressions-exec-relative-location
+
+// If the wrong absolute path is given, we don't try to construct
+// a relative path with it.
+// RUN: ASAN_OPTIONS="suppressions='/absolute/path'" not %run %t 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK-WRONG-FILE-NAME %s
+
+// Test that we reject directory as filename.
+// RUN: ASAN_OPTIONS="suppressions='folder/only/'" not %run %t 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK-WRONG-FILE-NAME %s
+
+// XFAIL: android
+// XFAIL: win32
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void crash_function() {
+  char *a = (char *)malloc(6);
+  free(a);
+  size_t len = strlen(a); // BOOM
+  fprintf(stderr, "strlen ignored, len = %zu\n", len);
+}
+
+int main() {
+  crash_function();
+}
+
+// CHECK-CRASH: AddressSanitizer: heap-use-after-free
+// CHECK-IGNORE-NOT: AddressSanitizer: heap-buffer-overflow
+// CHECK-IGNORE: ignored
+// CHECK-WRONG-FILE-NAME: failed to read suppressions file





More information about the llvm-commits mailing list