diff mbox

Add AddressSanitizer annotations to std::vector

Message ID 20170705191748.GF15340@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely July 5, 2017, 7:17 p.m. UTC
On 05/07/17 20:00 +0100, Jonathan Wakely wrote:
>We can probably do similar annotations for std::deque, so that
>partially filled pages are annotated. I also have a patch for
>shared_ptr so that objects created by make_shared can be marked as
>invalid after they're destroyed.

This is the make_shared annotation patch. This allows ASan to give an
error for:

  auto p = std::make_shared<int>();
  std::weak_ptr<int> w = p;
  int* pi = p.get();
  p = nullptr;
  return *pi;

The error isn't ideal, because ASan thinks we're using a container,
because that's what the annotations are intended for:

==4525==ERROR: AddressSanitizer: container-overflow
diff mbox

Patch

commit d0478d9fbd17b9e9d165b4893f784ae897531713
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Jun 27 13:31:12 2017 +0100

    Add AddressSanitizer annotations to std::make_shared
    
    	* include/bits/shared_ptr_base.h [_GLIBCXX_SANITIZE_STD_ALLOCATOR]
    	(__asan_annotate): Add.
    	(_Sp_counted_ptr_inplace::_M_dispose): Call __asan_annotate.

diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h
index 7e6766b..a720018 100644
--- a/libstdc++-v3/include/bits/shared_ptr_base.h
+++ b/libstdc++-v3/include/bits/shared_ptr_base.h
@@ -57,6 +57,12 @@ 
 #include <bits/stl_function.h>
 #include <ext/aligned_buffer.h>
 
+#if _GLIBCXX_SANITIZE_STD_ALLOCATOR
+extern "C" void
+__sanitizer_annotate_contiguous_container(const void*, const void*,
+                                         const void*, const void*);
+#endif
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 #if !__cpp_rtti
@@ -522,6 +528,19 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
   };
 
+#if _GLIBCXX_SANITIZE_STD_ALLOCATOR
+  template<typename _Tp>
+    inline void
+    __asan_annotate(const void* __beg, const void* __mid, const void* __end,
+		    const allocator<_Tp>&)
+    { __sanitizer_annotate_contiguous_container(__beg, __end, __end, __mid); }
+
+  template<typename _Alloc>
+    inline void
+    __asan_annotate(const void*, const void*, const void*, const _Alloc&)
+    { }
+#endif
+
   template<typename _Tp, typename _Alloc, _Lock_policy _Lp>
     class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp>
     {
@@ -556,6 +575,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _M_dispose() noexcept
       {
 	allocator_traits<_Alloc>::destroy(_M_impl._M_alloc(), _M_ptr());
+#if _GLIBCXX_SANITIZE_STD_ALLOCATOR
+	__asan_annotate(this, &_M_impl._M_storage, this + 1, _M_impl._M_alloc());
+#endif
       }
 
       // Override because the allocator needs to know the dynamic type