summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_common.h5
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_linux.h2
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_mac.cc17
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_posix.cc8
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc36
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_win.cc13
-rw-r--r--compiler-rt/test/asan/TestCases/suppressions-exec-relative-location.cc47
7 files changed, 124 insertions, 4 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
index f4eed0c5f33..486efc98a7e 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
@@ -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();
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h
index b2e603d3a23..2ce2025d2ab 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h
@@ -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();
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc
index 39a5c7e8d24..9669402865e 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc
@@ -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>
@@ -204,6 +206,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();
}
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc
index 5bc41c2580f..b8bd1b2b8e5 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc
@@ -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 =
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc b/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc
index 2b697e95570..8009b4d6aad 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc
@@ -30,18 +30,50 @@ SuppressionContext::SuppressionContext(const char *suppression_types[],
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);
}
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cc b/compiler-rt/lib/sanitizer_common/sanitizer_win.cc
index 335cecabe11..e019d0302e8 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cc
@@ -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);
}
diff --git a/compiler-rt/test/asan/TestCases/suppressions-exec-relative-location.cc b/compiler-rt/test/asan/TestCases/suppressions-exec-relative-location.cc
new file mode 100644
index 00000000000..cc69b7a6e2c
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/suppressions-exec-relative-location.cc
@@ -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
OpenPOWER on IntegriCloud