forked from OSchip/llvm-project
[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. llvm-svn: 230723
This commit is contained in:
parent
5bc883f39e
commit
2249049db2
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue