summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>2014-05-13 08:36:31 +0000
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>2014-05-13 08:36:31 +0000
commitcad7f30c4a24a2aaa81fac9e986d34bd6316b295 (patch)
tree5d3959a86918f49ba72b19ebdc0ead68922c02f3 /lib
parent50926f626de44bf11819b86e0f39240159c1e66d (diff)
[msan] Better open_memstream support.
Move fflush and fclose interceptors to sanitizer_common. Use a metadata map to keep information about the external locations that must be updated when the file is written to. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@208676 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/sanitizer_common/sanitizer_addrhashmap.h35
-rw-r--r--lib/sanitizer_common/sanitizer_common_interceptors.inc116
-rw-r--r--lib/sanitizer_common/sanitizer_platform_interceptors.h4
-rw-r--r--lib/sanitizer_common/sanitizer_platform_limits_posix.h4
-rw-r--r--lib/tsan/rtl/tsan_interceptors.cc26
5 files changed, 150 insertions, 35 deletions
diff --git a/lib/sanitizer_common/sanitizer_addrhashmap.h b/lib/sanitizer_common/sanitizer_addrhashmap.h
index c50fb1e33..e09192643 100644
--- a/lib/sanitizer_common/sanitizer_addrhashmap.h
+++ b/lib/sanitizer_common/sanitizer_addrhashmap.h
@@ -17,6 +17,7 @@
#include "sanitizer_common.h"
#include "sanitizer_mutex.h"
#include "sanitizer_atomic.h"
+#include "sanitizer_allocator_internal.h"
namespace __sanitizer {
@@ -66,9 +67,12 @@ class AddrHashMap {
class Handle {
public:
- Handle(AddrHashMap<T, kSize> *map, uptr addr, bool remove = false);
+ Handle(AddrHashMap<T, kSize> *map, uptr addr);
+ Handle(AddrHashMap<T, kSize> *map, uptr addr, bool remove);
+ Handle(AddrHashMap<T, kSize> *map, uptr addr, bool remove, bool create);
+
~Handle();
- T *operator -> ();
+ T *operator->();
bool created() const;
bool exists() const;
@@ -81,6 +85,7 @@ class AddrHashMap {
uptr addidx_;
bool created_;
bool remove_;
+ bool create_;
};
private:
@@ -93,11 +98,31 @@ class AddrHashMap {
};
template<typename T, uptr kSize>
+AddrHashMap<T, kSize>::Handle::Handle(AddrHashMap<T, kSize> *map, uptr addr) {
+ map_ = map;
+ addr_ = addr;
+ remove_ = false;
+ create_ = true;
+ map_->acquire(this);
+}
+
+template<typename T, uptr kSize>
AddrHashMap<T, kSize>::Handle::Handle(AddrHashMap<T, kSize> *map, uptr addr,
bool remove) {
map_ = map;
addr_ = addr;
remove_ = remove;
+ create_ = true;
+ map_->acquire(this);
+}
+
+template<typename T, uptr kSize>
+AddrHashMap<T, kSize>::Handle::Handle(AddrHashMap<T, kSize> *map, uptr addr,
+ bool remove, bool create) {
+ map_ = map;
+ addr_ = addr;
+ remove_ = remove;
+ create_ = create;
map_->acquire(this);
}
@@ -106,8 +131,8 @@ AddrHashMap<T, kSize>::Handle::~Handle() {
map_->release(this);
}
-template<typename T, uptr kSize>
-T *AddrHashMap<T, kSize>::Handle::operator -> () {
+template <typename T, uptr kSize>
+T *AddrHashMap<T, kSize>::Handle::operator->() {
return &cell_->val;
}
@@ -207,7 +232,7 @@ void AddrHashMap<T, kSize>::acquire(Handle *h) {
}
// The element does not exist, no need to create it if we want to remove.
- if (h->remove_) {
+ if (h->remove_ || !h->create_) {
b->mtx.Unlock();
return;
}
diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 2ff721820..31ec78bff 100644
--- a/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -28,6 +28,8 @@
// COMMON_INTERCEPTOR_HANDLE_RECVMSG
//===----------------------------------------------------------------------===//
#include "interception/interception.h"
+#include "sanitizer_addrhashmap.h"
+#include "sanitizer_placement_new.h"
#include "sanitizer_platform_interceptors.h"
#include "sanitizer_tls_get_addr.h"
@@ -73,6 +75,52 @@
#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) {}
#endif
+struct FileMetadata {
+ // For open_memstream().
+ char **addr;
+ SIZE_T *size;
+};
+
+struct CommonInterceptorMetadata {
+ enum {
+ CIMT_INVALID = 0,
+ CIMT_FILE
+ } type;
+ union {
+ FileMetadata file;
+ };
+};
+
+typedef AddrHashMap<CommonInterceptorMetadata, 31051> MetadataHashMap;
+
+static MetadataHashMap *interceptor_metadata_map;
+
+static void SetInterceptorMetadata(__sanitizer_FILE *addr,
+ const FileMetadata &file) {
+ MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr);
+ CHECK(h.created());
+ h->type = CommonInterceptorMetadata::CIMT_FILE;
+ h->file = file;
+}
+
+static const FileMetadata *GetInterceptorMetadata(__sanitizer_FILE *addr) {
+ MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr,
+ /* remove */ false,
+ /* create */ false);
+ if (h.exists()) {
+ CHECK(!h.created());
+ CHECK(h->type == CommonInterceptorMetadata::CIMT_FILE);
+ return &h->file;
+ } else {
+ return 0;
+ }
+}
+
+static void DeleteInterceptorMetadata(void *addr) {
+ MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr, true);
+ CHECK(h.exists());
+}
+
#if SANITIZER_INTERCEPT_TEXTDOMAIN
INTERCEPTOR(char*, textdomain, const char *domainname) {
void *ctx;
@@ -624,6 +672,14 @@ INTERCEPTOR(char *, strptime, char *s, char *format, __sanitizer_tm *tm) {
#define INIT_STRPTIME
#endif
+void update_FILE(__sanitizer_FILE *fp) {
+#if SANITIZER_HAS_STRUCT_FILE
+ const FileMetadata *m = GetInterceptorMetadata(fp);
+ if (m)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
+#endif // SANITIZER_HAS_STRUCT_FILE
+}
+
#if SANITIZER_INTERCEPT_SCANF || SANITIZER_INTERCEPT_PRINTF
#include "sanitizer_common_interceptors_format.inc"
@@ -789,7 +845,8 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
INTERCEPTOR(int, vprintf, const char *format, va_list ap)
VPRINTF_INTERCEPTOR_IMPL(vprintf, format, ap)
-INTERCEPTOR(int, vfprintf, void *stream, const char *format, va_list ap)
+INTERCEPTOR(int, vfprintf, __sanitizer_FILE *stream, const char *format,
+ va_list ap)
VPRINTF_INTERCEPTOR_IMPL(vfprintf, stream, format, ap)
INTERCEPTOR(int, vsnprintf, char *str, SIZE_T size, const char *format,
@@ -806,8 +863,8 @@ VASPRINTF_INTERCEPTOR_IMPL(vasprintf, strp, format, ap)
INTERCEPTOR(int, __isoc99_vprintf, const char *format, va_list ap)
VPRINTF_INTERCEPTOR_IMPL(__isoc99_vprintf, format, ap)
-INTERCEPTOR(int, __isoc99_vfprintf, void *stream, const char *format,
- va_list ap)
+INTERCEPTOR(int, __isoc99_vfprintf, __sanitizer_FILE *stream,
+ const char *format, va_list ap)
VPRINTF_INTERCEPTOR_IMPL(__isoc99_vfprintf, stream, format, ap)
INTERCEPTOR(int, __isoc99_vsnprintf, char *str, SIZE_T size, const char *format,
@@ -824,7 +881,7 @@ VSPRINTF_INTERCEPTOR_IMPL(__isoc99_vsprintf, str, format,
INTERCEPTOR(int, printf, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(printf, vprintf, format)
-INTERCEPTOR(int, fprintf, void *stream, const char *format, ...)
+INTERCEPTOR(int, fprintf, __sanitizer_FILE *stream, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(fprintf, vfprintf, stream, format)
INTERCEPTOR(int, sprintf, char *str, const char *format, ...) // NOLINT
@@ -840,7 +897,8 @@ FORMAT_INTERCEPTOR_IMPL(asprintf, vasprintf, strp, format)
INTERCEPTOR(int, __isoc99_printf, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc99_printf, __isoc99_vprintf, format)
-INTERCEPTOR(int, __isoc99_fprintf, void *stream, const char *format, ...)
+INTERCEPTOR(int, __isoc99_fprintf, __sanitizer_FILE *stream, const char *format,
+ ...)
FORMAT_INTERCEPTOR_IMPL(__isoc99_fprintf, __isoc99_vfprintf, stream, format)
INTERCEPTOR(int, __isoc99_sprintf, char *str, const char *format, ...)
@@ -3729,10 +3787,12 @@ INTERCEPTOR(void *, tsearch, void *key, void **rootp,
#if SANITIZER_INTERCEPT_LIBIO_INTERNALS || SANITIZER_INTERCEPT_FOPEN || \
SANITIZER_INTERCEPT_OPEN_MEMSTREAM
void unpoison_file(__sanitizer_FILE *fp) {
+#if SANITIZER_HAS_STRUCT_FILE
COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp, sizeof(*fp));
if (fp->_IO_read_base && fp->_IO_read_base < fp->_IO_read_end)
COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_IO_read_base,
fp->_IO_read_end - fp->_IO_read_base);
+#endif // SANITIZER_HAS_STRUCT_FILE
}
#endif
@@ -3863,6 +3923,8 @@ INTERCEPTOR(__sanitizer_FILE *, open_memstream, char **ptr, SIZE_T *sizeloc) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc));
unpoison_file(res);
+ FileMetadata file = {ptr, sizeloc};
+ SetInterceptorMetadata(res, file);
}
return res;
}
@@ -3875,6 +3937,8 @@ INTERCEPTOR(__sanitizer_FILE *, open_wmemstream, wchar_t **ptr,
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc));
unpoison_file(res);
+ FileMetadata file = {(char **)ptr, sizeloc};
+ SetInterceptorMetadata(res, file);
}
return res;
}
@@ -3937,7 +4001,47 @@ INTERCEPTOR(void, _obstack_newchunk, __sanitizer_obstack *obstack, int length) {
#define INIT_OBSTACK
#endif
+#if SANITIZER_INTERCEPT_FFLUSH
+INTERCEPTOR(int, fflush, __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fflush, fp);
+ int res = REAL(fflush)(fp);
+ // FIXME: handle fp == NULL
+ if (fp) {
+ const FileMetadata *m = GetInterceptorMetadata(fp);
+ if (m) COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
+ }
+ return res;
+}
+#define INIT_FFLUSH COMMON_INTERCEPT_FUNCTION(fflush);
+#else
+#define INIT_FFLUSH
+#endif
+
+#if SANITIZER_INTERCEPT_FCLOSE
+INTERCEPTOR(int, fclose, __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fclose, fp);
+ int res = REAL(fclose)(fp);
+ if (fp) {
+ COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
+ const FileMetadata *m = GetInterceptorMetadata(fp);
+ if (m) {
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
+ DeleteInterceptorMetadata(fp);
+ }
+ }
+ return res;
+}
+#define INIT_FCLOSE COMMON_INTERCEPT_FUNCTION(fclose);
+#else
+#define INIT_FCLOSE
+#endif
+
static void InitializeCommonInterceptors() {
+ static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
+ interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap();
+
INIT_TEXTDOMAIN;
INIT_STRCMP;
INIT_STRNCMP;
@@ -4072,4 +4176,6 @@ static void InitializeCommonInterceptors() {
INIT_FOPEN;
INIT_OPEN_MEMSTREAM;
INIT_OBSTACK;
+ INIT_FFLUSH;
+ INIT_FCLOSE;
}
diff --git a/lib/sanitizer_common/sanitizer_platform_interceptors.h b/lib/sanitizer_common/sanitizer_platform_interceptors.h
index d8c25874d..62c71faf7 100644
--- a/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -197,8 +197,10 @@
#define SANITIZER_INTERCEPT_XDR SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_TSEARCH SI_LINUX_NOT_ANDROID || SI_MAC
#define SANITIZER_INTERCEPT_LIBIO_INTERNALS SI_LINUX_NOT_ANDROID
-#define SANITIZER_INTERCEPT_FOPEN SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_FOPEN SI_NOT_WINDOWS
#define SANITIZER_INTERCEPT_OPEN_MEMSTREAM SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_OBSTACK SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_FFLUSH SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_FCLOSE SI_NOT_WINDOWS
#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/lib/sanitizer_common/sanitizer_platform_limits_posix.h
index cfe0d9946..d83ec8c81 100644
--- a/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -661,6 +661,10 @@ namespace __sanitizer {
__sanitizer_FILE *_chain;
int _fileno;
};
+# define SANITIZER_HAS_STRUCT_FILE 1
+#else
+ typedef void __sanitizer_FILE;
+# define SANITIZER_HAS_STRUCT_FILE 0
#endif
#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc
index 5c7e80652..8cfd80ba5 100644
--- a/lib/tsan/rtl/tsan_interceptors.cc
+++ b/lib/tsan/rtl/tsan_interceptors.cc
@@ -53,6 +53,7 @@ extern "C" int pthread_sigmask(int how, const __sanitizer_sigset_t *set,
__sanitizer_sigset_t *oldset);
// REAL(sigfillset) defined in common interceptors.
DECLARE_REAL(int, sigfillset, __sanitizer_sigset_t *set)
+DECLARE_REAL(int, fflush, __sanitizer_FILE *fp)
extern "C" void *pthread_self();
extern "C" void _exit(int status);
extern "C" int *__errno_location();
@@ -62,7 +63,7 @@ extern "C" void *__libc_calloc(uptr size, uptr n);
extern "C" void *__libc_realloc(void *ptr, uptr size);
extern "C" void __libc_free(void *ptr);
extern "C" int mallopt(int param, int value);
-extern void *stdout, *stderr;
+extern __sanitizer_FILE *stdout, *stderr;
const int PTHREAD_MUTEX_RECURSIVE = 1;
const int PTHREAD_MUTEX_RECURSIVE_NP = 1;
const int EINVAL = 22;
@@ -1621,19 +1622,6 @@ TSAN_INTERCEPTOR(void*, tmpfile64, int fake) {
return res;
}
-TSAN_INTERCEPTOR(int, fclose, void *stream) {
- // libc file streams can call user-supplied functions, see fopencookie.
- {
- SCOPED_TSAN_INTERCEPTOR(fclose, stream);
- if (stream) {
- int fd = fileno_unlocked(stream);
- if (fd >= 0)
- FdClose(thr, pc, fd);
- }
- }
- return REAL(fclose)(stream);
-}
-
TSAN_INTERCEPTOR(uptr, fread, void *ptr, uptr size, uptr nmemb, void *f) {
// libc file streams can call user-supplied functions, see fopencookie.
{
@@ -1652,14 +1640,6 @@ TSAN_INTERCEPTOR(uptr, fwrite, const void *p, uptr size, uptr nmemb, void *f) {
return REAL(fwrite)(p, size, nmemb, f);
}
-TSAN_INTERCEPTOR(int, fflush, void *stream) {
- // libc file streams can call user-supplied functions, see fopencookie.
- {
- SCOPED_TSAN_INTERCEPTOR(fflush, stream);
- }
- return REAL(fflush)(stream);
-}
-
TSAN_INTERCEPTOR(void, abort, int fake) {
SCOPED_TSAN_INTERCEPTOR(abort, fake);
REAL(fflush)(0);
@@ -2367,10 +2347,8 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(unlink);
TSAN_INTERCEPT(tmpfile);
TSAN_INTERCEPT(tmpfile64);
- TSAN_INTERCEPT(fclose);
TSAN_INTERCEPT(fread);
TSAN_INTERCEPT(fwrite);
- TSAN_INTERCEPT(fflush);
TSAN_INTERCEPT(abort);
TSAN_INTERCEPT(puts);
TSAN_INTERCEPT(rmdir);