[compiler-rt] r321365 - [MSan, TSan] Add aligned new/delete interceptors.

Alex Shlyapnikov via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 22 09:02:17 PST 2017


Author: alekseyshl
Date: Fri Dec 22 09:02:17 2017
New Revision: 321365

URL: http://llvm.org/viewvc/llvm-project?rev=321365&view=rev
Log:
[MSan,TSan] Add aligned new/delete interceptors.

Summary:
Providing aligned new/delete implementations to match ASan.
Unlike ASan, MSan and TSan do not perform any additional checks
on overaligned memory, hence no sanitizer specific tests.

Reviewers: eugenis

Subscribers: kubamracek, #sanitizers, llvm-commits

Differential Revision: https://reviews.llvm.org/D41532

Added:
    compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/new_delete_test.cc
Modified:
    compiler-rt/trunk/lib/msan/msan_new_delete.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_new_delete.cc

Modified: compiler-rt/trunk/lib/msan/msan_new_delete.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_new_delete.cc?rev=321365&r1=321364&r2=321365&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_new_delete.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_new_delete.cc Fri Dec 22 09:02:17 2017
@@ -22,9 +22,10 @@
 
 using namespace __msan;  // NOLINT
 
-// Fake std::nothrow_t to avoid including <new>.
+// Fake std::nothrow_t and std::align_val_t to avoid including <new>.
 namespace std {
   struct nothrow_t {};
+  enum class align_val_t: size_t {};
 }  // namespace std
 
 
@@ -34,6 +35,11 @@ namespace std {
   void *res = msan_malloc(size, &stack);\
   if (!nothrow && UNLIKELY(!res)) DieOnFailure::OnOOM();\
   return res
+#define OPERATOR_NEW_BODY_ALIGN(nothrow) \
+  GET_MALLOC_STACK_TRACE;\
+  void *res = msan_memalign((uptr)align, size, &stack);\
+  if (!nothrow && UNLIKELY(!res)) DieOnFailure::OnOOM();\
+  return res;
 
 INTERCEPTOR_ATTRIBUTE
 void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
@@ -47,6 +53,18 @@ INTERCEPTOR_ATTRIBUTE
 void *operator new[](size_t size, std::nothrow_t const&) {
   OPERATOR_NEW_BODY(true /*nothrow*/);
 }
+INTERCEPTOR_ATTRIBUTE
+void *operator new(size_t size, std::align_val_t align)
+{ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](size_t size, std::align_val_t align)
+{ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&)
+{ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&)
+{ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
 
 #define OPERATOR_DELETE_BODY \
   GET_MALLOC_STACK_TRACE; \
@@ -62,5 +80,29 @@ INTERCEPTOR_ATTRIBUTE
 void operator delete[](void *ptr, std::nothrow_t const&) {
   OPERATOR_DELETE_BODY;
 }
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, size_t size) NOEXCEPT { OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, size_t size) NOEXCEPT
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, std::align_val_t align) NOEXCEPT
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&)
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, std::align_val_t align, std::nothrow_t const&)
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, size_t size, std::align_val_t align) NOEXCEPT
+{ OPERATOR_DELETE_BODY; }
+
 
 #endif // MSAN_REPLACE_OPERATORS_NEW_AND_DELETE

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_new_delete.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_new_delete.cc?rev=321365&r1=321364&r2=321365&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_new_delete.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_new_delete.cc Fri Dec 22 09:02:17 2017
@@ -20,6 +20,7 @@ using namespace __tsan;  // NOLINT
 
 namespace std {
 struct nothrow_t {};
+enum class align_val_t: __sanitizer::uptr {};
 }  // namespace std
 
 DECLARE_REAL(void *, malloc, uptr size)
@@ -38,6 +39,18 @@ DECLARE_REAL(void, free, void *ptr)
   invoke_malloc_hook(p, size);  \
   return p;
 
+#define OPERATOR_NEW_BODY_ALIGN(mangled_name, nothrow) \
+  if (cur_thread()->in_symbolizer) \
+    return InternalAlloc(size, nullptr, (uptr)align); \
+  void *p = 0; \
+  {  \
+    SCOPED_INTERCEPTOR_RAW(mangled_name, size); \
+    p = user_memalign(thr, pc, (uptr)align, size); \
+    if (!nothrow && UNLIKELY(!p)) DieOnFailure::OnOOM(); \
+  }  \
+  invoke_malloc_hook(p, size);  \
+  return p;
+
 SANITIZER_INTERFACE_ATTRIBUTE
 void *operator new(__sanitizer::uptr size);
 void *operator new(__sanitizer::uptr size) {
@@ -62,6 +75,36 @@ void *operator new[](__sanitizer::uptr s
   OPERATOR_NEW_BODY(_ZnamRKSt9nothrow_t, true /*nothrow*/);
 }
 
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new(__sanitizer::uptr size, std::align_val_t align);
+void *operator new(__sanitizer::uptr size, std::align_val_t align) {
+  OPERATOR_NEW_BODY_ALIGN(_ZnwmSt11align_val_t, false /*nothrow*/);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new[](__sanitizer::uptr size, std::align_val_t align);
+void *operator new[](__sanitizer::uptr size, std::align_val_t align) {
+  OPERATOR_NEW_BODY_ALIGN(_ZnamSt11align_val_t, false /*nothrow*/);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new(__sanitizer::uptr size, std::align_val_t align,
+                   std::nothrow_t const&);
+void *operator new(__sanitizer::uptr size, std::align_val_t align,
+                   std::nothrow_t const&) {
+  OPERATOR_NEW_BODY_ALIGN(_ZnwmSt11align_val_tRKSt9nothrow_t,
+                          true /*nothrow*/);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new[](__sanitizer::uptr size, std::align_val_t align,
+                     std::nothrow_t const&);
+void *operator new[](__sanitizer::uptr size, std::align_val_t align,
+                     std::nothrow_t const&) {
+  OPERATOR_NEW_BODY_ALIGN(_ZnamSt11align_val_tRKSt9nothrow_t,
+                          true /*nothrow*/);
+}
+
 #define OPERATOR_DELETE_BODY(mangled_name) \
   if (ptr == 0) return;  \
   if (cur_thread()->in_symbolizer) \
@@ -93,3 +136,57 @@ void operator delete[](void *ptr, std::n
 void operator delete[](void *ptr, std::nothrow_t const&) {
   OPERATOR_DELETE_BODY(_ZdaPvRKSt9nothrow_t);
 }
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete(void *ptr, __sanitizer::uptr size) NOEXCEPT;
+void operator delete(void *ptr, __sanitizer::uptr size) NOEXCEPT {
+  OPERATOR_DELETE_BODY(_ZdlPvm);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete[](void *ptr, __sanitizer::uptr size) NOEXCEPT;
+void operator delete[](void *ptr, __sanitizer::uptr size) NOEXCEPT {
+  OPERATOR_DELETE_BODY(_ZdaPvm);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete(void *ptr, std::align_val_t align) NOEXCEPT;
+void operator delete(void *ptr, std::align_val_t align) NOEXCEPT {
+  OPERATOR_DELETE_BODY(_ZdlPvSt11align_val_t);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT;
+void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT {
+  OPERATOR_DELETE_BODY(_ZdaPvSt11align_val_t);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&);
+void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&) {
+  OPERATOR_DELETE_BODY(_ZdlPvSt11align_val_tRKSt9nothrow_t);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete[](void *ptr, std::align_val_t align,
+                       std::nothrow_t const&);
+void operator delete[](void *ptr, std::align_val_t align,
+                       std::nothrow_t const&) {
+  OPERATOR_DELETE_BODY(_ZdaPvSt11align_val_tRKSt9nothrow_t);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete(void *ptr, __sanitizer::uptr size,
+                     std::align_val_t align) NOEXCEPT;
+void operator delete(void *ptr, __sanitizer::uptr size,
+                     std::align_val_t align) NOEXCEPT {
+  OPERATOR_DELETE_BODY(_ZdlPvmSt11align_val_t);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete[](void *ptr, __sanitizer::uptr size,
+                       std::align_val_t align) NOEXCEPT;
+void operator delete[](void *ptr, __sanitizer::uptr size,
+                       std::align_val_t align) NOEXCEPT {
+  OPERATOR_DELETE_BODY(_ZdaPvmSt11align_val_t);
+}

Added: compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/new_delete_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/new_delete_test.cc?rev=321365&view=auto
==============================================================================
--- compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/new_delete_test.cc (added)
+++ compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/new_delete_test.cc Fri Dec 22 09:02:17 2017
@@ -0,0 +1,80 @@
+// RUN: %clangxx -std=c++1z -faligned-allocation -O0 %s -o %t && %run %t
+// RUN: %clangxx -std=c++1z -faligned-allocation -fsized-deallocation -O0 %s -o %t && %run %t
+
+// ubsan does not intercept new/delete.
+// UNSUPPORTED: ubsan
+
+// Check that all new/delete variants are defined and work with supported
+// sanitizers. Sanitizer-specific failure modes tests are supposed to go to
+// the particular sanitizier's test suites.
+
+#include <cstddef>
+
+// Define all new/delete to do not depend on the version provided by the
+// plaform. The implementation is provided by the sanitizer anyway.
+
+namespace std {
+struct nothrow_t {};
+static const nothrow_t nothrow;
+enum class align_val_t : size_t {};
+}  // namespace std
+
+void *operator new(size_t);
+void *operator new[](size_t);
+void *operator new(size_t, std::nothrow_t const&);
+void *operator new[](size_t, std::nothrow_t const&);
+void *operator new(size_t, std::align_val_t);
+void *operator new[](size_t, std::align_val_t);
+void *operator new(size_t, std::align_val_t, std::nothrow_t const&);
+void *operator new[](size_t, std::align_val_t, std::nothrow_t const&);
+
+void operator delete(void*) throw();
+void operator delete[](void*) throw();
+void operator delete(void*, std::nothrow_t const&);
+void operator delete[](void*, std::nothrow_t const&);
+void operator delete(void*, size_t) throw();
+void operator delete[](void*, size_t) throw();
+void operator delete(void*, std::align_val_t) throw();
+void operator delete[](void*, std::align_val_t) throw();
+void operator delete(void*, std::align_val_t, std::nothrow_t const&);
+void operator delete[](void*, std::align_val_t, std::nothrow_t const&);
+void operator delete(void*, size_t, std::align_val_t) throw();
+void operator delete[](void*, size_t, std::align_val_t) throw();
+
+
+template<typename T>
+inline T* break_optimization(T *arg) {
+  __asm__ __volatile__("" : : "r" (arg) : "memory");
+  return arg;
+}
+
+
+struct S12 { int a, b, c; };
+struct alignas(128) S12_128 { int a, b, c; };
+struct alignas(256) S12_256 { int a, b, c; };
+struct alignas(512) S1024_512 { char a[1024]; };
+struct alignas(1024) S1024_1024 { char a[1024]; };
+
+
+int main(int argc, char **argv) {
+  delete break_optimization(new S12);
+  operator delete(break_optimization(new S12), std::nothrow);
+  delete [] break_optimization(new S12[100]);
+  operator delete[](break_optimization(new S12[100]), std::nothrow);
+
+  delete break_optimization(new S12_128);
+  operator delete(break_optimization(new S12_128),
+                  std::align_val_t(alignof(S12_128)));
+  operator delete(break_optimization(new S12_128),
+                  std::align_val_t(alignof(S12_128)), std::nothrow);
+  operator delete(break_optimization(new S12_128), sizeof(S12_128),
+                  std::align_val_t(alignof(S12_128)));
+
+  delete [] break_optimization(new S12_128[100]);
+  operator delete[](break_optimization(new S12_128[100]),
+                    std::align_val_t(alignof(S12_128)));
+  operator delete[](break_optimization(new S12_128[100]),
+                    std::align_val_t(alignof(S12_128)), std::nothrow);
+  operator delete[](break_optimization(new S12_128[100]), sizeof(S12_128[100]),
+                    std::align_val_t(alignof(S12_128)));
+}




More information about the llvm-commits mailing list