An explanation of some "Container overflow" ASAN reports

From: Mark Millard <marklmi_at_yahoo.com>
Date: Fri, 14 Jan 2022 12:44:36 UTC
Looks like libc++ does the following sort of thing
(from lldb list):

. . .
   1635	
   1636	template <class _Tp, class _Allocator>
   1637	template <class _Up>
   1638	void
   1639	#ifndef _LIBCPP_CXX03_LANG
(lldb) 
   1640	vector<_Tp, _Allocator>::__push_back_slow_path(_Up&& __x)
   1641	#else
   1642	vector<_Tp, _Allocator>::__push_back_slow_path(_Up& __x)
   1643	#endif
   1644	{
   1645	    allocator_type& __a = this->__alloc();
   1646	    __split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), size(), __a);
   1647	    // __v.push_back(_VSTD::forward<_Up>(__x));
   1648	    __alloc_traits::construct(__a, _VSTD::__to_address(__v.__end_), _VSTD::forward<_Up>(__x));
   1649	    __v.__end_++;
(lldb) 
   1650	    __swap_out_circular_buffer(__v);
   1651	}
. . . (the bt points to 1650) . . .

1648 constructs into __v at __v.__end_ and 1649 then corrects
__v.__end_ to cause the constructed object to no longer be
an example of "Container overflow" but now in the Container.
(At least that is my interpretation.)

The compiler's code generation may move the detailed
place where __v.__end_++ happens relative to some other
of the activity but the compiler has been told an order
relative to the construction that would lead to writing
memory in the capacity of the container __v but outside
the size of the __v container at the time.

For reference:

   970 	template <class _Tp, class _Allocator>
   971 	void
   972 	vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v)
   973 	{
   974 	
   975 	    __annotate_delete();
   976 	    _VSTD::__construct_backward_with_exception_guarantees(this->__alloc(), this->__begin_, this->__end_, __v.__begin_);
   977 	    _VSTD::swap(this->__begin_, __v.__begin_);
   978 	    _VSTD::swap(this->__end_, __v.__end_);
   979 	    _VSTD::swap(this->__end_cap(), __v.__end_cap());
(lldb) 
   980 	    __v.__first_ = __v.__begin_;
   981 	    __annotate_new(size());
   982 	    __invalidate_all_iterators();
   983 	}
. . . (the bt for this points to 976) . . .


This suggests to me that using some equivalent of:

env ASAN_OPTIONS=detect_container_overflow=0

my be required fairly generally when libc++ can
be involved.


Other notes . . .

I used ld -v as an example for the above via:

env ASAN_OPTIONS=detect_container_overflow=0 lldb ld

and used:

(lldb) env ASAN_OPTIONS=
(lldb) run -v

in order to have ld itself not have detect_container_overflow
disabled.

lldb suffers the libc++ Container overflow problems via its
libc++ use and fails to operate without the:

ASAN_OPTIONS=detect_container_overflow=0

===
Mark Millard
marklmi at yahoo.com