On 05/07/17 21:24 +0100, Jonathan Wakely wrote:
On 05/07/17 20:44 +0100, Yuri Gribov wrote:
On Wed, Jul 5, 2017 at 8:00 PM, Jonathan Wakely <jwak...@redhat.com> wrote:
This patch adds AddressSanitizer annotations to std::vector, so that
ASan can detect out-of-bounds accesses to the unused capacity of a
vector. e.g.
std::vector<int> v(2);
int* p = v.data();
v.pop_back();
return p[1]; // ERROR
This cannot be detected by Debug Mode, but with these annotations ASan
knows that only v.data()[0] is valid and will give an error.
The annotations are only enabled for vector<T, std::allocator<T>> and
only when std::allocator's base class is either malloc_allocator or
new_allocator. For other allocators the memory might not come from the
freestore and so isn't tracked by ASan.
One important issue with enabling this by default is that it may
(will?) break separate sanitization (which is extremely important
feature in practice). If one part of application is sanitized but the
other isn't and some poor std::vector is push_back'ed in latter and
then accessed in former, we'll get a false positive because push_back
wouldn't properly annotate memory.
Good point.
Perhaps hide this under a compilation flag (disabled by default)?
If you define _GLIBCXX_SANITIZE_STD_ALLOCATOR to 0 the annotations are
disabled. To make them disabled by default would need some changes, to
use separate macros for "the std::allocator base class can be
sanitized" and "the user wants std::vector to be sanitized".
I'll do that before committing.
Here's what I've committed. std::vector<T, std::allocator<T>>
operations are not annotated unless
_GLIBCXX_SANITIZE_VECTOR is defined.
Tested powerpc64le-linux and x86_64-linux, committed to trunk.
commit 4212dcf491c1187be79c9c905d57eaf4bc17fece
Author: Jonathan Wakely <jwak...@redhat.com>
Date: Wed Jul 5 13:25:21 2017 +0100
Add AddressSanitizer annotations to std::vector
* config/allocator/malloc_allocator_base.h [__SANITIZE_ADDRESS__]
(_GLIBCXX_SANITIZE_STD_ALLOCATOR): Define.
* config/allocator/new_allocator_base.h [__SANITIZE_ADDRESS__]
(_GLIBCXX_SANITIZE_STD_ALLOCATOR): Define.
* doc/xml/manual/using.xml (_GLIBCXX_SANITIZE_VECTOR): Document macro.
* include/bits/stl_vector.h [_GLIBCXX_SANITIZE_VECTOR]
(_Vector_impl::_Asan, _Vector_impl::_Asan::_Reinit)
(_Vector_impl::_Asan::_Grow, _GLIBCXX_ASAN_ANNOTATE_REINIT)
(_GLIBCXX_ASAN_ANNOTATE_GROW, _GLIBCXX_ASAN_ANNOTATE_GREW)
(_GLIBCXX_ASAN_ANNOTATE_SHRINK, _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC):
Define annotation helper types and macros.
(vector::~vector, vector::push_back, vector::pop_back)
(vector::_M_erase_at_end): Add annotations.
* include/bits/vector.tcc (vector::reserve, vector::emplace_back)
(vector::insert, vector::_M_erase, vector::operator=)
(vector::_M_fill_assign, vector::_M_assign_aux)
(vector::_M_insert_rval, vector::_M_emplace_aux)
(vector::_M_insert_aux, vector::_M_realloc_insert)
(vector::_M_fill_insert, vector::_M_default_append)
(vector::_M_shrink_to_fit, vector::_M_range_insert): Annotate.
diff --git a/libstdc++-v3/config/allocator/malloc_allocator_base.h b/libstdc++-v3/config/allocator/malloc_allocator_base.h
index b091bbc..54e0837 100644
--- a/libstdc++-v3/config/allocator/malloc_allocator_base.h
+++ b/libstdc++-v3/config/allocator/malloc_allocator_base.h
@@ -52,4 +52,8 @@ namespace std
# define __allocator_base __gnu_cxx::malloc_allocator
#endif
+#if defined(__SANITIZE_ADDRESS__) && !defined(_GLIBCXX_SANITIZE_STD_ALLOCATOR)
+# define _GLIBCXX_SANITIZE_STD_ALLOCATOR 1
+#endif
+
#endif
diff --git a/libstdc++-v3/config/allocator/new_allocator_base.h b/libstdc++-v3/config/allocator/new_allocator_base.h
index 3d2bb67..e776ed3 100644
--- a/libstdc++-v3/config/allocator/new_allocator_base.h
+++ b/libstdc++-v3/config/allocator/new_allocator_base.h
@@ -52,4 +52,8 @@ namespace std
# define __allocator_base __gnu_cxx::new_allocator
#endif
+#if defined(__SANITIZE_ADDRESS__) && !defined(_GLIBCXX_SANITIZE_STD_ALLOCATOR)
+# define _GLIBCXX_SANITIZE_STD_ALLOCATOR 1
+#endif
+
#endif
diff --git a/libstdc++-v3/doc/xml/manual/using.xml b/libstdc++-v3/doc/xml/manual/using.xml
index 5c0e1b9..6ce29fd 100644
--- a/libstdc++-v3/doc/xml/manual/using.xml
+++ b/libstdc++-v3/doc/xml/manual/using.xml
@@ -991,6 +991,24 @@ g++ -Winvalid-pch -I. -include stdc++.h -H -g -O2 hello.cc -o test.exe
</listitem></varlistentry>
</variablelist>
+ <varlistentry><term><code>_GLIBCXX_SANITIZE_VECTOR</code></term>
+ <listitem>
+ <para>
+ Undefined by default. When defined, <classname>std::vector</classname>
+ operations will be annotated so that AddressSanitizer can detect
+ invalid accesses to the unused capacity of a
+ <classname>std::vector</classname>. These annotations are only
+ enabled for
+ <classname>std::vector<T, std::allocator<T>></classname>
+ and only when <classname>std::allocator</classname> is derived from
+ <xref linkend="allocator.impl"><classname>new_allocator</classname>
+ or <classname>malloc_allocator</classname></xref>. The annotations
+ must be present on all vector operations or none, so this macro must
+ be defined to the same value for all translation units that create,
+ destroy or modify vectors.
+ </para>
+ </listitem></varlistentry>
+
</section>
<section xml:id="manual.intro.using.abi" xreflabel="Dual ABI">
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h
index 7ee3ce9..c7787f7 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -65,6 +65,12 @@
#include <debug/assertions.h>
+#if _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR
+extern "C" void
+__sanitizer_annotate_contiguous_container(const void*, const void*,
+ const void*, const void*);
+#endif
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
@@ -106,6 +112,121 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
std::swap(_M_finish, __x._M_finish);
std::swap(_M_end_of_storage, __x._M_end_of_storage);
}
+
+#if _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR
+ template<typename = _Tp_alloc_type>
+ struct _Asan
+ {
+ typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>
+ ::size_type size_type;
+
+ static void _S_shrink(_Vector_impl&, size_type) { }
+ static void _S_on_dealloc(_Vector_impl&) { }
+
+ typedef _Vector_impl& _Reinit;
+
+ struct _Grow
+ {
+ _Grow(_Vector_impl&, size_type) { }
+ void _M_grew(size_type) { }
+ };
+ };
+
+ // Enable ASan annotations for memory obtained from std::allocator.
+ template<typename _Up>
+ struct _Asan<allocator<_Up> >
+ {
+ typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>
+ ::size_type size_type;
+
+ // Adjust ASan annotation for [_M_start, _M_end_of_storage) to
+ // mark end of valid region as __curr instead of __prev.
+ static void
+ _S_adjust(_Vector_impl& __impl, pointer __prev, pointer __curr)
+ {
+ __sanitizer_annotate_contiguous_container(__impl._M_start,
+ __impl._M_end_of_storage, __prev, __curr);
+ }
+
+ static void
+ _S_grow(_Vector_impl& __impl, size_type __n)
+ { _S_adjust(__impl, __impl._M_finish, __impl._M_finish + __n); }
+
+ static void
+ _S_shrink(_Vector_impl& __impl, size_type __n)
+ { _S_adjust(__impl, __impl._M_finish + __n, __impl._M_finish); }
+
+ static void
+ _S_on_dealloc(_Vector_impl& __impl)
+ {
+ if (__impl._M_start)
+ _S_adjust(__impl, __impl._M_finish, __impl._M_end_of_storage);
+ }
+
+ // Used on reallocation to tell ASan unused capacity is invalid.
+ struct _Reinit
+ {
+ explicit _Reinit(_Vector_impl& __impl) : _M_impl(__impl)
+ {
+ // Mark unused capacity as valid again before deallocating it.
+ _S_on_dealloc(_M_impl);
+ }
+
+ ~_Reinit()
+ {
+ // Mark unused capacity as invalid after reallocation.
+ if (_M_impl._M_start)
+ _S_adjust(_M_impl, _M_impl._M_end_of_storage,
+ _M_impl._M_finish);
+ }
+
+ _Vector_impl& _M_impl;
+
+#if __cplusplus >= 201103L
+ _Reinit(const _Reinit&) = delete;
+ _Reinit& operator=(const _Reinit&) = delete;
+#endif
+ };
+
+ // Tell ASan when unused capacity is initialized to be valid.
+ struct _Grow
+ {
+ _Grow(_Vector_impl& __impl, size_type __n)
+ : _M_impl(__impl), _M_n(__n)
+ { _S_grow(_M_impl, __n); }
+
+ ~_Grow() { if (_M_n) _S_shrink(_M_impl, _M_n); }
+
+ void _M_grew(size_type __n) { _M_n -= __n; }
+
+#if __cplusplus >= 201103L
+ _Grow(const _Grow&) = delete;
+ _Grow& operator=(const _Grow&) = delete;
+#endif
+ private:
+ _Vector_impl& _M_impl;
+ size_type _M_n;
+ };
+ };
+
+#define _GLIBCXX_ASAN_ANNOTATE_REINIT \
+ typename _Base::_Vector_impl::template _Asan<>::_Reinit const \
+ __attribute__((__unused__)) __reinit_guard(this->_M_impl)
+#define _GLIBCXX_ASAN_ANNOTATE_GROW(n) \
+ typename _Base::_Vector_impl::template _Asan<>::_Grow \
+ __attribute__((__unused__)) __grow_guard(this->_M_impl, (n))
+#define _GLIBCXX_ASAN_ANNOTATE_GREW(n) __grow_guard._M_grew(n)
+#define _GLIBCXX_ASAN_ANNOTATE_SHRINK(n) \
+ _Base::_Vector_impl::template _Asan<>::_S_shrink(this->_M_impl, n)
+#define _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC \
+ _Base::_Vector_impl::template _Asan<>::_S_on_dealloc(this->_M_impl)
+#else // ! (_GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR)
+#define _GLIBCXX_ASAN_ANNOTATE_REINIT
+#define _GLIBCXX_ASAN_ANNOTATE_GROW(n)
+#define _GLIBCXX_ASAN_ANNOTATE_GREW(n)
+#define _GLIBCXX_ASAN_ANNOTATE_SHRINK(n)
+#define _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC
+#endif // _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR
};
public:
@@ -159,8 +280,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
~_Vector_base() _GLIBCXX_NOEXCEPT
- { _M_deallocate(this->_M_impl._M_start, this->_M_impl._M_end_of_storage
- - this->_M_impl._M_start); }
+ {
+ _M_deallocate(_M_impl._M_start,
+ _M_impl._M_end_of_storage - _M_impl._M_start);
+ }
public:
_Vector_impl _M_impl;
@@ -431,8 +554,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* responsibility.
*/
~vector() _GLIBCXX_NOEXCEPT
- { std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
- _M_get_Tp_allocator()); }
+ {
+ std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
+ _M_get_Tp_allocator());
+ _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC;
+ }
/**
* @brief %Vector assignment operator.
@@ -940,9 +1066,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(1);
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
__x);
++this->_M_impl._M_finish;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(1);
}
else
_M_realloc_insert(end(), __x);
@@ -977,6 +1105,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
__glibcxx_requires_nonempty();
--this->_M_impl._M_finish;
_Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish);
+ _GLIBCXX_ASAN_ANNOTATE_SHRINK(1);
}
#if __cplusplus >= 201103L
@@ -1510,8 +1639,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
void
_M_erase_at_end(pointer __pos) _GLIBCXX_NOEXCEPT
{
- std::_Destroy(__pos, this->_M_impl._M_finish, _M_get_Tp_allocator());
- this->_M_impl._M_finish = __pos;
+ if (size_type __n = this->_M_impl._M_finish - __pos)
+ {
+ std::_Destroy(__pos, this->_M_impl._M_finish,
+ _M_get_Tp_allocator());
+ this->_M_impl._M_finish = __pos;
+ _GLIBCXX_ASAN_ANNOTATE_SHRINK(__n);
+ }
}
iterator
diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc
index da4a64c..b9dff0e 100644
--- a/libstdc++-v3/include/bits/vector.tcc
+++ b/libstdc++-v3/include/bits/vector.tcc
@@ -73,6 +73,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
pointer __tmp = _M_allocate_and_copy(__n,
_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_start),
_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_finish));
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator());
_M_deallocate(this->_M_impl._M_start,
@@ -97,9 +98,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(1);
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
std::forward<_Args>(__args)...);
++this->_M_impl._M_finish;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(1);
}
else
_M_realloc_insert(end(), std::forward<_Args>(__args)...);
@@ -122,9 +125,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
if (__position == end())
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(1);
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
__x);
++this->_M_impl._M_finish;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(1);
}
else
{
@@ -157,6 +162,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX_MOVE3(__position + 1, end(), __position);
--this->_M_impl._M_finish;
_Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish);
+ _GLIBCXX_ASAN_ANNOTATE_SHRINK(1);
return __position;
}
@@ -181,6 +187,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
if (&__x != this)
{
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
#if __cplusplus >= 201103L
if (_Alloc_traits::_S_propagate_on_copy_assign())
{
@@ -245,10 +252,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
else if (__n > size())
{
std::fill(begin(), end(), __val);
+ const size_type __add = __n - size();
+ _GLIBCXX_ASAN_ANNOTATE_GROW(__add);
this->_M_impl._M_finish =
std::__uninitialized_fill_n_a(this->_M_impl._M_finish,
- __n - size(), __val,
- _M_get_Tp_allocator());
+ __add, __val, _M_get_Tp_allocator());
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__add);
}
else
_M_erase_at_end(std::fill_n(this->_M_impl._M_start, __n, __val));
@@ -284,6 +293,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
if (__len > capacity())
{
pointer __tmp(_M_allocate_and_copy(__len, __first, __last));
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator());
_M_deallocate(this->_M_impl._M_start,
@@ -300,10 +310,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_ForwardIterator __mid = __first;
std::advance(__mid, size());
std::copy(__first, __mid, this->_M_impl._M_start);
+ const size_type __attribute__((__unused__)) __n = __len - size();
+ _GLIBCXX_ASAN_ANNOTATE_GROW(__n);
this->_M_impl._M_finish =
std::__uninitialized_copy_a(__mid, __last,
this->_M_impl._M_finish,
_M_get_Tp_allocator());
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__n);
}
}
@@ -317,9 +330,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
if (__position == cend())
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(1);
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
std::move(__v));
++this->_M_impl._M_finish;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(1);
}
else
_M_insert_aux(begin() + __n, std::move(__v));
@@ -340,9 +355,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
if (__position == cend())
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(1);
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
std::forward<_Args>(__args)...);
++this->_M_impl._M_finish;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(1);
}
else
{
@@ -370,10 +387,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_insert_aux(iterator __position, const _Tp& __x)
#endif
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(1);
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
- _GLIBCXX_MOVE(*(this->_M_impl._M_finish
- - 1)));
+ _GLIBCXX_MOVE(*(this->_M_impl._M_finish - 1)));
++this->_M_impl._M_finish;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(1);
#if __cplusplus < 201103L
_Tp __x_copy = __x;
#endif
@@ -443,11 +461,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_deallocate(__new_start, __len);
__throw_exception_again;
}
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator());
_M_deallocate(this->_M_impl._M_start,
- this->_M_impl._M_end_of_storage
- - this->_M_impl._M_start);
+ this->_M_impl._M_end_of_storage - this->_M_impl._M_start);
this->_M_impl._M_start = __new_start;
this->_M_impl._M_finish = __new_finish;
this->_M_impl._M_end_of_storage = __new_start + __len;
@@ -473,11 +491,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
pointer __old_finish(this->_M_impl._M_finish);
if (__elems_after > __n)
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(__n);
std::__uninitialized_move_a(this->_M_impl._M_finish - __n,
this->_M_impl._M_finish,
this->_M_impl._M_finish,
_M_get_Tp_allocator());
this->_M_impl._M_finish += __n;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__n);
_GLIBCXX_MOVE_BACKWARD3(__position.base(),
__old_finish - __n, __old_finish);
std::fill(__position.base(), __position.base() + __n,
@@ -485,15 +505,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
else
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(__n);
this->_M_impl._M_finish =
std::__uninitialized_fill_n_a(this->_M_impl._M_finish,
__n - __elems_after,
__x_copy,
_M_get_Tp_allocator());
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__n - __elems_after);
std::__uninitialized_move_a(__position.base(), __old_finish,
this->_M_impl._M_finish,
_M_get_Tp_allocator());
this->_M_impl._M_finish += __elems_after;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__elems_after);
std::fill(__position.base(), __old_finish, __x_copy);
}
}
@@ -536,6 +559,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_deallocate(__new_start, __len);
__throw_exception_again;
}
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator());
_M_deallocate(this->_M_impl._M_start,
@@ -559,9 +583,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
if (size_type(this->_M_impl._M_end_of_storage
- this->_M_impl._M_finish) >= __n)
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(__n);
this->_M_impl._M_finish =
std::__uninitialized_default_n_a(this->_M_impl._M_finish,
__n, _M_get_Tp_allocator());
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__n);
}
else
{
@@ -587,6 +613,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_deallocate(__new_start, __len);
__throw_exception_again;
}
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator());
_M_deallocate(this->_M_impl._M_start,
@@ -606,6 +633,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
if (capacity() == size())
return false;
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
return std::__shrink_to_fit_aux<vector>::_S_do_it(*this);
}
#endif
@@ -648,11 +676,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
pointer __old_finish(this->_M_impl._M_finish);
if (__elems_after > __n)
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(__n);
std::__uninitialized_move_a(this->_M_impl._M_finish - __n,
this->_M_impl._M_finish,
this->_M_impl._M_finish,
_M_get_Tp_allocator());
this->_M_impl._M_finish += __n;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__n);
_GLIBCXX_MOVE_BACKWARD3(__position.base(),
__old_finish - __n, __old_finish);
std::copy(__first, __last, __position);
@@ -661,15 +691,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
_ForwardIterator __mid = __first;
std::advance(__mid, __elems_after);
+ _GLIBCXX_ASAN_ANNOTATE_GROW(__n);
std::__uninitialized_copy_a(__mid, __last,
this->_M_impl._M_finish,
_M_get_Tp_allocator());
this->_M_impl._M_finish += __n - __elems_after;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__n - __elems_after);
std::__uninitialized_move_a(__position.base(),
__old_finish,
this->_M_impl._M_finish,
_M_get_Tp_allocator());
this->_M_impl._M_finish += __elems_after;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__elems_after);
std::copy(__first, __mid, __position);
}
}
@@ -701,6 +734,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_deallocate(__new_start, __len);
__throw_exception_again;
}
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator());
_M_deallocate(this->_M_impl._M_start,
@@ -909,4 +943,9 @@ _GLIBCXX_END_NAMESPACE_VERSION
#endif // C++11
+#undef _GLIBCXX_ASAN_ANNOTATE_REINIT
+#undef _GLIBCXX_ASAN_ANNOTATE_GROW
+#undef _GLIBCXX_ASAN_ANNOTATE_GREW
+#undef _GLIBCXX_ASAN_ANNOTATE_SHRINK
+
#endif /* _VECTOR_TCC */