summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_linux.cc4
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_mac.cc4
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_netbsd.cc5
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_posix.cc24
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_posix.h4
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_rtems.cc2
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_solaris.cc4
-rw-r--r--compiler-rt/test/asan/TestCases/Posix/no-fd.cc39
8 files changed, 76 insertions, 10 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
index 6cfb6150674..ecc5bacbf7f 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
@@ -381,6 +381,10 @@ uptr internal_filesize(fd_t fd) {
return (uptr)st.st_size;
}
+uptr internal_dup(int oldfd) {
+ return internal_syscall(SYSCALL(dup), oldfd);
+}
+
uptr internal_dup2(int oldfd, int newfd) {
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
return internal_syscall(SYSCALL(dup3), oldfd, newfd, 0);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc
index 95c47babe08..e738ff1e90c 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc
@@ -174,6 +174,10 @@ uptr internal_filesize(fd_t fd) {
return (uptr)st.st_size;
}
+uptr internal_dup(int oldfd) {
+ return dup(oldfd);
+}
+
uptr internal_dup2(int oldfd, int newfd) {
return dup2(oldfd, newfd);
}
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_netbsd.cc b/compiler-rt/lib/sanitizer_common/sanitizer_netbsd.cc
index cdf552c8f24..80d0855efab 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_netbsd.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_netbsd.cc
@@ -169,6 +169,11 @@ uptr internal_filesize(fd_t fd) {
return (uptr)st.st_size;
}
+uptr internal_dup(int oldfd) {
+ DEFINE__REAL(int, dup, int a);
+ return _REAL(dup, oldfd);
+}
+
uptr internal_dup2(int oldfd, int newfd) {
DEFINE__REAL(int, dup2, int a, int b);
return _REAL(dup2, oldfd, newfd);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc
index 116270f8d23..c92986c1786 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc
@@ -166,7 +166,7 @@ fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *errno_p) {
fd_t res = internal_open(filename, flags, 0660);
if (internal_iserror(res, errno_p))
return kInvalidFd;
- return res;
+ return ReserveStandardFds(res);
}
void CloseFile(fd_t fd) {
@@ -269,13 +269,8 @@ bool IsAbsolutePath(const char *path) {
void ReportFile::Write(const char *buffer, uptr length) {
SpinMutexLock l(mu);
- static const char *kWriteError =
- "ReportFile::Write() can't output requested buffer!\n";
ReopenIfNecessary();
- if (length != internal_write(fd, buffer, length)) {
- internal_write(fd, kWriteError, internal_strlen(kWriteError));
- Die();
- }
+ internal_write(fd, buffer, length);
}
bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end) {
@@ -323,6 +318,21 @@ const char *SignalContext::Describe() const {
return "UNKNOWN SIGNAL";
}
+fd_t ReserveStandardFds(fd_t fd) {
+ CHECK_GE(fd, 0);
+ if (fd > 2)
+ return fd;
+ bool used[3] = {false, false, false};
+ while (fd <= 2) {
+ used[fd] = true;
+ fd = internal_dup(fd);
+ }
+ for (int i = 0; i <= 2; ++i)
+ if (used[i])
+ internal_close(i);
+ return fd;
+}
+
} // namespace __sanitizer
#endif // SANITIZER_POSIX
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_posix.h
index 2ebfae8ba2f..37f27d56707 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_posix.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix.h
@@ -49,6 +49,7 @@ uptr internal_filesize(fd_t fd); // -1 on error.
uptr internal_stat(const char *path, void *buf);
uptr internal_lstat(const char *path, void *buf);
uptr internal_fstat(fd_t fd, void *buf);
+uptr internal_dup(int oldfd);
uptr internal_dup2(int oldfd, int newfd);
uptr internal_readlink(const char *path, char *buf, uptr bufsize);
uptr internal_unlink(const char *path);
@@ -99,6 +100,9 @@ uptr internal_execve(const char *filename, char *const argv[],
bool IsStateDetached(int state);
+// Move the fd out of {0, 1, 2} range.
+fd_t ReserveStandardFds(fd_t fd);
+
} // namespace __sanitizer
#endif // SANITIZER_POSIX_H
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_rtems.cc b/compiler-rt/lib/sanitizer_common/sanitizer_rtems.cc
index 678906a187a..ebf05db2573 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_rtems.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_rtems.cc
@@ -200,7 +200,7 @@ fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *errno_p) {
fd_t res = open(filename, flags, 0660);
if (internal_iserror(res, errno_p))
return kInvalidFd;
- return res;
+ return ReserveStandardFds(res);
}
void CloseFile(fd_t fd) {
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_solaris.cc b/compiler-rt/lib/sanitizer_common/sanitizer_solaris.cc
index 9d0c3d93d44..cc0201c7a37 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_solaris.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_solaris.cc
@@ -88,8 +88,8 @@ uptr internal_open(const char *filename, int flags, u32 mode) {
}
uptr OpenFile(const char *filename, bool write) {
- return internal_open(filename,
- write ? O_WRONLY | O_CREAT : O_RDONLY, 0660);
+ return ReserveStandardFds(
+ internal_open(filename, write ? O_WRONLY | O_CREAT : O_RDONLY, 0660));
}
DECLARE__REAL_AND_INTERNAL(uptr, read, fd_t fd, void *buf, uptr count) {
diff --git a/compiler-rt/test/asan/TestCases/Posix/no-fd.cc b/compiler-rt/test/asan/TestCases/Posix/no-fd.cc
new file mode 100644
index 00000000000..1c94545c7b3
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/Posix/no-fd.cc
@@ -0,0 +1,39 @@
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+// RUN: %env_asan_opts=debug=1,verbosity=2 %run %t 2>&1 | FileCheck %s
+
+// Test ASan initialization
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+void parent(int argc, char **argv) {
+ fprintf(stderr, "hello\n");
+ // CHECK: hello
+ close(0);
+ close(1);
+ dup2(2, 3);
+ close(2);
+ char *const newargv[] = {argv[0], (char *)"x", nullptr};
+ execv(argv[0], newargv);
+ perror("execve");
+ exit(1);
+}
+
+void child() {
+ assert(dup(3) == 0);
+ assert(dup(3) == 1);
+ assert(dup(3) == 2);
+ fprintf(stderr, "world\n");
+ // CHECK: world
+}
+
+int main(int argc, char **argv) {
+ if (argc == 1) {
+ parent(argc, argv);
+ } else {
+ child();
+ }
+}
OpenPOWER on IntegriCloud