Patchwork asan unit tests from llvm lit-test incremental changes

login
register
mail settings
Submitter Jakub Jelinek
Date Dec. 5, 2012, 12:29 p.m.
Message ID <20121205122906.GO2315@tucnak.redhat.com>
Download mbox | patch
Permalink /patch/203858/
State New
Headers show

Comments

Jakub Jelinek - Dec. 5, 2012, 12:29 p.m.
Hi!

On Tue, Dec 04, 2012 at 10:00:35AM -0800, Wei Mi wrote:
> I updated the patch according to the comments. Please take a look. Thanks.

Rather than several further rounds of review, let me post an incremental
patch on top of yours.  Your patch seems to be incomplete BTW, that
asan-special.exp and tests needing it weren't added.  Let's resolve what
you've posted first and look at the rest as a follow-up.

With this patch as well as the two patches I've posted today,
http://gcc.gnu.org/ml/gcc-patches/2012-12/msg00301.html
http://gcc.gnu.org/ml/gcc-patches/2012-12/msg00302.html
on top of your patch there are no testsuite failures on x86_64-linux during
make check-gcc check-g++ RUNTESTFLAGS='--target_board=unix\{-m32,-m64\} asan.exp'
beyond the preexisting asan_test.C failures.

The patch combines tiny cleanups (whitespace, * sizeof(char), etc.),
avoiding relying on argc being 1 (not the case for some bare metal targets
if we ever support them), some dg-options tweaks (e.g. global-overflow-1.c
clearly assumes non-optimizing compiler, with memset (YYY, 0, sizeof (YYY));
int res = YYY[ten]; the FRE pass happily optimizes the read into 0,
because all entries of the array were set to 0, even when ten is volatile,
because for every valid value of that it must return 0).
Beyond that, some comments:
1) I've disabled deep-stack-uaf-1.C for -flto, because with lto the
symbolized function names aren't actually printed as the C++ mangled
names, but as plain free (all of them).
2) In large-func-test-1.C, I had to stop matching the backtrace after
_Znw[jm], because libasan is using the fast but inaccurate backtrace,
and while the tests can be easily tweaked to compile with
-fno-omit-frame-pointer, we definitely can't rely on libstdc++.so to be
built with that option.  Most likely it isn't.  I repeat that I think
that at least for Linux libasan should use the _Unwind* based backtrace
at least for the fatal functions (__asan_report* etc.), 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.
3) deep-thread-stack-1.C fails for me right now with some libasan assertion,
Kostya, can you please look at that?
  AsanThread *t = asanThreadRegistry().GetCurrent();
  CHECK(t);
where it failed on the CHECK, because t was NULL.  I've skipped the test for
now.
4) some regexps needed tweaking to accomodate older versions of addr2line,
those that understand DWARF4 somewhat but not fully (and is sometimes being confused
by DW_AT_high_pc GCC 4.8 emits, with that we can end up with e.g.
in function cc1ebajk.o:0
instead of
in function /usr/src/...filename.c:18) and with even older addr2line which
gives up on DWARF4 and thus prints just
in function ??:0
etc.
I've tested this with current binutils addr2line, Fedora 17 addr2line
(doesn't handle DW_AT_high_pc yet), and RHEL5 addr2line (doesn't handle
DWARF4 at all).

Ok for trunk?

2012-12-05  Jakub Jelinek  <jakub@redhat.com>

	* g++.dg/asan/deep-tail-call-1.C: Whitespace fixes.  Don't rely
	on argc being one.
	* g++.dg/asan/interception-malloc-test-1.C: Only run on linux.
	Whitespace fixes.  Avoid unnecessary * sizeof(char).
	* g++.dg/asan/deep-thread-stack-1.C: Add -lpthread to dg-options,
	skip for now.  Whitespace fixes.
	* g++.dg/asan/deep-stack-uaf-1.C: Skip for -flto.  Whitespace fixes.
	* g++.dg/asan/interception-test-1.C: Whitespace fixes.
	* g++.dg/asan/interception-failure-test-1.C: Whitespace fixes.
	Avoid unnecessary * sizeof(char).  Remove // CHECK: comment.
	* g++.dg/asan/default-options-1.C: Whitespace fixes.
	* g++.dg/asan/symbolize-callback-1.C: Whitespace fixes.  Make
	first __asan_symbolize argument unnamed.  Avoid unnecessary
	* sizeof(char).
	* g++.dg/asan/large-func-test-1.C: Whitespace fixes.  Don't rely
	on argc being one.  Allow both _Znwj and _Znwm as operator new.
	Ignore everything in the backtrace above operator new.  Fix up
	dg-output regexps.
	* c-c++-common/asan/null-deref-1.c: Add -fno-omit-frame-pointer
	and for x86 -mno-omit-leaf-frame-pointer.  Fix up dg-output regexps.
	* c-c++-common/asan/clone-test-1.c: Whitespace fixes.  Return non-zero
	on failures.  Avoid pointless PASS dg-output check.
	* c-c++-common/asan/sanity-check-pure-c-1.c: Fix up dg-output regexps.
	Avoid unnecessary * sizeof(char).
	* c-c++-common/asan/heap-overflow-1.c: Fix up dg-output regexps.
	Don't rely on argc being one.
	* c-c++-common/asan/sleep-before-dying-1.c: Whitespace fixes.
	Avoid unnecessary * sizeof(char).
	* c-c++-common/asan/rlimit-mmap-test-1.c: Whitespace fixes.
	* c-c++-common/asan/stack-overflow-1.c: Fix up dg-output regexps.
	* c-c++-common/asan/global-overflow-1.c: Add -fno-builtin-memset.
	Fix up dg-output regexps.
	* c-c++-common/asan/strncpy-overflow-1.c: Fix up dg-output regexps.
	* c-c++-common/asan/memcmp-1.c:	Don't rely on argc being one.
	* c-c++-common/asan/use-after-free-1.c: Fix up dg-output regexps.
	* c-c++-common/asan/swapcontext-test-1.c: Don't rely on argc being
	one.
	* c-c++-common/asan/force-inline-opt0-1.c: Remove dg-skip-if.
	* c-c++-common/asan/strip-path-prefix-1.c: Whitespace fixes.
	Avoid unnecessary * sizeof(char).



	Jakub
Dodji Seketeli - Dec. 12, 2012, 9:16 p.m.
Hello,

Independently of this review, I think it's be interesting to hear
Kostya's voice on:

Jakub Jelinek <jakub@redhat.com> writes:

> 2) In large-func-test-1.C, I had to stop matching the backtrace after
> _Znw[jm], because libasan is using the fast but inaccurate backtrace,
> and while the tests can be easily tweaked to compile with
> -fno-omit-frame-pointer, we definitely can't rely on libstdc++.so to be
> built with that option.  Most likely it isn't.  I repeat that I think
> that at least for Linux libasan should use the _Unwind* based backtrace
> at least for the fatal functions (__asan_report* etc.), 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.

and on:

> 3) deep-thread-stack-1.C fails for me right now with some libasan assertion,
> Kostya, can you please look at that?
>   AsanThread *t = asanThreadRegistry().GetCurrent();
>   CHECK(t);
> where it failed on the CHECK, because t was NULL.  I've skipped the test for
> now.

[...]

> --- gcc/testsuite/g++.dg/asan/deep-tail-call-1.C.jj	2012-12-04 20:24:10.000000000 +0100
> +++ gcc/testsuite/g++.dg/asan/deep-tail-call-1.C	2012-12-05 11:01:48.600443834 +0100
> @@ -1,21 +1,22 @@
> -// { dg-do run } 
> +// { dg-do run }
>  // { dg-options "-fno-omit-frame-pointer -fno-optimize-sibling-calls" }
>  // { dg-additional-options "-mno-omit-leaf-frame-pointer" { target { i?86-*-* x86_64-*-* } } }
> -// { dg-shouldfail "asan" } 
> +// { dg-shouldfail "asan" }
>  
>  int global[10];
>  void __attribute__((noinline)) call4(int i) { global[i+10]++; }
>  void __attribute__((noinline)) call3(int i) { call4(i); }
>  void __attribute__((noinline)) call2(int i) { call3(i); }
>  void __attribute__((noinline)) call1(int i) { call2(i); }
> -int main(int argc, char **argv) {
> -  call1(argc);
> +volatile int one = 1;

Just curious, why do we need this variable to be volatile, especially
since the test is compiled without optimization?

> +int main() {
> +  call1(one);
>    return global[0];
>  }

[...]

The patch looks OK to me in any case.

Thanks.
Jakub Jelinek - Dec. 12, 2012, 9:30 p.m.
On Wed, Dec 12, 2012 at 10:16:49PM +0100, Dodji Seketeli wrote:
> Independently of this review, I think it's be interesting to hear
> Kostya's voice on:
> 
> Jakub Jelinek <jakub@redhat.com> writes:
> 
> > 2) In large-func-test-1.C, I had to stop matching the backtrace after
> > _Znw[jm], because libasan is using the fast but inaccurate backtrace,
> > and while the tests can be easily tweaked to compile with
> > -fno-omit-frame-pointer, we definitely can't rely on libstdc++.so to be
> > built with that option.  Most likely it isn't.  I repeat that I think
> > that at least for Linux libasan should use the _Unwind* based backtrace
> > at least for the fatal functions (__asan_report* etc.), 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.

Yeah, I'd appreciate that too.

> and on:
> 
> > 3) deep-thread-stack-1.C fails for me right now with some libasan assertion,
> > Kostya, can you please look at that?
> >   AsanThread *t = asanThreadRegistry().GetCurrent();
> >   CHECK(t);
> > where it failed on the CHECK, because t was NULL.  I've skipped the test for
> > now.
> 
> [...]

This one is for the testcase solved right now already by the -lasan -lpthread 
linking instead of just -lpthread (and driver adding -lasan afterwards).
We'll need to think about how to tweak the driver to add -lasan early on the
command line, before user passed -l* options.
> 
> > --- gcc/testsuite/g++.dg/asan/deep-tail-call-1.C.jj	2012-12-04 20:24:10.000000000 +0100
> > +++ gcc/testsuite/g++.dg/asan/deep-tail-call-1.C	2012-12-05 11:01:48.600443834 +0100
> > @@ -1,21 +1,22 @@
> > -// { dg-do run } 
> > +// { dg-do run }
> >  // { dg-options "-fno-omit-frame-pointer -fno-optimize-sibling-calls" }
> >  // { dg-additional-options "-mno-omit-leaf-frame-pointer" { target { i?86-*-* x86_64-*-* } } }
> > -// { dg-shouldfail "asan" } 
> > +// { dg-shouldfail "asan" }
> >  
> >  int global[10];
> >  void __attribute__((noinline)) call4(int i) { global[i+10]++; }
> >  void __attribute__((noinline)) call3(int i) { call4(i); }
> >  void __attribute__((noinline)) call2(int i) { call3(i); }
> >  void __attribute__((noinline)) call1(int i) { call2(i); }
> > -int main(int argc, char **argv) {
> > -  call1(argc);
> > +volatile int one = 1;
> 
> Just curious, why do we need this variable to be volatile, especially
> since the test is compiled without optimization?

asan.exp tests are torture tests, they iterate over several -O* options,
unless explicitly dg-skip-if skipped.  It could be non-volatile with
asm volatile ("" : : : "memory");
or asm volatile ("" : "+m" (one)); or similar too, sure.
I just don't want to rely on argc being one, and the compiler shouldn't know
that one is 1 in the test.

> [...]
> 
> The patch looks OK to me in any case.

Thanks.

	Jakub
Konstantin Serebryany - Dec. 13, 2012, 7:44 a.m.
On Thu, Dec 13, 2012 at 1:30 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Wed, Dec 12, 2012 at 10:16:49PM +0100, Dodji Seketeli wrote:
>> Independently of this review, I think it's be interesting to hear
>> Kostya's voice on:
>>
>> Jakub Jelinek <jakub@redhat.com> writes:
>>
>> > 2) In large-func-test-1.C, I had to stop matching the backtrace after
>> > _Znw[jm], because libasan is using the fast but inaccurate backtrace,
>> > and while the tests can be easily tweaked to compile with
>> > -fno-omit-frame-pointer, we definitely can't rely on libstdc++.so to be
>> > built with that option.  Most likely it isn't.

The tests should be built with -fno-omit-frame-pointer and we don't
need that for libstdc++.so.
This is how it works in LLVM.
asan's interceptors are written in such a way that they don't care
if libstdc++.so or the asan run-time have frame pointers.

>>> I repeat that I think
>> > that at least for Linux libasan should use the _Unwind* based backtrace
>> > at least for the fatal functions (__asan_report* etc.),

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).
I also vaguely remember some problems with _Unwind* depending on
malloc (or maybe that's something else?)
Now we mostly care about Ubuntu Precise and we need to test whether
_Unwind produces good enough results there before switching.

unwinding on malloc/free should keep using the fp-based unwinder, at
least by default.

We'll be tracking the issue in
https://code.google.com/p/address-sanitizer/issues/detail?id=137

>>  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.
asan's allocator should never return 0 anyway, it should simply crash.
I don't think we want to support new handler at all.

>
> Yeah, I'd appreciate that too.





>
>> and on:
>>
>> > 3) deep-thread-stack-1.C fails for me right now with some libasan assertion,
>> > Kostya, can you please look at that?
>> >   AsanThread *t = asanThreadRegistry().GetCurrent();
>> >   CHECK(t);
>> > where it failed on the CHECK, because t was NULL.  I've skipped the test for
>> > now.
>>
>> [...]
>
> This one is for the testcase solved right now already by the -lasan -lpthread
> linking instead of just -lpthread (and driver adding -lasan afterwards).
> We'll need to think about how to tweak the driver to add -lasan early on the
> command line, before user passed -l* options.
>>
>> > --- gcc/testsuite/g++.dg/asan/deep-tail-call-1.C.jj 2012-12-04 20:24:10.000000000 +0100
>> > +++ gcc/testsuite/g++.dg/asan/deep-tail-call-1.C    2012-12-05 11:01:48.600443834 +0100
>> > @@ -1,21 +1,22 @@
>> > -// { dg-do run }
>> > +// { dg-do run }
>> >  // { dg-options "-fno-omit-frame-pointer -fno-optimize-sibling-calls" }
>> >  // { dg-additional-options "-mno-omit-leaf-frame-pointer" { target { i?86-*-* x86_64-*-* } } }
>> > -// { dg-shouldfail "asan" }
>> > +// { dg-shouldfail "asan" }
>> >
>> >  int global[10];
>> >  void __attribute__((noinline)) call4(int i) { global[i+10]++; }
>> >  void __attribute__((noinline)) call3(int i) { call4(i); }
>> >  void __attribute__((noinline)) call2(int i) { call3(i); }
>> >  void __attribute__((noinline)) call1(int i) { call2(i); }
>> > -int main(int argc, char **argv) {
>> > -  call1(argc);
>> > +volatile int one = 1;
>>
>> Just curious, why do we need this variable to be volatile, especially
>> since the test is compiled without optimization?
>
> asan.exp tests are torture tests, they iterate over several -O* options,
> unless explicitly dg-skip-if skipped.  It could be non-volatile with
> asm volatile ("" : : : "memory");
> or asm volatile ("" : "+m" (one)); or similar too, sure.
> I just don't want to rely on argc being one, and the compiler shouldn't know
> that one is 1 in the test.
>
>> [...]
>>
>> The patch looks OK to me in any case.
>
> Thanks.
>
>         Jakub


--kcc
Jakub Jelinek - Dec. 13, 2012, 8:36 a.m.
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.

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.

> 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
Konstantin Serebryany - Dec. 13, 2012, 10:22 a.m.
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
Jakub Jelinek - Dec. 13, 2012, 3:22 p.m.
On Thu, Dec 13, 2012 at 02:22:52PM +0400, Konstantin Serebryany wrote:
> 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).

I'll wait for your commit, then will test it on Fedora.  msort.c and qsort.c
are definitely built with -fasynchronous-unwind-tables -fexceptions though,
at least by default.

> 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.

libstdc++ doesn't have __new_handler exported I think, and there is no way
to query it outside of libstdc++ itself though.  One can only set it.

	Jakub

Patch

--- gcc/testsuite/g++.dg/asan/deep-tail-call-1.C.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/g++.dg/asan/deep-tail-call-1.C	2012-12-05 11:01:48.600443834 +0100
@@ -1,21 +1,22 @@ 
-// { dg-do run } 
+// { dg-do run }
 // { dg-options "-fno-omit-frame-pointer -fno-optimize-sibling-calls" }
 // { dg-additional-options "-mno-omit-leaf-frame-pointer" { target { i?86-*-* x86_64-*-* } } }
-// { dg-shouldfail "asan" } 
+// { dg-shouldfail "asan" }
 
 int global[10];
 void __attribute__((noinline)) call4(int i) { global[i+10]++; }
 void __attribute__((noinline)) call3(int i) { call4(i); }
 void __attribute__((noinline)) call2(int i) { call3(i); }
 void __attribute__((noinline)) call1(int i) { call2(i); }
-int main(int argc, char **argv) {
-  call1(argc);
+volatile int one = 1;
+int main() {
+  call1(one);
   return global[0];
 }
 
-// { dg-output "AddressSanitizer:? global-buffer-overflow.*(\n|\r\n|\r)" } 
-// { dg-output "    #0 0x\[0-9a-f\]+ (in \[^\n\r]*call4\[^\n\r]*|\[(\])\[^\n\r]*(\n|\r\n|\r)" } 
-// { dg-output "    #1 0x\[0-9a-f\]+ (in \[^\n\r]*call3\[^\n\r]*|\[(\])\[^\n\r]*(\n|\r\n|\r)" } 
-// { dg-output "    #2 0x\[0-9a-f\]+ (in \[^\n\r]*call2\[^\n\r]*|\[(\])\[^\n\r]*(\n|\r\n|\r)" } 
-// { dg-output "    #3 0x\[0-9a-f\]+ (in \[^\n\r]*call1\[^\n\r]*|\[(\])\[^\n\r]*(\n|\r\n|\r)" } 
-// { dg-output "    #4 0x\[0-9a-f\]+ (in \[^\n\r]*main\[^\n\r]*|\[(\])\[^\n\r]*(\n|\r\n|\r)" } 
+// { dg-output "AddressSanitizer:? global-buffer-overflow.*(\n|\r\n|\r)" }
+// { dg-output "    #0 0x\[0-9a-f\]+ (in \[^\n\r]*call4\[^\n\r]*|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
+// { dg-output "    #1 0x\[0-9a-f\]+ (in \[^\n\r]*call3\[^\n\r]*|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
+// { dg-output "    #2 0x\[0-9a-f\]+ (in \[^\n\r]*call2\[^\n\r]*|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
+// { dg-output "    #3 0x\[0-9a-f\]+ (in \[^\n\r]*call1\[^\n\r]*|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
+// { dg-output "    #4 0x\[0-9a-f\]+ (in \[^\n\r]*main\[^\n\r]*|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
--- gcc/testsuite/g++.dg/asan/interception-malloc-test-1.C.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/g++.dg/asan/interception-malloc-test-1.C	2012-12-05 11:02:14.130293308 +0100
@@ -1,8 +1,8 @@ 
 // ASan interceptor can be accessed with __interceptor_ prefix.
 
-// { dg-do run }
+// { dg-do run { target *-*-linux* } }
 // { dg-options "-fno-builtin-free" }
-// { dg-shouldfail "asan" } 
+// { dg-shouldfail "asan" }
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -15,10 +15,10 @@  extern "C" void *malloc(size_t size) {
 }
 
 int main() {
-  char *x = (char*)malloc(10 * sizeof(char));
+  char *x = (char*)malloc(10);
   free(x);
   return (int)strtol(x, 0, 10);
 }
 
-// { dg-output "malloc call.*(\n|\r\n|\r)" } 
-// { dg-output "\[^\n\r]*heap-use-after-free" } 
+// { dg-output "malloc call.*(\n|\r\n|\r)" }
+// { dg-output "\[^\n\r]*heap-use-after-free" }
--- gcc/testsuite/g++.dg/asan/deep-thread-stack-1.C.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/g++.dg/asan/deep-thread-stack-1.C	2012-12-05 11:45:31.009423658 +0100
@@ -1,4 +1,6 @@ 
 // { dg-do run { target pthread } }
+// { dg-skip-if "" { *-*-* } { "*" } { "" } }
+// { dg-options "-lpthread" }
 // { dg-shouldfail "asan" }
 
 #include <pthread.h>
@@ -49,7 +51,7 @@  int main(int argc, char *argv[]) {
 // { dg-output "previously allocated by thread T(\[0-9\]+) here:.*(\n|\r\n|\r)" }
 // { dg-output "Thread T\\2 created by T(\[0-9\]+) here:.*(\n|\r\n|\r)" }
 // { dg-output "Thread T\\8 created by T0 here:.*(\n|\r\n|\r)" }
-// { dg-output "Thread T\\4 created by T(\[0-9\]+) here:.*(\n|\r\n|\r)" } 
+// { dg-output "Thread T\\4 created by T(\[0-9\]+) here:.*(\n|\r\n|\r)" }
 // { dg-output "Thread T\\11 created by T0 here:.*(\n|\r\n|\r)" }
 // { dg-output "Thread T\\6 created by T(\[0-9\]+) here:.*(\n|\r\n|\r)" }
 // { dg-output "Thread T\\14 created by T0 here:" }
--- gcc/testsuite/g++.dg/asan/deep-stack-uaf-1.C.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/g++.dg/asan/deep-stack-uaf-1.C	2012-12-05 11:01:42.990476536 +0100
@@ -1,10 +1,11 @@ 
 // Check that we can store lots of stack frames if asked to.
 
-// { dg-do run } 
+// { dg-do run }
+// { dg-skip-if "" { *-*-* } { "-flto" } { "" } }
 // { dg-set-target-env-var ASAN_OPTIONS "malloc_context_size=120:redzone=512" }
 // { dg-options "-fno-omit-frame-pointer -fno-optimize-sibling-calls" }
 // { dg-additional-options "-mno-omit-leaf-frame-pointer" { target { i?86-*-* x86_64-*-* } } }
-// { dg-shouldfail "asan" } 
+// { dg-shouldfail "asan" }
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -32,7 +33,7 @@  int main() {
   return x[5];
 }
 
-// { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on address.*(\n|\r\n|\r)" } 
-// { dg-output "    #37 0x\[0-9a-f\]+ (in \[^\n\r]*DeepFree\[^\n\r]*36|\[(\]).*(\n|\r\n|\r)" } 
-// { dg-output "    #99 0x\[0-9a-f\]+ (in \[^\n\r]*DeepFree\[^\n\r]*98|\[(\]).*(\n|\r\n|\r)" } 
-// { dg-output "    #116 0x\[0-9a-f\]+ (in \[^\n\r]*DeepFree\[^\n\r]*115|\[(\])\[^\n\r]*(\n|\r\n|\r)" } 
+// { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on address.*(\n|\r\n|\r)" }
+// { dg-output "    #37 0x\[0-9a-f\]+ (in \[^\n\r]*DeepFree\[^\n\r]*36|\[(\]).*(\n|\r\n|\r)" }
+// { dg-output "    #99 0x\[0-9a-f\]+ (in \[^\n\r]*DeepFree\[^\n\r]*98|\[(\]).*(\n|\r\n|\r)" }
+// { dg-output "    #116 0x\[0-9a-f\]+ (in \[^\n\r]*DeepFree\[^\n\r]*115|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
--- gcc/testsuite/g++.dg/asan/interception-test-1.C.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/g++.dg/asan/interception-test-1.C	2012-12-05 11:02:18.224268716 +0100
@@ -2,7 +2,7 @@ 
 
 // { dg-do run }
 // { dg-options "-fno-builtin-malloc -fno-builtin-free" }
-// { dg-shouldfail "asan" } 
+// { dg-shouldfail "asan" }
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -19,5 +19,5 @@  int main() {
   return (int)strtol(x, 0, 10);
 }
 
-// { dg-output "my_strtol_interceptor.*(\n|\r\n|\r)" } 
-// { dg-output "\[^\n\r]*heap-use-after-free" } 
+// { dg-output "my_strtol_interceptor.*(\n|\r\n|\r)" }
+// { dg-output "\[^\n\r]*heap-use-after-free" }
--- gcc/testsuite/g++.dg/asan/interception-failure-test-1.C.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/g++.dg/asan/interception-failure-test-1.C	2012-12-05 11:02:09.739307322 +0100
@@ -1,7 +1,7 @@ 
 // If user provides his own libc functions, ASan doesn't
 // intercept these functions.
 
-// { dg-do run } 
+// { dg-do run }
 // { dg-options "-fno-builtin-malloc -fno-builtin-free" }
 
 #include <stdlib.h>
@@ -13,10 +13,9 @@  extern "C" long strtol(const char *nptr,
 }
 
 int main() {
-  char *x = (char*)malloc(10 * sizeof(char));
+  char *x = (char*)malloc(10);
   free(x);
   return (int)strtol(x, 0, 10);
-  // CHECK: my_strtol_interceptor
 }
 
-// { dg-output "my_strtol_interceptor" } 
+// { dg-output "my_strtol_interceptor" }
--- gcc/testsuite/g++.dg/asan/default-options-1.C.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/g++.dg/asan/default-options-1.C	2012-12-05 11:02:00.510373678 +0100
@@ -1,4 +1,4 @@ 
-// { dg-do run } 
+// { dg-do run }
 
 const char *kAsanDefaultOptions="verbosity=1 foo=bar";
 
@@ -12,4 +12,4 @@  int main() {
   return 0;
 }
 
-// { dg-output "Using the defaults from __asan_default_options:.* foo=bar.*(\n|\r\n|\r)" } 
+// { dg-output "Using the defaults from __asan_default_options:.* foo=bar.*(\n|\r\n|\r)" }
--- gcc/testsuite/g++.dg/asan/symbolize-callback-1.C.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/g++.dg/asan/symbolize-callback-1.C	2012-12-05 11:02:30.314196137 +0100
@@ -1,21 +1,21 @@ 
-// { dg-do run } 
-// { dg-skip-if "" { *-*-* }  { "*" } { "-O2" } } 
+// { dg-do run }
+// { dg-skip-if "" { *-*-* }  { "*" } { "-O2" } }
 // { dg-options "-fno-builtin-malloc -fno-builtin-free" }
-// { dg-shouldfail "asan" } 
+// { dg-shouldfail "asan" }
 
 #include <stdio.h>
 #include <stdlib.h>
 
 extern "C"
-bool __asan_symbolize(const void *pc, char *out_buffer, int out_size) {
+bool __asan_symbolize(const void *, char *out_buffer, int out_size) {
   snprintf(out_buffer, out_size, "MySymbolizer");
   return true;
 }
 
 int main() {
-  char *x = (char*)malloc(10 * sizeof(char));
+  char *x = (char*)malloc(10);
   free(x);
   return x[5];
 }
 
-// { dg-output "MySymbolizer" } 
+// { dg-output "MySymbolizer" }
--- gcc/testsuite/g++.dg/asan/large-func-test-1.C.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/g++.dg/asan/large-func-test-1.C	2012-12-05 12:25:34.064156196 +0100
@@ -1,5 +1,5 @@ 
-// { dg-do run } 
-// { dg-shouldfail "asan" } 
+// { dg-do run }
+// { dg-shouldfail "asan" }
 
 #include <stdlib.h>
 __attribute__((noinline))
@@ -28,20 +28,18 @@  static void LargeFunction(int *x, int ze
   x[18]++;
   x[19]++;
 }
-
-int main(int argc, char **argv) {
+volatile int one = 1;
+int main() {
   int *x = new int[100];
-  LargeFunction(x, argc - 1);
+  LargeFunction(x, one - 1);
   delete x;
 }
 
-// { dg-output "ERROR: AddressSanitizer:? heap-buffer-overflow on address\[^\n\r]*" } 
-// { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } 
-// { dg-output "READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } 
-// { dg-output "    #0 0x\[0-9a-f\]+ (in \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[?\]\[?\]:0)|\[(\]).*(\n|\r\n|\r)" } 
-// { dg-output "0x\[0-9a-f\]+ is located 44 bytes to the right of 400-byte region.*(\n|\r\n|\r)" } 
-// { dg-output "allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } 
-// { dg-output "    #0 0x\[0-9a-f\]+ (in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } 
-// { dg-output "    #1 0x\[0-9a-f\]+ (in (operator new|_Znwm)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } 
-// { dg-output "    #2 0x\[0-9a-f\]+ (in (operator new|_Znam)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } 
-// { dg-output "    #3 0x\[0-9a-f\]+ (in _*main\[^\n\r]*(large-func-test-1.C:33|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } 
+// { dg-output "ERROR: AddressSanitizer:? heap-buffer-overflow on address\[^\n\r]*" }
+// { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" }
+// { dg-output "READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" }
+// { dg-output "    #0 0x\[0-9a-f\]+ (in \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" }
+// { dg-output "0x\[0-9a-f\]+ is located 44 bytes to the right of 400-byte region.*(\n|\r\n|\r)" }
+// { dg-output "allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" }
+// { dg-output "    #0 0x\[0-9a-f\]+ (in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
+// { dg-output "    #1 0x\[0-9a-f\]+ (in (operator new|_*_Znw\[mj\])|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
--- gcc/testsuite/c-c++-common/asan/null-deref-1.c.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/c-c++-common/asan/null-deref-1.c	2012-12-05 12:24:26.522557195 +0100
@@ -1,16 +1,23 @@ 
 /* { dg-do run } */
+/* { dg-options "-fno-omit-frame-pointer" } */
+/* { dg-additional-options "-mno-omit-leaf-frame-pointer" { target { i?86-*-* x86_64-*-* } } } */
 /* { dg-shouldfail "asan" } */
 
 __attribute__((noinline, noclone))
-static void NullDeref(int *ptr) {
+static void
+NullDeref(int *ptr)
+{
   ptr[10]++;
 }
-int main() {
+
+int main()
+{
   NullDeref((int*)0);
+  return 0;
 }
 
-/* { dg-output "ERROR: AddressSanitizer:? SEGV on unknown address.*" } */
-/* { dg-output "0x\[0-9a-f\]+ .*pc 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "ERROR: AddressSanitizer:? SEGV on unknown address\[^\n\r]*" } */
+/* { dg-output "0x\[0-9a-f\]+ \[^\n\r]*pc 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "AddressSanitizer can not provide additional info.*(\n|\r\n|\r)" } */
-/* { dg-output "    #0 0x\[0-9a-f\]+ (in \[^\n\r]*NullDeref\[^\n\r]*(null-deref-1.c:6|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "    #1 0x\[0-9a-f\]+ (in \[^\n\r]*main\[^\n\r]*(null-deref-1.c:9|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "    #0 0x\[0-9a-f\]+ (in \[^\n\r]*NullDeref\[^\n\r]* (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "    #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*null-deref-1.c:15|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
--- gcc/testsuite/c-c++-common/asan/clone-test-1.c.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/c-c++-common/asan/clone-test-1.c	2012-12-05 11:04:12.109599800 +0100
@@ -1,4 +1,4 @@ 
-/* Regression test for: 
+/* Regression test for:
    http://code.google.com/p/address-sanitizer/issues/detail?id=37 */
 
 /* { dg-do run { target { *-*-linux* } } } */
@@ -20,6 +20,8 @@  int Child(void *arg) {
   _exit(1);  /* NoReturn, stack will remain unpoisoned unless we do something. */
 }
 
+volatile int zero = 0;
+
 int main(int argc, char **argv) {
   int i;
   const int kStackSize = 1 << 20;
@@ -31,17 +33,14 @@  int main(int argc, char **argv) {
   pid_t wait_result = waitpid(clone_pid, &status, __WCLONE);
   if (wait_result < 0) {
     perror("waitpid");
-    return 0;
+    return 1;
   }
   if (wait_result == clone_pid && WIFEXITED(status)) {
     /* Make sure the child stack was indeed unpoisoned. */
     for (i = 0; i < kStackSize; i++)
       child_stack[i] = i;
-    int ret = child_stack[argc - 1];
-    printf("PASSED\n");
+    int ret = child_stack[zero];
     return ret;
   }
-  return 0;
+  return 1;
 }
-
-/* { dg-output "PASSED" } */
--- gcc/testsuite/c-c++-common/asan/sanity-check-pure-c-1.c.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/c-c++-common/asan/sanity-check-pure-c-1.c	2012-12-05 12:22:44.517154170 +0100
@@ -4,14 +4,13 @@ 
 
 #include <stdlib.h>
 int main() {
-  char *x = (char*)malloc(10 * sizeof(char));
+  char *x = (char*)malloc(10);
   free(x);
   return x[5];
 }
 
 /* { dg-output "heap-use-after-free.*(\n|\r\n|\r)" } */
-/* { dg-output "    #0 \[^\n\r]*free\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "    #1 \[^\n\r]*(in main\[^\n\r]*(sanity-check-pure-c-1.c:8|\[?\]\[?\]:0)|\[(\]).*(\n|\r\n|\r)" } */
-/* { dg-output "    #0 \[^\n\r]*(interceptor_|)malloc\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "    #1 \[^\n\r]*(in main\[^\n\r]*(sanity-check-pure-c-1.c:7|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
-
+/* { dg-output "    #0 \[^\n\r]*(in _*(interceptor_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "    #1 \[^\n\r]*(in _*main (\[^\n\r]*sanity-check-pure-c-1.c:8|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "    #0 \[^\n\r]*(in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "    #1 \[^\n\r]*(in _*main (\[^\n\r]*sanity-check-pure-c-1.c:7|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
--- gcc/testsuite/c-c++-common/asan/heap-overflow-1.c.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/c-c++-common/asan/heap-overflow-1.c	2012-12-05 12:22:39.632181308 +0100
@@ -4,18 +4,18 @@ 
 
 #include <stdlib.h>
 #include <string.h>
+volatile int ten = 10;
 int main(int argc, char **argv) {
-  char *x = (char*)malloc(10 * sizeof(char));
+  char *x = (char*)malloc(10);
   memset(x, 0, 10);
-  int res = x[argc * 10];  /* BOOOM */
+  int res = x[ten];  /* BOOOM */
   free(x);
   return res;
 }
 
 /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
-/* { dg-output "    #0 0x\[0-9a-f\]+ (in _*main .*(heap-overflow-1.c:10|\[?\]\[?\]:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "    #0 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*heap-overflow-1.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
 /* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "    #0 0x\[0-9a-f\]+ (in .*malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "    #1 0x\[0-9a-f\]+ (in _*main .*(heap-overflow-1.c:8|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
-
+/* { dg-output "    #0 0x\[0-9a-f\]+ (in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "    #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*heap-overflow-1.c:9|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
--- gcc/testsuite/c-c++-common/asan/sleep-before-dying-1.c.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/c-c++-common/asan/sleep-before-dying-1.c	2012-12-04 20:41:31.127621371 +0100
@@ -1,12 +1,12 @@ 
 /* { dg-do run } */
 /* { dg-set-target-env-var ASAN_OPTIONS "sleep_before_dying=1" } */
-/* { dg-skip-if "" { *-*-* }  { "*" } { "-O2" } } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
 /* { dg-options "-fno-builtin-malloc -fno-builtin-free" } */
 /* { dg-shouldfail "asan" } */
 
 #include <stdlib.h>
 int main() {
-  char *x = (char*)malloc(10 * sizeof(char));
+  char *x = (char*)malloc(10);
   free(x);
   return x[5];
 }
--- gcc/testsuite/c-c++-common/asan/rlimit-mmap-test-1.c.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/c-c++-common/asan/rlimit-mmap-test-1.c	2012-12-04 20:41:14.637703428 +0100
@@ -1,7 +1,7 @@ 
 /* Check that we properly report mmap failure. */
 
 /* { dg-do run { target setrlimit } } */
-/* { dg-skip-if "" { *-*-* }  { "*" } { "-O0" } } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
 /* { dg-shouldfail "asan" } */
 
 #include <stdlib.h>
--- gcc/testsuite/c-c++-common/asan/stack-overflow-1.c.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/c-c++-common/asan/stack-overflow-1.c	2012-12-05 12:22:46.368145570 +0100
@@ -14,5 +14,5 @@  int main() {
 }
 
 /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "    #0 0x\[0-9a-f\]+ (in _*main \[^\n\r]*(stack-overflow-1.c:12|\[?\]\[?\]:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "    #0 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*stack-overflow-1.c:12|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
 /* { dg-output "Address 0x\[0-9a-f\]+ is\[^\n\r]*frame <main>" } */
--- gcc/testsuite/c-c++-common/asan/global-overflow-1.c.jj	2012-12-05 09:02:25.000000000 +0100
+++ gcc/testsuite/c-c++-common/asan/global-overflow-1.c	2012-12-05 12:22:35.517210015 +0100
@@ -1,4 +1,5 @@ 
 /* { dg-do run } */
+/* { dg-options "-fno-builtin-memset" } */
 /* { dg-shouldfail "asan" } */
 
 #include <string.h>
@@ -17,6 +18,6 @@  int main() {
 }
 
 /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
-/* { dg-output "    #0 0x\[0-9a-f\]+ (in _*main .*global-overflow.cc:14|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of global variable.*(\n|\r\n|\r)" } */
-/* { dg-output ".*YYY.* of size 10.*(\n|\r\n|\r)" } */
+/* { dg-output "    #0 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*global-overflow-1.c:15|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r).*" } */
+/* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of global variable" } */
+/* { dg-output ".*YYY\[^\n\r]* of size 10\[^\n\r]*(\n|\r\n|\r)" } */
--- gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c	2012-12-05 12:23:11.423993530 +0100
@@ -14,10 +14,8 @@  int main(int argc, char **argv) {
 
 /* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "    #0 0x\[0-9a-f\]+ (in _*(interceptor_|)strncpy|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "    #1 0x\[0-9a-f\]+ (in _*main \[^\n\r]*(strncpy-overflow-1.c:11|\[?]\[?]:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "    #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*strncpy-overflow-1.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
 /* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "    #0 0x\[0-9a-f\]+ (in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "    #1 0x\[0-9a-f\]+ (in _*main \[^\n\r]*(strncpy-overflow-1.c:10|\[?]\[?]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
-
-
+/* { dg-output "    #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*strncpy-overflow-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
--- gcc/testsuite/c-c++-common/asan/memcmp-1.c.jj	2012-11-23 16:06:31.000000000 +0100
+++ gcc/testsuite/c-c++-common/asan/memcmp-1.c	2012-12-04 20:52:09.840918270 +0100
@@ -4,12 +4,14 @@ 
 
 #include <string.h>
 
+volatile int one = 1;
+
 int
-main (int argc, char **argv)
+main ()
 {
-  char a1[] = {argc, 2, 3, 4};
-  char a2[] = {1, 2*argc, 3, 4};
-  int res = memcmp (a1, a2, 5 + argc);
+  char a1[] = {one, 2, 3, 4};
+  char a2[] = {1, 2*one, 3, 4};
+  int res = memcmp (a1, a2, 5 + one);
   return res;
 }
 
--- gcc/testsuite/c-c++-common/asan/use-after-free-1.c.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/c-c++-common/asan/use-after-free-1.c	2012-12-05 12:23:31.213889677 +0100
@@ -12,11 +12,11 @@  int main() {
 /* { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on address\[^\n\r]*" } */
 /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "    #0 0x\[0-9a-f\]+ (in _*main \[^\n\r]*(use-after-free-1.c:9|\[?]\[?]:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "    #0 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*use-after-free-1.c:9|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
 /* { dg-output "0x\[0-9a-f\]+ is located 5 bytes inside of 10-byte region .0x\[0-9a-f\]+,0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "freed by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "    #0 0x\[0-9a-f\]+ (in \[^\n\r]*free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "    #1 0x\[0-9a-f\]+ (in \[^\n\r]*main \[^\n\r]*(use-after-free-1.c:8|\[?]\[?]:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "    #0 0x\[0-9a-f\]+ (in _*(interceptor_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "    #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*use-after-free-1.c:8|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
 /* { dg-output "previously allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "    #0 0x\[0-9a-f\]+ (in \[^\n\r]*malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "    #1 0x\[0-9a-f\]+ (in \[^\n\r]*main \[^\n\r]*(use-after-free-1.c:7|\[?]\[?]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "    #0 0x\[0-9a-f\]+ (in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "    #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*use-after-free-1.c:7|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
--- gcc/testsuite/c-c++-common/asan/swapcontext-test-1.c.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/c-c++-common/asan/swapcontext-test-1.c	2012-12-04 20:52:58.324638245 +0100
@@ -47,11 +47,13 @@  int Run(int arg, int mode) {
   return child_stack[arg];
 }
 
+volatile int zero = 0;
+
 int main(int argc, char **argv) {
   int ret = 0;
-  ret += Run(argc - 1, 0);
+  ret += Run(zero, 0);
   printf("Test1 passed\n");
-  ret += Run(argc - 1, 1);
+  ret += Run(zero, 1);
   printf("Test2 passed\n");
   return ret;
 }
--- gcc/testsuite/c-c++-common/asan/force-inline-opt0-1.c.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/c-c++-common/asan/force-inline-opt0-1.c	2012-12-04 20:40:31.310940931 +0100
@@ -2,7 +2,6 @@ 
    (before and after inlining) */
 
 /* { dg-do compile } */
-/* { dg-skip-if "" { *-*-* }  { "*" } { "-O0" "-O1" } } */
 /* { dg-final { scan-assembler-not "__asan_report_load" } } */
 
 __attribute__((always_inline))
--- gcc/testsuite/c-c++-common/asan/strip-path-prefix-1.c.jj	2012-12-04 20:24:10.000000000 +0100
+++ gcc/testsuite/c-c++-common/asan/strip-path-prefix-1.c	2012-12-05 11:04:00.219677616 +0100
@@ -1,12 +1,12 @@ 
 /* { dg-do run } */
-/* { dg-skip-if "" { *-*-* }  { "*" } { "-O2" } } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
 /* { dg-set-target-env-var ASAN_OPTIONS "strip_path_prefix='/'" } */
-/* { dg-options "-fno-builtin-malloc -fno-builtin-free" } */ 
+/* { dg-options "-fno-builtin-malloc -fno-builtin-free" } */
 /* { dg-shouldfail "asan" } */
 
 #include <stdlib.h>
 int main() {
-  char *x = (char*)malloc(10 * sizeof(char));
+  char *x = (char*)malloc(10);
   free(x);
   return x[5];
 }