[compiler-rt] r208676 - [msan] Better open_memstream support.

Evgeniy Stepanov eugeni.stepanov at gmail.com
Tue May 13 01:36:32 PDT 2014


Author: eugenis
Date: Tue May 13 03:36:31 2014
New Revision: 208676

URL: http://llvm.org/viewvc/llvm-project?rev=208676&view=rev
Log:
[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.

Added:
    compiler-rt/trunk/test/sanitizer_common/TestCases/open_memstream.cc   (with props)
Removed:
    compiler-rt/trunk/test/msan/open_memstream.cc
Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_addrhashmap.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_addrhashmap.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_addrhashmap.h?rev=208676&r1=208675&r2=208676&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_addrhashmap.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_addrhashmap.h Tue May 13 03:36:31 2014
@@ -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(Hand
   }
 
   // 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;
   }

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc?rev=208676&r1=208675&r2=208676&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc Tue May 13 03:36:31 2014
@@ -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, c
 #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,
 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, st
 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_vspri
 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, vaspri
 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,
 #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_mem
     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_wme
     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, __s
 #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;
 }

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h?rev=208676&r1=208675&r2=208676&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h Tue May 13 03:36:31 2014
@@ -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

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h?rev=208676&r1=208675&r2=208676&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h Tue May 13 03:36:31 2014
@@ -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 && \

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=208676&r1=208675&r2=208676&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Tue May 13 03:36:31 2014
@@ -53,6 +53,7 @@ extern "C" int pthread_sigmask(int how,
                                __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
 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 f
   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 voi
   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);

Removed: compiler-rt/trunk/test/msan/open_memstream.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/msan/open_memstream.cc?rev=208675&view=auto
==============================================================================
--- compiler-rt/trunk/test/msan/open_memstream.cc (original)
+++ compiler-rt/trunk/test/msan/open_memstream.cc (removed)
@@ -1,18 +0,0 @@
-// RUN: %clangxx_msan -m64 -O0 -g -xc++ %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O3 -g -xc++ %s -o %t && %run %t
-
-#include <stdio.h>
-#include <stdlib.h>
-
-int main(void) {
-  char *buf;
-  size_t buf_len = 42;
-  FILE *fp = open_memstream(&buf, &buf_len);
-  fprintf(fp, "hello");
-  fflush(fp);
-  printf("buf_len = %zu\n", buf_len);
-  for (int j = 0; j < buf_len; j++) {
-    printf("buf[%d] = %c\n", j, buf[j]);
-  }
-  return 0;
-}

Added: compiler-rt/trunk/test/sanitizer_common/TestCases/open_memstream.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/sanitizer_common/TestCases/open_memstream.cc?rev=208676&view=auto
==============================================================================
--- compiler-rt/trunk/test/sanitizer_common/TestCases/open_memstream.cc (added)
+++ compiler-rt/trunk/test/sanitizer_common/TestCases/open_memstream.cc Tue May 13 03:36:31 2014
@@ -0,0 +1,57 @@
+// RUN: %clangxx -m64 -O0 -g -xc++ %s -o %t && %run %t
+// RUN: %clangxx -m64 -O3 -g -xc++ %s -o %t && %run %t
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef __has_feature
+#define __has_feature(x) 0
+#endif
+
+#if __has_feature(memory_sanitizer)
+#include <sanitizer/msan_interface.h>
+static void check_mem_is_good(void *p, size_t s) {
+  __msan_check_mem_is_initialized(p, s);
+}
+#elif __has_feature(address_sanitizer)
+#include <sanitizer/asan_interface.h>
+static void check_mem_is_good(void *p, size_t s) {
+  assert(__asan_region_is_poisoned(p, s) == 0);
+}
+#else
+static void check_mem_is_good(void *p, size_t s) {}
+#endif
+
+static void run(void) {
+  char *buf;
+  size_t buf_len;
+  fprintf(stderr, " &buf %p, &buf_len %p\n", &buf, &buf_len);
+  FILE *fp = open_memstream(&buf, &buf_len);
+  fprintf(fp, "hello");
+  fflush(fp);
+  check_mem_is_good(&buf, sizeof(buf));
+  check_mem_is_good(&buf_len, sizeof(buf_len));
+  check_mem_is_good(buf, buf_len);
+
+  char *p = new char[1024];
+  memset(p, 'a', 1023);
+  p[1023] = 0;
+  for (int i = 0; i < 100; ++i)
+    fprintf(fp, "%s", p);
+  delete[] p;
+  fflush(fp);
+  fprintf(stderr, " %p addr %p, len %zu\n", &buf, buf, buf_len);
+  check_mem_is_good(&buf, sizeof(buf));
+  check_mem_is_good(&buf_len, sizeof(buf_len));
+  check_mem_is_good(buf, buf_len);
+  fclose(fp);
+  free(buf);
+}
+
+int main(void) {
+  for (int i = 0; i < 100; ++i)
+    run();
+  return 0;
+}

Propchange: compiler-rt/trunk/test/sanitizer_common/TestCases/open_memstream.cc
------------------------------------------------------------------------------
    svn:eol-style = LF





More information about the llvm-commits mailing list