Add Address Sanitizer support to std::vector
llvm-svn: 208319
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: 5c520bd985ee51472d2396fe28a3ef8b30eb5a6c
diff --git a/include/__config b/include/__config
index fb775c6..ce39243 100644
--- a/include/__config
+++ b/include/__config
@@ -629,6 +629,11 @@
#define _LIBCPP_DEPRECATED_AFTER_CXX11 [[deprecated]]
#endif
+#ifndef _LIBCPP_HAS_NO_ASAN
+extern "C" void __sanitizer_annotate_contiguous_container(
+ const void *, const void *, const void *, const void *);
+#endif
+
// Try to find out if RTTI is disabled.
// g++ and cl.exe have RTTI on by default and define a macro when it is.
// g++ only defines the macro in 4.3.2 and onwards.
diff --git a/include/vector b/include/vector
index 6ac78d5..2cc23e5 100644
--- a/include/vector
+++ b/include/vector
@@ -483,6 +483,7 @@
{
private:
typedef __vector_base<_Tp, _Allocator> __base;
+ typedef allocator<_Tp> __default_allocator_type;
public:
typedef vector __self;
typedef _Tp value_type;
@@ -749,7 +750,9 @@
_LIBCPP_INLINE_VISIBILITY
void clear() _NOEXCEPT
{
+ size_type __old_size = size();
__base::clear();
+ __annotate_shrink(__old_size);
__invalidate_all_iterators();
}
@@ -816,7 +819,9 @@
}
__get_db()->unlock();
#endif
+ size_type __old_size = size();
__base::__destruct_at_end(__new_last);
+ __annotate_shrink(__old_size);
}
template <class _Up>
void
@@ -830,17 +835,52 @@
void
__emplace_back_slow_path(_Args&&... __args);
#endif
+ // The following functions are no-ops outside of AddressSanitizer mode.
+ // We call annotatations only for the default Allocator because other allocators
+ // may not meet the AddressSanitizer alignment constraints.
+ // See the documentation for __sanitizer_annotate_contiguous_container for more details.
+ void __annotate_contiguous_container
+ (const void *__beg, const void *__end, const void *__old_mid, const void *__new_mid)
+ {
+#ifndef _LIBCPP_HAS_NO_ASAN
+ if (__beg && is_same<allocator_type, __default_allocator_type>::value)
+ __sanitizer_annotate_contiguous_container(__beg, __end, __old_mid, __new_mid);
+#endif
+ }
+
+ void __annotate_new(size_type __current_size)
+ {
+ __annotate_contiguous_container(data(), data() + capacity(),
+ data() + capacity(), data() + __current_size);
+ }
+ void __annotate_delete()
+ {
+ __annotate_contiguous_container(data(), data() + capacity(),
+ data() + size(), data() + capacity());
+ }
+ void __annotate_increase(size_type __n)
+ {
+ __annotate_contiguous_container(data(), data() + capacity(),
+ data() + size(), data() + size() + __n);
+ }
+ void __annotate_shrink(size_type __old_size)
+ {
+ __annotate_contiguous_container(data(), data() + capacity(),
+ data() + __old_size, data() + size());
+ }
};
template <class _Tp, class _Allocator>
void
vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v)
{
+ __annotate_delete();
__alloc_traits::__construct_backward(this->__alloc(), this->__begin_, this->__end_, __v.__begin_);
_VSTD::swap(this->__begin_, __v.__begin_);
_VSTD::swap(this->__end_, __v.__end_);
_VSTD::swap(this->__end_cap(), __v.__end_cap());
__v.__first_ = __v.__begin_;
+ __annotate_new(size());
__invalidate_all_iterators();
}
@@ -848,6 +888,7 @@
typename vector<_Tp, _Allocator>::pointer
vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v, pointer __p)
{
+ __annotate_delete();
pointer __r = __v.__begin_;
__alloc_traits::__construct_backward(this->__alloc(), this->__begin_, __p, __v.__begin_);
__alloc_traits::__construct_forward(this->__alloc(), __p, this->__end_, __v.__end_);
@@ -855,6 +896,7 @@
_VSTD::swap(this->__end_, __v.__end_);
_VSTD::swap(this->__end_cap(), __v.__end_cap());
__v.__first_ = __v.__begin_;
+ __annotate_new(size());
__invalidate_all_iterators();
return __r;
}
@@ -874,6 +916,7 @@
this->__throw_length_error();
this->__begin_ = this->__end_ = __alloc_traits::allocate(this->__alloc(), __n);
this->__end_cap() = this->__begin_ + __n;
+ __annotate_new(0);
}
template <class _Tp, class _Allocator>
@@ -920,6 +963,7 @@
vector<_Tp, _Allocator>::__construct_at_end(size_type __n)
{
allocator_type& __a = this->__alloc();
+ __annotate_increase(__n);
do
{
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_));
@@ -940,6 +984,7 @@
vector<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x)
{
allocator_type& __a = this->__alloc();
+ __annotate_increase(__n);
do
{
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_), __x);
@@ -960,6 +1005,7 @@
allocator_type& __a = this->__alloc();
for (; __first != __last; ++__first)
{
+ __annotate_increase(1);
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_), *__first);
++this->__end_;
}
@@ -972,6 +1018,7 @@
allocator_type& __a = this->__alloc();
for (; __first != __last; ++__first)
{
+ __annotate_increase(1);
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_),
_VSTD::move(*__first));
++this->__end_;
@@ -1535,6 +1582,7 @@
{
if (this->__end_ != this->__end_cap())
{
+ __annotate_increase(1);
__alloc_traits::construct(this->__alloc(),
_VSTD::__to_raw_pointer(this->__end_), __x);
++this->__end_;
@@ -1552,6 +1600,7 @@
{
if (this->__end_ < this->__end_cap())
{
+ __annotate_increase(1);
__alloc_traits::construct(this->__alloc(),
_VSTD::__to_raw_pointer(this->__end_),
_VSTD::move(__x));
@@ -1584,6 +1633,7 @@
{
if (this->__end_ < this->__end_cap())
{
+ __annotate_increase(1);
__alloc_traits::construct(this->__alloc(),
_VSTD::__to_raw_pointer(this->__end_),
_VSTD::forward<_Args>(__args)...);
@@ -1666,6 +1716,7 @@
pointer __p = this->__begin_ + (__position - begin());
if (this->__end_ < this->__end_cap())
{
+ __annotate_increase(1);
if (__p == this->__end_)
{
__alloc_traits::construct(this->__alloc(),
@@ -1705,6 +1756,7 @@
pointer __p = this->__begin_ + (__position - begin());
if (this->__end_ < this->__end_cap())
{
+ __annotate_increase(1);
if (__p == this->__end_)
{
__alloc_traits::construct(this->__alloc(),
@@ -1743,6 +1795,7 @@
pointer __p = this->__begin_ + (__position - begin());
if (this->__end_ < this->__end_cap())
{
+ __annotate_increase(1);
if (__p == this->__end_)
{
__alloc_traits::construct(this->__alloc(),
@@ -1794,6 +1847,7 @@
}
if (__n > 0)
{
+ __annotate_increase(__n);
__move_range(__p, __old_last, __p + __old_n);
const_pointer __xr = pointer_traits<const_pointer>::pointer_to(__x);
if (__p <= __xr && __xr < this->__end_)
@@ -1904,6 +1958,7 @@
}
if (__n > 0)
{
+ __annotate_increase(__n);
__move_range(__p, __old_last, __p + __old_n);
_VSTD::copy(__first, __m, __p);
}