[PATCH] asan unit tests from llvm lit-test incremental changes

Konstantin Serebryany konstantin.s.serebryany@gmail.com
Thu Dec 13 10:23:00 GMT 2012


I've added two flags, both on by default for now.

  // Use fast (frame-pointer-based) unwinder on fatal errors (if available).
  bool fast_unwind_on_fatal;
  // Use fast (frame-pointer-based) unwinder on malloc/free (if available).
  bool fast_unwind_on_malloc;


% clang -fsanitize=address -g
~/llvm/projects/compiler-rt/lib/asan/lit_tests/overflow-in-qsort.cc
% ASAN_OPTIONS=fast_unwind_on_fatal=0 ./a.out 2>&1 | asan_symbolize.py
 / | grep '#'
    #0 0x419731 in QsortCallback overflow-in-qsort.cc:18
    #1 0x7fa7e137b61f in msort_with_tmp msort.c:143
    #2 0x7fa7e137baba in msort_with_tmp msort.c:46
    #3 0x419a58 in MyQsort overflow-in-qsort.cc:25
    #4 0x419c94 in main overflow-in-qsort.cc:33
    #5 0x7fa7e136276c in __libc_start_main libc-start.c:226
    #6 0x4193ac in _start ??:0
% ASAN_OPTIONS=fast_unwind_on_fatal=1 ./a.out 2>&1 | asan_symbolize.py
 / | grep '#'
    #0 0x419731 in QsortCallback overflow-in-qsort.cc:18
    #1 0x7f816783f61f in msort_with_tmp msort.c:143
%

This feature still needs some love.
I'll set fast_unwind_on_fatal to 0 after some testing and then merge
to gcc (unless there is a rush).


On Thu, Dec 13, 2012 at 12:36 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Thu, Dec 13, 2012 at 11:44:12AM +0400, Konstantin Serebryany wrote:
>> We are discussing it from time to time.
>> Sometimes, if e.g. an error happens inside a qsort callback,
>> the fp-based unwinder fails to unwind through libc, while _Unwind would work.
>>
>> I was opposed to this sometime ago because _Unwind often produced
>> buggy stack traces on Ubuntu Lucid (the version we cared about).
>
> Weird, must be some distro modifications, we've been using _Unwind based
> backtraces everywhere for many years successfully, glibc backtrace uses it
> too, pthread_cancel as well.
>
>> >>  and perhaps for
>> >> > these malloc wrappers like ::operator new, ::operator new[] and their
>> >> > const std::nothrow_t& variants libasan could intercept them, call
>> >> > malloc and if that returns NULL, call the original corresponding function
>> >> > so that it deals with exceptions, new handler etc.
>>
>> Hmm.. Why's that?
>> Calling libc's malloc or libstdc++'s operator new in asan run-time is
>> really a bad idea.
>
> I didn't mean calling libc malloc, I meant calling libstdc++'s operator new,
> which then calls malloc (== any, thus asan version), but does some
> additional bookkeeping for failures.

Got it.
Probably, a bad idea as well -- what if the standard C++ library is
not libstdc++, but something else?
Also, when compiling .c programs we don't link libstdc++ at all, so
there will be some linking issues.

If we want to support new handler and allow asan's malloc to return 0,
it is much easier and cleaner to implement it from scratch.
However, no one complained so far (after 1.5 years) so I'd prefer to
do this lazily (i.e. only after first motivated complaint).
And it'll be nowhere near the top of my TODO list :(

>
> The thing is that libstdc++'s operator new:
> _GLIBCXX_WEAK_DEFINITION void *
> operator new (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc)
> {
>   void *p;
>
>   /* malloc (0) is unpredictable; avoid it.  */
>   if (sz == 0)
>     sz = 1;
>   p = (void *) malloc (sz);
>   while (p == 0)
>     {
>       new_handler handler = __new_handler;
>       if (! handler)
>         _GLIBCXX_THROW_OR_ABORT(bad_alloc());
>       handler ();
>       p = (void *) malloc (sz);
>     }
>
>   return p;
> }
>
> _GLIBCXX_WEAK_DEFINITION void*
> operator new[] (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc)
> {
>   return ::operator new(sz);
> }
> etc. aren't built with frame pointers, therefore ebp/rbp may be used for
> anything, therefore non-unwind based backtrace will stop on that or get
> confused.  What I meant was have
> void *
> operator new (std::size_t sz) throw (std::bad_alloc)
> {
>   void *p = malloc (sz);
>   if (__builtin_expect (p == NULL, 0))
>     call_original_operator_new (sz);
>   return p;
> }
> and similarly for operator new[] etc. in libasan, forcefully built with
> -fno-omit-frame-pointer, so that in the likely case that malloc doesn't
> return NULL the non-_Unwind based backtrace in malloc would unwind well
> through operator new as well as operator new[].  Or if libasan malloc really
> never returns NULL and you don't plan to ever change that (why?), you could
> just make operator new/operator new[] etc. in libasan aliases to malloc.

I am planing to implement malloc/delete, new/free and new/delete[]
mismatch detection,
so using aliases is not a choice.


--kcc

>
>> asan's allocator should never return 0 anyway, it should simply crash.
>> I don't think we want to support new handler at all.
>
> Does it?  Then it will abort perfectly valid programs.
>
>         Jakub



More information about the Gcc-patches mailing list