[sanitizer] Check if directory exists before trying to create
Add a DirExists mechanism, modeled after FileExists. Use it to guard creation of the report path directory. This should avoid failures running the sanitizer in a sandbox where the file creation attempt causes hard failures, even for an existing directory. Problem reported on D109794 for ChromeOS in sandbox (https://issuetracker.google.com/209296420). Differential Revision: https://reviews.llvm.org/D119495
This commit is contained in:
parent
0e4ecfaf5a
commit
634da7a1c6
|
@ -84,8 +84,12 @@ static void RecursiveCreateParentDirs(char *path) {
|
|||
if (!IsPathSeparator(path[i]))
|
||||
continue;
|
||||
path[i] = '\0';
|
||||
/* Some of these will fail, because the directory exists, ignore it. */
|
||||
CreateDir(path);
|
||||
if (!DirExists(path) && !CreateDir(path)) {
|
||||
const char *ErrorMsgPrefix = "ERROR: Can't create directory: ";
|
||||
WriteToFile(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix));
|
||||
WriteToFile(kStderrFd, path, internal_strlen(path));
|
||||
Die();
|
||||
}
|
||||
path[i] = save;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ bool SupportsColoredOutput(fd_t fd);
|
|||
// OS
|
||||
const char *GetPwd();
|
||||
bool FileExists(const char *filename);
|
||||
bool DirExists(const char *path);
|
||||
char *FindPathToBinary(const char *name);
|
||||
bool IsPathSeparator(const char c);
|
||||
bool IsAbsolutePath(const char *path);
|
||||
|
|
|
@ -499,7 +499,18 @@ bool FileExists(const char *filename) {
|
|||
return S_ISREG(st.st_mode);
|
||||
}
|
||||
|
||||
#if !SANITIZER_NETBSD
|
||||
bool DirExists(const char *path) {
|
||||
struct stat st;
|
||||
# if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
|
||||
if (internal_syscall(SYSCALL(newfstatat), AT_FDCWD, path, &st, 0))
|
||||
# else
|
||||
if (internal_stat(path, &st))
|
||||
# endif
|
||||
return false;
|
||||
return S_ISDIR(st.st_mode);
|
||||
}
|
||||
|
||||
# if !SANITIZER_NETBSD
|
||||
tid_t GetTid() {
|
||||
#if SANITIZER_FREEBSD
|
||||
long Tid;
|
||||
|
|
|
@ -393,6 +393,13 @@ bool FileExists(const char *filename) {
|
|||
return S_ISREG(st.st_mode);
|
||||
}
|
||||
|
||||
bool DirExists(const char *path) {
|
||||
struct stat st;
|
||||
if (stat(path, &st))
|
||||
return false;
|
||||
return S_ISDIR(st.st_mode);
|
||||
}
|
||||
|
||||
tid_t GetTid() {
|
||||
tid_t tid;
|
||||
pthread_threadid_np(nullptr, &tid);
|
||||
|
|
|
@ -93,6 +93,11 @@ bool FileExists(const char *filename) {
|
|||
return ::GetFileAttributesA(filename) != INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
bool DirExists(const char *path) {
|
||||
auto attr = ::GetFileAttributesA(path);
|
||||
return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);
|
||||
}
|
||||
|
||||
uptr internal_getpid() {
|
||||
return GetProcessId(GetCurrentProcess());
|
||||
}
|
||||
|
|
|
@ -63,6 +63,20 @@ struct stat_and_more {
|
|||
unsigned char z;
|
||||
};
|
||||
|
||||
static void get_temp_dir(char *buf, size_t bufsize) {
|
||||
#if SANITIZER_WINDOWS
|
||||
buf[0] = '\0';
|
||||
if (!::GetTempPathA(bufsize, buf))
|
||||
return;
|
||||
#else
|
||||
const char *tmpdir = "/tmp";
|
||||
# if SANITIZER_ANDROID
|
||||
tmpdir = GetEnv("TMPDIR");
|
||||
# endif
|
||||
internal_snprintf(buf, bufsize, "%s", tmpdir);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void temp_file_name(char *buf, size_t bufsize, const char *prefix) {
|
||||
#if SANITIZER_WINDOWS
|
||||
buf[0] = '\0';
|
||||
|
@ -340,3 +354,19 @@ TEST(SanitizerCommon, ReportFile) {
|
|||
report_file.SetReportPath("stderr");
|
||||
Unlink(tmpfile);
|
||||
}
|
||||
|
||||
TEST(SanitizerCommon, FileExists) {
|
||||
char tmpfile[128];
|
||||
temp_file_name(tmpfile, sizeof(tmpfile), "sanitizer_common.fileexists.tmp.");
|
||||
fd_t fd = OpenFile(tmpfile, WrOnly);
|
||||
ASSERT_NE(fd, kInvalidFd);
|
||||
EXPECT_TRUE(FileExists(tmpfile));
|
||||
CloseFile(fd);
|
||||
Unlink(tmpfile);
|
||||
}
|
||||
|
||||
TEST(SanitizerCommon, DirExists) {
|
||||
char tmpdir[128];
|
||||
get_temp_dir(tmpdir, sizeof(tmpdir));
|
||||
EXPECT_TRUE(DirExists(tmpdir));
|
||||
}
|
||||
|
|
|
@ -16,10 +16,14 @@
|
|||
// RUN: %env_asan_opts=log_path=%t.log not %run %t 2> %t.out
|
||||
// RUN: FileCheck %s --check-prefix=CHECK-ERROR < %t.log.*
|
||||
|
||||
// Invalid log_path.
|
||||
// RUN: %env_asan_opts=log_path=/dev/null/INVALID not %run %t 2> %t.out
|
||||
// Invalid log_path in existing directory.
|
||||
// RUN: %env_asan_opts=log_path=/INVALID not %run %t 2> %t.out
|
||||
// RUN: FileCheck %s --check-prefix=CHECK-INVALID < %t.out
|
||||
|
||||
// Directory of log_path can't be created.
|
||||
// RUN: %env_asan_opts=log_path=/dev/null/INVALID not %run %t 2> %t.out
|
||||
// RUN: FileCheck %s --check-prefix=CHECK-BAD-DIR < %t.out
|
||||
|
||||
// Too long log_path.
|
||||
// RUN: %env_asan_opts=log_path=`for((i=0;i<10000;i++)); do echo -n $i; done` \
|
||||
// RUN: not %run %t 2> %t.out
|
||||
|
@ -44,5 +48,6 @@ int main(int argc, char **argv) {
|
|||
return res;
|
||||
}
|
||||
// CHECK-ERROR: ERROR: AddressSanitizer
|
||||
// CHECK-INVALID: ERROR: Can't open file: /dev/null/INVALID
|
||||
// CHECK-INVALID: ERROR: Can't open file: /INVALID
|
||||
// CHECK-BAD-DIR: ERROR: Can't create directory: /dev/null
|
||||
// CHECK-LONG: ERROR: Path is too long: 01234
|
||||
|
|
|
@ -3,18 +3,21 @@
|
|||
//
|
||||
// RUN: %clangxx_memprof %s -o %t
|
||||
|
||||
// stderr print_text=true:log_path
|
||||
// stderr log_path
|
||||
// RUN: %env_memprof_opts=print_text=true:log_path=stderr %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-GOOD --dump-input=always
|
||||
|
||||
// Good print_text=true:log_path.
|
||||
// Good log_path.
|
||||
// RUN: rm -f %t.log.*
|
||||
// RUN: %env_memprof_opts=print_text=true:log_path=%t.log %run %t
|
||||
// RUN: FileCheck %s --check-prefix=CHECK-GOOD --dump-input=always < %t.log.*
|
||||
|
||||
// Invalid print_text=true:log_path.
|
||||
// RUN: %env_memprof_opts=print_text=true:log_path=/dev/null/INVALID not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-INVALID --dump-input=always
|
||||
// Invalid log_path.
|
||||
// RUN: %env_memprof_opts=print_text=true:log_path=/INVALID not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-INVALID --dump-input=always
|
||||
|
||||
// Too long print_text=true:log_path.
|
||||
// Directory of log_path can't be created.
|
||||
// RUN: %env_memprof_opts=print_text=true:log_path=/dev/null/INVALID not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-BAD-DIR --dump-input=always
|
||||
|
||||
// Too long log_path.
|
||||
// RUN: %env_memprof_opts=print_text=true:log_path=`for((i=0;i<10000;i++)); do echo -n $i; done` \
|
||||
// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-LONG --dump-input=always
|
||||
|
||||
|
@ -24,7 +27,7 @@
|
|||
// Using an automatically generated name via %t can cause weird issues with
|
||||
// unexpected macro expansion if the path includes tokens that match a build
|
||||
// system macro (e.g. "linux").
|
||||
// RUN: %clangxx_memprof %s -o %t -DPROFILE_NAME_VAR="/dev/null/INVALID"
|
||||
// RUN: %clangxx_memprof %s -o %t -DPROFILE_NAME_VAR="/INVALID"
|
||||
// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-INVALID --dump-input=always
|
||||
|
||||
#include <sanitizer/memprof_interface.h>
|
||||
|
@ -45,5 +48,6 @@ int main(int argc, char **argv) {
|
|||
return 0;
|
||||
}
|
||||
// CHECK-GOOD: Memory allocation stack id
|
||||
// CHECK-INVALID: ERROR: Can't open file: /dev/null/INVALID
|
||||
// CHECK-INVALID: ERROR: Can't open file: /INVALID
|
||||
// CHECK-BAD-DIR: ERROR: Can't create directory: /dev/null
|
||||
// CHECK-LONG: ERROR: Path is too long: 01234
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
// Test __sanitizer_set_report_path and __sanitizer_get_report_path:
|
||||
// RUN: rm -rf %t.report_path
|
||||
// RUN: %clangxx -O2 %s -o %t
|
||||
// RUN: %run %t | FileCheck %s
|
||||
// Try again with a directory without write access.
|
||||
// RUN: rm -rf %t.report_path && mkdir -p %t.report_path
|
||||
// RUN: chmod u-w %t.report_path || true
|
||||
// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=FAIL
|
||||
|
||||
#include <assert.h>
|
||||
#include <sanitizer/common_interface_defs.h>
|
||||
|
@ -18,3 +23,4 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
// CHECK: Path {{.*}}Posix/Output/sanitizer_set_report_path_test.cpp.tmp.report_path/report.
|
||||
// FAIL: ERROR: Can't open file: {{.*}}Posix/Output/sanitizer_set_report_path_test.cpp.tmp.report_path/report.
|
||||
|
|
Loading…
Reference in a new issue