[cfe-dev] annotating libc++ to catch buffer overflows in vector/string with asan

Kostya Serebryany kcc at google.com
Mon Dec 9 06:58:41 PST 2013


Marshall,
Here is a more complete patch for asan vector annotations.
It passes all tests in libcxx/test/containers/sequences/vector, but doesn't
yet work on larger programs (I tried Chrome).
Two questions:
   1. Does it look like something potentially committable?
   2. Would you suggest some bigger test suite specifically targeted to
test std::vector?

Thanks,

--kcc



On Wed, Nov 20, 2013 at 6:35 PM, Kostya Serebryany <kcc at google.com> wrote:

> Attached is an intermediate patch that passes my tests (also attached).
> Few questions:
>
> The patch gets a bit too verbose and it has a few repetitions, e.g. we
> have this snippet repeated multiple times:
> +            __annotate_contiguous_container(data(), data() + capacity(),
> +                                            data() + size(), data() +
> size() + 1);
>
> WDYT about adding a private method to vector like this (and a couple more)?
>
> void __annotate_size_increase(size_t __n) {
>     __annotate_contiguous_container(data(), data() + capacity(),
>                                             data() + size(), data() +
> size() + __n);
> }
>
> In order to test the annotation properly I need to do something like this
> as often as possible:
> template <class T> void TestVector(std::vector<T> &v) {
>
>   if (v.capacity() == 0) return;
>
>   char *beg = (char*)&v.front();
>
>   char *end = beg + v.capacity() * sizeof(T);
>
>   char *mid = beg + v.size() * sizeof(T);
>
>   for (char *p = beg; p < mid; p++)
>
>     assert(!__asan_address_is_poisoned(p));
>
>   for (char *p = mid ; p < end; p++)
>
>     assert(__asan_address_is_poisoned(p));
>
> }
>
> Is it possible to add code like this as another private method of vector
> (under some ifdef)?
>
> --kcc
>
>
> On Tue, Nov 19, 2013 at 1:57 PM, Kostya Serebryany <kcc at google.com> wrote:
>
>>
>>> > Do you like the idea?
>>>
>>> Yes - very much so.
>>>
>>> > Any comments about the prototype patch?
>>>
>>> Yes.
>>>
>>> 1) I would implement it with inline functions other than macros.
>>>
>>> Like this:
>>>
>>>
>>> extern "C" void __sanitizer_annotate_contiguous_container(void *, void
>>> *, void *, void *);
>>> void inline __annotate_contiguous container
>>>         ( const void *__beg, const void *__end, const void *__old_mid,
>>> const void *new_mid )
>>> #if __has_feature(address_sanitizer)
>>>         {  __sanitizer_annotate_contiguous_container(beg, end, old_mid,
>>> new_mid); }
>>> #else
>>>         {}
>>> #endif
>>>
>>
>> Makes sense, see below.
>> We''l probably want to move __annotate_contiguous container into a
>> separate file so that both string and vector use it.
>> But let's do the whole thing with vector before moving to string.
>>
>>
>>
>>>
>>> 2) I'd like more information about what
>>> __sanitizer_annotate_contiguous_container does ;-)
>>>
>>
>> In short, it [un]poisons the parts of shadow memory that correspond to
>> the container's memory.
>> More details in compiler-rt files:
>>  include/sanitizer/common_interface_defs.h and lib/asan/asan_poisoning.cc
>>
>>
>>
>>>
>>> > Any suggestion how to test these annotations in libc++ (we need some
>>> kind of DEATH tests)?
>>>
>>> We already have failing tests in libc++.
>>> they are named XXXX.fail.cpp.
>>>
>>
>> These are tests that fail to compile.
>> for asan annotations we need tests that build and run, and then either
>> fail at run-time or check the state of shadow.
>> Like these:
>> compiler-rt/lib/asan/lit_tests/TestCases/contiguous_container.cc
>> compiler-rt/lib/asan/lit_tests/TestCases/contiguous_container_crash.cc
>>
>> Suggestions?
>>
>> --kcc
>>
>> --- include/vector      (revision 195116)
>> +++ include/vector      (working copy)
>> @@ -288,6 +288,16 @@
>>
>>  _LIBCPP_BEGIN_NAMESPACE_STD
>>
>> +extern "C" void __sanitizer_annotate_contiguous_container(
>> +  const void *, const void *, const void *, const void *);
>> +void inline __annotate_contiguous_container
>> +    (const void *__beg, const void *__end, const void *__old_mid, const
>> void *__new_mid)
>> +#if __has_feature(address_sanitizer)
>> +    {  __sanitizer_annotate_contiguous_container(__beg, __end,
>> __old_mid, __new_mid); }
>> +#else
>> +    {}
>> +#endif
>> +
>>  template <bool>
>>  class __vector_base_common
>>  {
>> @@ -1525,7 +1535,12 @@
>>      // __v.push_back(_VSTD::forward<_Up>(__x));
>>      __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__v.__end_),
>> _VSTD::forward<_Up>(__x));
>>      __v.__end_++;
>> +    if (data())
>> +      __annotate_contiguous_container(
>>  +          data(), data() + capacity(), data() + size(), data() +
>> capacity());
>>      __swap_out_circular_buffer(__v);
>> +    __annotate_contiguous_container(data(), data() + capacity(),
>> +                                          data() + capacity(), data() +
>> size());
>>  }
>>
>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20131209/d2573283/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: vector_asan.patch
Type: text/x-patch
Size: 8512 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20131209/d2573283/attachment.bin>


More information about the cfe-dev mailing list