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. Perhaps hide this under a compilation flag (disabled by default)? > Something similar has been on the google branches for some time: > https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=207517 > This patch is a complete rewrite from scratch, because the google code > was not exception safe. If an exception happened while appending > elements to a vector, so that the size didn't change, the google code > did not undo the annotation for the increased size. It also didn't > annotate before deallocating, to mark the unused capacity as valid > again. > > 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. > > * 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. > * include/bits/stl_vector.h [_GLIBCXX_SANITIZE_STD_ALLOCATOR] > (_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. > > Tested x86_64-linux (using -fsanitize=address, with some local patches > to the testsuite) and powerpc64le-linux. > > I plan to commit this to trunk tomorrow.