From patchwork Fri Nov 30 20:35:35 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Wei Mi X-Patchwork-Id: 203041 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 2D5AA2C0093 for ; Sat, 1 Dec 2012 07:36:06 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1354912568; h=Comment: DomainKey-Signature:Received:Received:Received:Received: MIME-Version:Received:Received:In-Reply-To:References:Date: Message-ID:Subject:From:To:Cc:Content-Type:Mailing-List: Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:Sender:Delivered-To; bh=pl6UObV+uok5GNZXaYHAHo56Vz0=; b=YytyekupbWnirfS5Va8cTk6Ph1rmUH28aaUNKOTz+mx2n4gok8SO1wEqb11WWH iTv6p3MTgsJlk+20g//K9HndUm7jsopkuReW6/A8RMjYZOr5fVvrRmiC7G7J8SWL 9fCbqIWPMkIn/mZNf0ZcHiaaOHPdRJW7q6DSTzMgWIFIU= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:X-Google-DKIM-Signature:MIME-Version:Received:Received:In-Reply-To:References:Date:Message-ID:Subject:From:To:Cc:Content-Type:X-Gm-Message-State:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=cxURu2ks7y3e35emK16Zbb7Mnfb0sl79g9nPqdG3lYRjtLf1OomkBIyrkUrccC x+/JYS46XLIThd2IW+N5iL7lYCHZrz8ykkwMGfY323pGi3Q8BpeU+L6hRWJ+g1z9 yibxwCQ0FSlTyj/LtHfGo4TSWIsSKNtGzL0zs9PROvAZ0=; Received: (qmail 31782 invoked by alias); 30 Nov 2012 20:35:57 -0000 Received: (qmail 31074 invoked by uid 22791); 30 Nov 2012 20:35:51 -0000 X-SWARE-Spam-Status: No, hits=-6.1 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, KHOP_RCVD_TRUST, KHOP_THREADED, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE, RP_MATCHES_RCVD, TW_CP, TW_LV X-Spam-Check-By: sourceware.org Received: from mail-qa0-f47.google.com (HELO mail-qa0-f47.google.com) (209.85.216.47) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 30 Nov 2012 20:35:38 +0000 Received: by mail-qa0-f47.google.com with SMTP id a19so1759555qad.20 for ; Fri, 30 Nov 2012 12:35:35 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:x-gm-message-state; bh=6NImthoiB+ND+US5uydPiRoQqNvQZTdJgN0B0Mnf6Qk=; b=W/w9le6qD85cOKppdZfM+xq54qi6zvJhvSnMYy61yOmL+Q4XAMJ9wKZzzfYXMPijwe kb3WBcN18qrGcuB6+/EYnRj41wgoawRWjV6/zEMVJRUUfngdgWP1DwqWJcIC1EIZV6yR PYOO0Qmiw4at435nw2bc8jvbtGOtJ1zemtWyjdhrmFePls37R4YTZjsQIW1DMqMkee7l KYZ9ERAnoHF15rRZQWlL1CO8Ys0W+uQ2S/kGxApkIbT11S770Cqv9L5BNWjn6e0uNhYz xV/Q0hZymxzniFjuH1ppjSzdL7E7ZmRh6n4f1jrBRqt9AZC0cx6vCP4L4cpgYyg7BdsP cB/Q== MIME-Version: 1.0 Received: by 10.229.78.17 with SMTP id i17mr921575qck.2.1354307735317; Fri, 30 Nov 2012 12:35:35 -0800 (PST) Received: by 10.49.74.7 with HTTP; Fri, 30 Nov 2012 12:35:35 -0800 (PST) In-Reply-To: <20121128101420.GG2315@tucnak.redhat.com> References: <20121128101420.GG2315@tucnak.redhat.com> Date: Fri, 30 Nov 2012 12:35:35 -0800 Message-ID: Subject: Re: [PATCH] asan unit tests from llvm lit-test From: Wei Mi To: Jakub Jelinek Cc: GCC Patches , David Li , Diego Novillo , Kostya Serebryany , Dodji Seketeli X-Gm-Message-State: ALoCoQms+VsfSsx3wxkrNeZFGOqK/nyeerV5YklcJxaXGMVdNCuEiTsgQpGGPYmk4gfkAJa+GnbgC8HXe7mBX/PBouBZG+UKKdxCfNbUaRS5TRLfG6YFvw9wPUIV/2JDzQTVpJqwV56C6/tfXYnZpUKToeNntbdTIT5RlC1+cEYAgMstBysPMSKuJULtwKtawT7pWsTvRmQ3 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Thanks for the comments! Here is the second version patch. Please see if it is ok. (-Wno-attributes is kept or else we will get a warning because of __attribute__((always_inline))). These tests are excluded for now because unsupported features or needs some twists to be included. blacklist-1.c (use -asan-blacklist=) initialization-blacklist-1.C   (use -asan-blacklist=) initialization-bug-1.c           (use -asan-initialization-order) initialization-nobug-1.C      (use -asan-initialization-order) initialization-bug-any-order.cc (use -asan-initialization-order) interface-symbols-1.c         (needs to be added to libsanitizer/Makefile.am) log-path_test.cc (needs to twist dg-final commands, skip for now) Test results: gcc summary # of expected passes 248 # of unexpected failures 39 # of unsupported tests 27 g++ summary # of expected passes 468 # of unexpected failures 56 # of unsupported tests 50 Thanks, Wei. On Wed, Nov 28, 2012 at 2:14 AM, Jakub Jelinek wrote: > Hi! > > On Wed, Nov 28, 2012 at 01:15:20AM -0800, Wei Mi wrote: >> I try to migrate the left asan lit-tests from llvm (class3). This is a >> preliminary version patch. Please forgive it has many mistakes. > > Thanks for working on it. > >> A known problems: I hardcoded -m32 in (set link_flags >> "[asan_link_flags [get_multilibs -m32]] $link_flags") in >> gcc/testsuite/lib/asan-dg.exp to make 32 bit library path included in >> ld_library_path. I don't know the elegant way to fix it. > > That is wrong, no *.exp file should do anything with -m32/-m64. > If user wants to test both -m32 and -m64, it should be done through > RUNTESTFLAGS='--target_board=unix\{-m32,-m64\}' > on the command line of make check if desired (or any other options deemed > necessary to test). Not all targets support both -m32 and -m64 (e.g. even > i686-linux doesn't), some targets have other ABI options (e.g. -m31/-m64 on > s390x, mips has more variants, etc.). It must be user's choice what he > wants to test for what multilibs. > >> * g++.dg/asan/linux: New, migrate from llvm asan lit-test. >> * g++.dg/asan/linux/interception-test-1.C: Likewise. >> * g++.dg/asan/linux/interception-failure-test-1.C: Likewise. >> * g++.dg/asan/linux/interception-malloc-test-1.C: Likewise. > > Why the linux/ subdirectories (which you seem to run for all targets > anyway)? That doesn't make any sense. All tests that won't run on certain > targets because of some required features (whether it is e.g. dlopen, mmap, > pthreads) should be guarded, e.g. > // { dg-require-effective-target pthread } > or > /* { dg-run { target pthread } } */ > and similar. If some check_effective_target_* tcl test is missing, it can > be always added (e.g. dlopen doesn't have any, and you can't assume dlopen > works everywhere). > >> * g++.dg/asan/Helpers: Likewise. >> * g++.dg/asan/Helpers/initialization-blacklist-1.tmp: Likewise. >> * g++.dg/asan/Helpers/initialization-blacklist-extra-1.C: Likewise. > > We aren't a CamelCase shop, I'd strongly prefer if we could avoid that > ugliness. Ditto for SharedLibs/ etc. subdirs. And why you need the subdirs > at all? The usual way how to handle e.g. the dg-additional-sources is just > make sure the additional sources are either named in a way that doesn't > match the normal wildcard (for C++ e.g. *.cc instead of *.C) or add some dg > directive in there that it won't run, or be dg-do compile only test etc. > >> + if { [string match "*blacklist-1.c" $source] } { >> + set blacklist_options $options >> + set blist_tmp [glob $srcdir/c-c++-common/asan/Helpers/blacklist-1.tmp] >> + lappend blacklist_options "additional_flags=-asan-blacklist=$blist_tmp" >> + set result [eval [list saved_asan_target_compile $source $dest $type $blacklist_options]] >> + return $result >> + } elseif { [string match "*interface-symbols-1.c" $source] } { >> + set result [eval [list saved_asan_target_compile \ >> + $source "interface-symbols-1.exe" \ >> + "executable" $options]] >> + if { [string match "" $result] } { >> + set exefile [glob interface-symbols-1.exe] >> + set asan_interface_h [glob $srcdir/../../libsanitizer/include/sanitizer/asan_interface.h] >> + set script [glob $srcdir/c-c++-common/asan/Helpers/interface_symbols.sh] >> + set diff_result [exec sh $script $exefile $asan_interface_h] >> + if { ![string match "" $diff_result] } { >> + fail "$source -- diff result not empty: $diff_result" >> + } >> + } >> + } elseif { [string match "*initialization-bug-any-order-1.c" $source] } { >> + set auxfile [glob $srcdir/c-c++-common/asan/Helpers/initialization-bug-extra-1.c] >> + global subtest >> + if { [string match "subtest1" $subtest] } { >> + set source "$source $auxfile" >> + } else { >> + set source "$auxfile $source" >> + } >> + set result [eval [list saved_asan_target_compile $source $dest $type $options]] >> + } else { >> + set result [eval [list saved_asan_target_compile $source $dest $type $options]] >> + } > > This is too ugly. asan.exp shouldn't turn into yet another vect.exp, the > ideal is that for adding new tests you don't need to tweak any *.exp and add > exceptions for that, unless there is no other way. So, preferrably in asan/ > dir should stay tests that can be just handled the standard way, and there > can be some extra subdirectory that will handle hard to handle tests. > Say g++.dg/asan/special/ could have its own asan-special.exp or similar. > Note that e.g. for building shared libraries you really need to guard it > with appropriate target checks. > >> +foreach srcfile [lsort [glob -nocomplain \ >> + $srcdir/$subdir/*.c \ >> + $srcdir/c-c++-common/asan/*.c \ >> + $srcdir/c-c++-common/asan/linux/*.c]] { >> + set asan_torture_options $default_asan_torture_options >> + if { [string match "*force-inline-opt0-1.c" $srcfile] } { >> + set asan_torture_options [list { -O0 -m64 } { -O1 -m64 }] > > As said earlier, no -m64/-m32 here, and if at all possible, no special > casing of tests in *.exp. If you want to change the set of options > at which some test is run, i.e. you don't want to iterate over all the > options, just use dg-skip-if. See > http://gcc.gnu.org/onlinedocs/gccint/Directives.html > for details about it. > >> + } elseif { [string match "*sleep-before-dying-1.c" $srcfile] } { >> + setenv ASAN_OPTIONS "sleep_before_dying=1" >> + set asan_torture_options [list { -O2 }] > > For env options, I believe we don't have any dg directive right now to > set env vars for runtime tests, but the best way would be to add it, > dg-env-var or similar. Or better yet, does libasan have a way to set > the options through some function call? Then you wouldn't have to > set env vars... > >> --- gcc/testsuite/g++.dg/asan/deep-thread-stack-1.C (revision 0) >> +++ gcc/testsuite/g++.dg/asan/deep-thread-stack-1.C (revision 0) >> @@ -0,0 +1,55 @@ >> +/* { dg-do run } */ >> +/* { dg-shouldfail "asan" } */ > > In C++ only tests, just use // comments instead of /* ... */ >> + >> +#include > > That is exactly where you need to require effective target pthread... > >> +/* { dg-options "-asan-initialization-order" } */ > > AFAIK gcc doesn't have that option, and if it had, it wouldn't be of this > form. -fasan-initialization-order, --param asan-initialization-order=1 or > similar, perhaps, but not -asan-initialization-order. > But more generally, adding tests into GCC testsuite for unimplemented > features is undesirable, you can prepare the tests and post a rough patch > how they could look like, but it shouldn't be committed until the feature > is implemented. > >> +/* { dg-additional-sources "Helpers/initialization-blacklist-extra-1.C" } */ > >> +// >> +// The LLVM Compiler Infrastructure > > I believe we've been removing the above two lines from libsanitizer, so they > should probably be removed also from the tests? > >> --- gcc/testsuite/lib/asan-dg.exp (revision 193881) >> +++ gcc/testsuite/lib/asan-dg.exp (working copy) >> @@ -75,6 +75,7 @@ proc asan_init { args } { >> set link_flags "[asan_link_flags [get_multilibs ${TOOL_OPTIONS}]]" >> } else { >> set link_flags "[asan_link_flags [get_multilibs]]" >> + set link_flags "[asan_link_flags [get_multilibs -m32]] $link_flags" > > As has been said earlier, please don't do this. > >> --- gcc/testsuite/c-c++-common/asan/interface-symbols-1.c (revision 0) >> +++ gcc/testsuite/c-c++-common/asan/interface-symbols-1.c (revision 0) >> @@ -0,0 +1,24 @@ >> +// Check the presense of interface symbols in compiled file. >> + >> +// RUN: %clang -fsanitize=address -dead_strip -O2 %s -o %t.exe >> +// RUN: nm %t.exe | egrep " [TW] " | sed "s/.* T //" | sed "s/.* W //" \ >> +// RUN: | grep "__asan_" | sed "s/___asan_/__asan_/" > %t.symbols >> +// RUN: cat %p/../../../include/sanitizer/asan_interface.h \ >> +// RUN: | sed "s/\/\/.*//" | sed "s/typedef.*//" \ >> +// RUN: | grep "__asan_.*(" | sed "s/.* __asan_/__asan_/;s/(.*//" \ >> +// RUN: > %t.interface >> +// RUN: echo __asan_report_load1 >> %t.interface >> +// RUN: echo __asan_report_load2 >> %t.interface >> +// RUN: echo __asan_report_load4 >> %t.interface >> +// RUN: echo __asan_report_load8 >> %t.interface >> +// RUN: echo __asan_report_load16 >> %t.interface >> +// RUN: echo __asan_report_store1 >> %t.interface >> +// RUN: echo __asan_report_store2 >> %t.interface >> +// RUN: echo __asan_report_store4 >> %t.interface >> +// RUN: echo __asan_report_store8 >> %t.interface >> +// RUN: echo __asan_report_store16 >> %t.interface >> +// RUN: cat %t.interface | sort -u | diff %t.symbols - >> + >> +/* { dg-options "-static-libasan -lpthread -ldl" } */ >> + >> +int main() { return 0; } > > This kind of test IMHO doesn't belong to the dejagnu testsuite, > if you really want to do it, it should be done somewhere in > libsanitizer/asan/ Makefile.am as part of building the library. > >> --- gcc/testsuite/c-c++-common/asan/force-inline-opt0-1.c (revision 0) >> +++ gcc/testsuite/c-c++-common/asan/force-inline-opt0-1.c (revision 0) >> @@ -0,0 +1,15 @@ >> +// This test checks that we are no instrumenting a memory access twice >> +// (before and after inlining) >> + >> +/* { dg-do run } */ >> +/* { dg-options "-Wno-attributes" } */ >> +__attribute__((always_inline)) > > Why -Wno-attributes? > >> +#include >> +int main(int argc, char **argv) { >> + static char XXX[10]; >> + static char YYY[10]; >> + static char ZZZ[10]; >> + memset(XXX, 0, 10); >> + memset(YYY, 0, 10); >> + memset(ZZZ, 0, 10); >> + int res = YYY[argc * 10]; // BOOOM >> + res += XXX[argc] + ZZZ[argc]; > > argc/argv using tests are not portable to all targets, you can't rely > argc isn't e.g. zero. Better just have some global variable, say, > int one = 1; > and at the beginning of main do asm volatile ("" : : : "memory"); > to let compiler forget about the value it has, or just make the variable > volatile int one = 1; > >> @@ -0,0 +1,22 @@ >> +/* { dg-do run } */ > > I'd expect you want /* { dg-options "-fno-builtin-strncpy" } */ > here, otherwise it is reported inside of main directly, rather than in the > strncpy interceptor. > >> +/* { dg-shouldfail "asan" } */ >> + >> +#include >> +#include >> +int main(int argc, char **argv) { >> + char *hello = (char*)malloc(6); >> + strcpy(hello, "hello"); >> + char *short_buffer = (char*)malloc(9); >> + strncpy(short_buffer, hello, 10); // BOOM >> + return short_buffer[8]; >> +} >> + >> +/* { 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:10|\[?]\[?]: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:9|\[?]\[?]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ > > Jakub Index: gcc/testsuite/gcc.dg/asan/asan.exp =================================================================== --- gcc/testsuite/gcc.dg/asan/asan.exp (revision 194002) +++ gcc/testsuite/gcc.dg/asan/asan.exp (working copy) @@ -30,6 +30,10 @@ if ![check_effective_target_faddress_san dg-init asan_init +# Set default torture options +set default_asan_torture_options [list { -O0 } { -O1 } { -O2 } { -O3 }] +set-torture-options $default_asan_torture_options + # Main loop. gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c $srcdir/c-c++-common/asan/*.c]] "" Index: gcc/testsuite/g++.dg/asan/deep-stack-uaf-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/deep-stack-uaf-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/deep-stack-uaf-1.C (revision 0) @@ -0,0 +1,33 @@ +// Check that we can store lots of stack frames if asked to. + +// { dg-do run } +// { dg-env-var ASAN_OPTIONS "malloc_context_size=120:redzone=512" } +// { dg-shouldfail "asan" } +#include +#include + +template +struct DeepFree { + static void free(char *x) { + DeepFree::free(x); + } +}; + +template<> +struct DeepFree<0> { + static void free(char *x) { + ::free(x); + } +}; + +int main() { + char *x = new char[10]; + // deep_free(x); + DeepFree<200>::free(x); + 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)" } Index: gcc/testsuite/g++.dg/asan/deep-tail-call-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/deep-tail-call-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/deep-tail-call-1.C (revision 0) @@ -0,0 +1,20 @@ +// { dg-do run } +// { dg-options "-mno-omit-leaf-frame-pointer -fno-omit-frame-pointer -fno-optimize-sibling-calls" } +// { 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); + 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)" } Index: gcc/testsuite/g++.dg/asan/default-options-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/default-options-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/default-options-1.C (revision 0) @@ -0,0 +1,15 @@ +// { dg-do run } + +const char *kAsanDefaultOptions="verbosity=1 foo=bar"; + +extern "C" +__attribute__((no_address_safety_analysis)) +const char *__asan_default_options() { + return kAsanDefaultOptions; +} + +int main() { + return 0; +} + +// { dg-output "Using the defaults from __asan_default_options:.* foo=bar.*(\n|\r\n|\r)" } Index: gcc/testsuite/g++.dg/asan/asan.exp =================================================================== --- gcc/testsuite/g++.dg/asan/asan.exp (revision 194002) +++ gcc/testsuite/g++.dg/asan/asan.exp (working copy) @@ -28,9 +28,15 @@ if ![check_effective_target_faddress_san dg-init asan_init +# Set default torture options +set default_asan_torture_options [list { -O0 } { -O1 } { -O2 } { -O3 }] +set-torture-options $default_asan_torture_options + # Main loop. gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C $srcdir/c-c++-common/asan/*.c]] "" +source $srcdir/$subdir/special/special.exp + # All done. asan_finish dg-finish Index: gcc/testsuite/g++.dg/asan/interception-test-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/interception-test-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/interception-test-1.C (revision 0) @@ -0,0 +1,22 @@ +// ASan interceptor can be accessed with __interceptor_ prefix. + +// { dg-do run } +// { dg-shouldfail "asan" } + +#include +#include + +extern "C" long __interceptor_strtol(const char *nptr, char **endptr, int base); +extern "C" long strtol(const char *nptr, char **endptr, int base) { + fprintf(stderr, "my_strtol_interceptor\n"); + return __interceptor_strtol(nptr, endptr, base); +} + +int main() { + char *x = (char*)malloc(10 * sizeof(char)); + free(x); + return (int)strtol(x, 0, 10); +} + +// { dg-output "my_strtol_interceptor.*(\n|\r\n|\r)" } +// { dg-output "\[^\n\r]*heap-use-after-free" } Index: gcc/testsuite/g++.dg/asan/large-func-test-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/large-func-test-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/large-func-test-1.C (revision 0) @@ -0,0 +1,47 @@ +// { dg-do run } +// { dg-shouldfail "asan" } + +#include +__attribute__((noinline)) +static void LargeFunction(int *x, int zero) { + x[0]++; + x[1]++; + x[2]++; + x[3]++; + x[4]++; + x[5]++; + x[6]++; + x[7]++; + x[8]++; + x[9]++; + + x[zero + 111]++; // we should report this exact line + + x[10]++; + x[11]++; + x[12]++; + x[13]++; + x[14]++; + x[15]++; + x[16]++; + x[17]++; + x[18]++; + x[19]++; +} + +int main(int argc, char **argv) { + int *x = new int[100]; + LargeFunction(x, argc - 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)" } Index: gcc/testsuite/g++.dg/asan/dlclose-test-1-so.C =================================================================== --- gcc/testsuite/g++.dg/asan/dlclose-test-1-so.C (revision 0) +++ gcc/testsuite/g++.dg/asan/dlclose-test-1-so.C (revision 0) @@ -0,0 +1,34 @@ +//===----------- dlclose-test-so.cc -----------------------------*- C++ -*-===// +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of AddressSanitizer, an address sanity checker. +// +// Regression test for +// http://code.google.com/p/address-sanitizer/issues/detail?id=19 +//===----------------------------------------------------------------------===// + +// { dg-skip-if "" { *-*-* } { "*" } { "" } } + +#include + +static int pad1; +static int static_var; +static int pad2; + +extern "C" +int *get_address_of_static_var() { + return &static_var; +} + +__attribute__((constructor)) +void at_dlopen() { + printf("%s: I am being dlopened\n", __FILE__); +} +__attribute__((destructor)) +void at_dlclose() { + printf("%s: I am being dlclosed\n", __FILE__); +} Index: gcc/testsuite/g++.dg/asan/special/dlclose-test-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/special/dlclose-test-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/special/dlclose-test-1.C (revision 0) @@ -0,0 +1,69 @@ +// Regression test for +// http://code.google.com/p/address-sanitizer/issues/detail?id=19 +// Bug description: +// 1. application dlopens foo.so +// 2. asan registers all globals from foo.so +// 3. application dlcloses foo.so +// 4. application mmaps some memory to the location where foo.so was before +// 5. application starts using this mmaped memory, but asan still thinks there +// are globals. +// 6. BOOM + +// { dg-do run } +// { dg-require-effective-target "dlopen" } +// { dg-require-effective-target "mmap" } + +#include +#include +#include +#include +#include + +#include + +using std::string; + +static const int kPageSize = 4096; + +typedef int *(fun_t)(); + +int main(int argc, char *argv[]) { + string path = string(argv[0]) + "-so.so"; + printf("opening %s ... \n", path.c_str()); + void *lib = dlopen(path.c_str(), RTLD_NOW); + if (!lib) { + printf("error in dlopen(): %s\n", dlerror()); + return 1; + } + fun_t *get = (fun_t*)dlsym(lib, "get_address_of_static_var"); + if (!get) { + printf("failed dlsym\n"); + return 1; + } + int *addr = get(); + //assert(((size_t)addr % 32) == 0); // should be 32-byte aligned. + printf("addr: %p\n", addr); + addr[0] = 1; // make sure we can write there. + + // Now dlclose the shared library. + printf("attempting to dlclose\n"); + if (dlclose(lib)) { + printf("failed to dlclose\n"); + return 1; + } + // Now, the page where 'addr' is unmapped. Map it. + size_t page_beg = ((size_t)addr) & ~(kPageSize - 1); + void *res = mmap((void*)(page_beg), kPageSize, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 0, 0); + if (res == (char*)-1L) { + printf("failed to mmap\n"); + return 1; + } + addr[1] = 2; // BOOM (if the bug is not fixed). + printf("PASS\n"); + // CHECK: PASS + return 0; +} + +// { dg-output "PASS" } Index: gcc/testsuite/g++.dg/asan/special/shared-lib-test-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/special/shared-lib-test-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/special/shared-lib-test-1.C (revision 0) @@ -0,0 +1,34 @@ +// { dg-do run } +// { dg-require-effective-target "dlopen" } +// { dg-shouldfail "asan" } + +#include +#include +#include + +#include + +using std::string; + +typedef void (fun_t)(int x); + +int main(int argc, char *argv[]) { + string path = string(argv[0]) + "-so.so"; + printf("opening %s ... \n", path.c_str()); + void *lib = dlopen(path.c_str(), RTLD_NOW); + if (!lib) { + printf("error in dlopen(): %s\n", dlerror()); + return 1; + } + fun_t *inc = (fun_t*)dlsym(lib, "inc"); + if (!inc) return 1; + printf("ok\n"); + inc(1); + inc(-1); // BOOM + return 0; +} + +// { dg-output "ERROR: AddressSanitizer:? global-buffer-overflow\[^\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\]+\[^\n\r]*(\n|\r\n|\r)" } +// { dg-output " #1 0x\[0-9a-f\]+ (in _*main \[^\n\r]*(shared-lib-test-1.C:27|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } Index: gcc/testsuite/g++.dg/asan/special/special.exp =================================================================== --- gcc/testsuite/g++.dg/asan/special/special.exp (revision 0) +++ gcc/testsuite/g++.dg/asan/special/special.exp (revision 0) @@ -0,0 +1,59 @@ +# Copyright (C) 2012 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +# Handle special tests +if { [info procs target_compile] != [list] \ + && [info procs saved_asan_target_compile] == [list] } { + rename target_compile saved_asan_target_compile + + proc target_compile { source dest type options } { + global srcdir subdir + + if { [string match "*dlclose-test-1.C" $source] } { + set dlclose_so_options $options + lappend dlclose_so_options "additional_flags=-fPIC -shared" + set auxfile [glob $srcdir/$subdir/dlclose-test-1-so.C] + set result [eval [list saved_asan_target_compile \ + $auxfile \ + "dlclose-test-1.exe-so.so" \ + "executable" $dlclose_so_options]] + } elseif { [string match "*shared-lib-test-1.C" $source] } { + set shared_lib_so_options $options + lappend shared_lib_so_options "additional_flags=-fPIC -shared" + set auxfile [glob $srcdir/$subdir/shared-lib-test-1-so.C] + set result [eval [list saved_asan_target_compile \ + $auxfile \ + "shared-lib-test-1.exe-so.so" \ + "executable" $shared_lib_so_options]] + } + set result [eval [list saved_asan_target_compile $source $dest $type $options]] + return $result + } +} + +# Main loop. +gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/special/*.C $srcdir/c-c++-common/asan/special/*.c]] "" + +if { [info procs saved_asan_target_compile] != [list] } { + rename target_compile "" + rename saved_asan_target_compile target_compile +} + +# Clean .so generated by special tests. +file delete dlclose-test-1.exe-so.so +file delete shared-lib-test-1.exe-so.so Index: gcc/testsuite/g++.dg/asan/deep-thread-stack-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/deep-thread-stack-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/deep-thread-stack-1.C (revision 0) @@ -0,0 +1,56 @@ +// { dg-do run } +// { dg-require-effective-target "pthread" } +// { dg-shouldfail "asan" } + +#include + +int *x; + +void *AllocThread(void *arg) { + x = new int; + *x = 42; + return NULL; +} + +void *FreeThread(void *arg) { + delete x; + return NULL; +} + +void *AccessThread(void *arg) { + *x = 43; // BOOM + return NULL; +} + +typedef void* (*callback_type)(void* arg); + +void *RunnerThread(void *function) { + pthread_t thread; + pthread_create(&thread, NULL, (callback_type)function, NULL); + pthread_join(thread, NULL); + return NULL; +} + +void RunThread(callback_type function) { + pthread_t runner; + pthread_create(&runner, NULL, RunnerThread, (void*)function); + pthread_join(runner, NULL); +} + +int main(int argc, char *argv[]) { + RunThread(AllocThread); + RunThread(FreeThread); + RunThread(AccessThread); + return (x != 0); +} + +// { dg-output "ERROR: AddressSanitizer: heap-use-after-free.*(\n|\r\n|\r)" } +// { dg-output "WRITE of size 4 at 0x\[0-9a-f\]+ thread T(\[0-9\]+).*(\n|\r\n|\r)" } +// { dg-output "freed by thread T(\[0-9\]+) here:.*(\n|\r\n|\r)" } +// { 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\\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:" } Index: gcc/testsuite/g++.dg/asan/interception-failure-test-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/interception-failure-test-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/interception-failure-test-1.C (revision 0) @@ -0,0 +1,21 @@ +// If user provides his own libc functions, ASan doesn't +// intercept these functions. + +// { dg-do run } + +#include +#include + +extern "C" long strtol(const char *nptr, char **endptr, int base) { + fprintf(stderr, "my_strtol_interceptor\n"); + return 0; +} + +int main() { + char *x = (char*)malloc(10 * sizeof(char)); + free(x); + return (int)strtol(x, 0, 10); + // CHECK: my_strtol_interceptor +} + +// { dg-output "my_strtol_interceptor" } Index: gcc/testsuite/g++.dg/asan/interception-malloc-test-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/interception-malloc-test-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/interception-malloc-test-1.C (revision 0) @@ -0,0 +1,23 @@ +// ASan interceptor can be accessed with __interceptor_ prefix. + +// { dg-do run } +// { dg-shouldfail "asan" } + +#include +#include +#include + +extern "C" void *__interceptor_malloc(size_t size); +extern "C" void *malloc(size_t size) { + write(2, "malloc call\n", sizeof("malloc call\n") - 1); + return __interceptor_malloc(size); +} + +int main() { + char *x = (char*)malloc(10 * sizeof(char)); + free(x); + return (int)strtol(x, 0, 10); +} + +// { dg-output "malloc call.*(\n|\r\n|\r)" } +// { dg-output "\[^\n\r]*heap-use-after-free" } Index: gcc/testsuite/g++.dg/asan/shared-lib-test-1-so.C =================================================================== --- gcc/testsuite/g++.dg/asan/shared-lib-test-1-so.C (revision 0) +++ gcc/testsuite/g++.dg/asan/shared-lib-test-1-so.C (revision 0) @@ -0,0 +1,22 @@ +//===----------- shared-lib-test-so.cc --------------------------*- C++ -*-===// +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of AddressSanitizer, an address sanity checker. +// +//===----------------------------------------------------------------------===// + +// { dg-skip-if "" { *-*-* } { "*" } { "" } } + +#include + +int pad[10]; +int GLOB[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +extern "C" +void inc(int index) { + GLOB[index]++; +} Index: gcc/testsuite/g++.dg/asan/symbolize-callback-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/symbolize-callback-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/symbolize-callback-1.C (revision 0) @@ -0,0 +1,20 @@ +// { dg-do run } +// { dg-skip-if "" { *-*-* } { "*" } { "-O2 -m64" } } +// { dg-shouldfail "asan" } + +#include +#include + +extern "C" +bool __asan_symbolize(const void *pc, char *out_buffer, int out_size) { + snprintf(out_buffer, out_size, "MySymbolizer"); + return true; +} + +int main() { + char *x = (char*)malloc(10 * sizeof(char)); + free(x); + return x[5]; +} + +// { dg-output "MySymbolizer" } Index: gcc/testsuite/lib/target-supports.exp =================================================================== --- gcc/testsuite/lib/target-supports.exp (revision 194002) +++ gcc/testsuite/lib/target-supports.exp (working copy) @@ -719,6 +719,26 @@ proc check_effective_target_mmap {} { return [check_function_available "mmap"] } +# Return 1 if the target supports dlopen, 0 otherwise. +proc check_effective_target_dlopen {} { + return [check_function_available "dlopen"] +} + +# Return 1 if the target supports clone, 0 otherwise. +proc check_effective_target_clone {} { + return [check_function_available "clone"] +} + +# Return 1 if the target supports setrlimit, 0 otherwise. +proc check_effective_target_setrlimit {} { + return [check_function_available "setrlimit"] +} + +# Return 1 if the target supports swapcontext, 0 otherwise. +proc check_effective_target_swapcontext {} { + return [check_function_available "swapcontext"] +} + # Return 1 if compilation with -pthread is error-free for trivial # code, 0 otherwise. Index: gcc/testsuite/lib/gcc-dg.exp =================================================================== --- gcc/testsuite/lib/gcc-dg.exp (revision 194002) +++ gcc/testsuite/lib/gcc-dg.exp (working copy) @@ -254,7 +254,16 @@ if { [info procs ${tool}_load] != [list] proc ${tool}_load { program args } { global tool global shouldfail + global set_env_var + + set saved_env_var [list] + if { [llength $set_env_var] != 0 } { + set-env-var + } set result [eval [list saved_${tool}_load $program] $args] + if { [llength $set_env_var] != 0 } { + restore-env-var + } if { $shouldfail != 0 } { switch [lindex $result 0] { "pass" { set status "fail" } @@ -266,6 +275,37 @@ if { [info procs ${tool}_load] != [list] } } +proc dg-env-var { args } { + global set_env_var + if { [llength $args] != 3 } { + error "[lindex $args 1]: need two arguments" + return + } + lappend set_env_var [list [lindex $args 1] [lindex $args 2]] +} + +proc set-env-var { } { + global set_env_var + upvar 1 saved_env_var saved_env_var + foreach env_var $set_env_var { + set var [lindex $env_var 0] + set value [lindex $env_var 1] + if [info exists env($var)] { + lappend saved_env_var [list $var $env($var)] + } + setenv $var $value + } +} + +proc restore-env-var { } { + upvar 1 saved_env_var saved_env_var + foreach env_var $saved_env_var { + set var [lindex $env_var 0] + set value [lindex $env_var 1] + unsetenv $var $value + } +} + # Utility routines. # @@ -287,6 +327,10 @@ proc search_for { file pattern } { # as c-torture does. proc gcc-dg-runtest { testcases default-extra-flags } { global runtests + global set_env_var + + # Init set_env_var + set set_env_var [list] # Some callers set torture options themselves; don't override those. set existing_torture_options [torture-options-exist] Index: gcc/testsuite/c-c++-common/asan/strip-path-prefix-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/strip-path-prefix-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/strip-path-prefix-1.c (revision 0) @@ -0,0 +1,14 @@ +/* { dg-do run } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O2 -m64" } } */ +/* { dg-env-var ASAN_OPTIONS "strip_path_prefix='/'" } */ +/* { dg-shouldfail "asan" } */ + +#include +int main() { + char *x = (char*)malloc(10 * sizeof(char)); + free(x); + return x[5]; +} + +/* { dg-output "heap-use-after-free.*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ \[(\]\[^/\]\[^\n\r]*(\n|\r\n|\r)" } */ Index: gcc/testsuite/c-c++-common/asan/force-inline-opt0-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/force-inline-opt0-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/force-inline-opt0-1.c (revision 0) @@ -0,0 +1,16 @@ +/* This test checks that we are no instrumenting a memory access twice + (before and after inlining) */ + +/* { dg-do run } */ +/* { dg-options "-Wno-attributes" } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0 -m64" "-O1 -m64" } } */ +__attribute__((always_inline)) +void foo(int *x) { + *x = 0; +} + +int main() { + int x; + foo(&x); + return x; +} Index: gcc/testsuite/c-c++-common/asan/swapcontext-test-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/swapcontext-test-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/swapcontext-test-1.c (revision 0) @@ -0,0 +1,62 @@ +/* Check that ASan plays well with easy cases of makecontext/swapcontext. */ + +/* { dg-do run } */ +/* { dg-require-effective-target "swapcontext" } */ + +#include +#include +#include + +ucontext_t orig_context; +ucontext_t child_context; + +void Child(int mode) { + char x[32] = {0}; /* Stack gets poisoned. */ + printf("Child: %p\n", x); + /* (a) Do nothing, just return to parent function. + (b) Jump into the original function. Stack remains poisoned unless we do + something. */ + if (mode == 1) { + if (swapcontext(&child_context, &orig_context) < 0) { + perror("swapcontext"); + _exit(0); + } + } +} + +int Run(int arg, int mode) { + int i; + const int kStackSize = 1 << 20; + char child_stack[kStackSize + 1]; + printf("Child stack: %p\n", child_stack); + /* Setup child context. */ + getcontext(&child_context); + child_context.uc_stack.ss_sp = child_stack; + child_context.uc_stack.ss_size = kStackSize / 2; + if (mode == 0) { + child_context.uc_link = &orig_context; + } + makecontext(&child_context, (void (*)())Child, 1, mode); + if (swapcontext(&orig_context, &child_context) < 0) { + perror("swapcontext"); + return 0; + } + /* Touch childs's stack to make sure it's unpoisoned. */ + for (i = 0; i < kStackSize; i++) { + child_stack[i] = i; + } + return child_stack[arg]; +} + +int main(int argc, char **argv) { + int ret = 0; + ret += Run(argc - 1, 0); + printf("Test1 passed\n"); + ret += Run(argc - 1, 1); + printf("Test2 passed\n"); + return ret; +} + +/* { dg-output "WARNING: ASan doesn't fully support makecontext/swapcontext.*" } */ +/* { dg-output "Test1 passed.*" } */ +/* { dg-output "Test2 passed.*" } */ Index: gcc/testsuite/c-c++-common/asan/null-deref-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/null-deref-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/null-deref-1.c (revision 0) @@ -0,0 +1,16 @@ +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +__attribute__((noinline)) +static void NullDeref(int *ptr) { + ptr[10]++; +} +int main() { + NullDeref((int*)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 "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)" } */ Index: gcc/testsuite/c-c++-common/asan/global-overflow-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/global-overflow-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/global-overflow-1.c (revision 0) @@ -0,0 +1,22 @@ +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +#include +volatile int one = 1; + +int main() { + static char XXX[10]; + static char YYY[10]; + static char ZZZ[10]; + memset(XXX, 0, 10); + memset(YYY, 0, 10); + memset(ZZZ, 0, 10); + int res = YYY[one * 10]; /* BOOOM */ + res += XXX[one] + ZZZ[one]; + 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 .*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)" } */ Index: gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c (revision 0) @@ -0,0 +1,23 @@ +/* { dg-do run } */ +/* { dg-options "-fno-builtin-strncpy" } */ +/* { dg-shouldfail "asan" } */ + +#include +#include +int main(int argc, char **argv) { + char *hello = (char*)malloc(6); + strcpy(hello, "hello"); + char *short_buffer = (char*)malloc(9); + strncpy(short_buffer, hello, 10); /* BOOM */ + return short_buffer[8]; +} + +/* { 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 "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)" } */ + + Index: gcc/testsuite/c-c++-common/asan/rlimit-mmap-test-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/rlimit-mmap-test-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/rlimit-mmap-test-1.c (revision 0) @@ -0,0 +1,22 @@ +/* Check that we properly report mmap failure. */ + +/* { dg-do run } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0 -m64" } } */ +/* { dg-require-effective-target "setrlimit" } */ +/* { dg-shouldfail "asan" } */ + +#include +#include +#include +#include + +static volatile void *x; + +int main(int argc, char **argv) { + struct rlimit mmap_resource_limit = { 0, 0 }; + assert(0 == setrlimit(RLIMIT_AS, &mmap_resource_limit)); + x = malloc(10000000); + return 0; +} + +/* { dg-output "AddressSanitizer is unable to mmap" } */ Index: gcc/testsuite/c-c++-common/asan/stack-overflow-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/stack-overflow-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/stack-overflow-1.c (revision 0) @@ -0,0 +1,17 @@ +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +volatile int one = 1; + +#include + +int main() { + char x[10]; + memset(x, 0, 10); + int res = x[one * 10]; /* BOOOM */ + return res; +} + +/* { 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:11|\[?\]\[?\]:0)|\[(\]).*(\n|\r\n|\r)" } */ +/* { dg-output "Address 0x\[0-9a-f\]+ is\[^\n\r]*frame
" } */ Index: gcc/testsuite/c-c++-common/asan/use-after-free-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/use-after-free-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/use-after-free-1.c (revision 0) @@ -0,0 +1,22 @@ +/* { dg-do run } */ +/* { dg-options "-fno-builtin-malloc" } */ +/* { dg-shouldfail "asan" } */ + +#include +int main() { + char *x = (char*)malloc(10 * sizeof(char)); + free(x); + return x[5]; +} + +/* { 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 "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 "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)" } */ Index: gcc/testsuite/c-c++-common/asan/stack-use-after-return-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/stack-use-after-return-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/stack-use-after-return-1.c (revision 0) @@ -0,0 +1,31 @@ +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ +#include + +__attribute__((noinline)) +char *Ident(char *x) { + fprintf(stderr, "1: %p\n", x); + return x; +} + +__attribute__((noinline)) +char *Func1() { + char local; + return Ident(&local); +} + +__attribute__((noinline)) +void Func2(char *x) { + fprintf(stderr, "2: %p\n", x); + *x = 1; +} + +int main(int argc, char **argv) { + Func2(Func1()); + return 0; +} + +/* { dg-output "WRITE of size 1 \[^\n\r]* thread T0" } */ +/* { dg-output " #0\[^\n\r]*Func2\[^\n\r]*(stack-use-after-return.cc:24|\[?\]\[?\]:)" } */ +/* { dg-output "is located in frame <\[^\n\r]*Func1\[^\n\r]*> of T0's stack" } */ + Index: gcc/testsuite/c-c++-common/asan/sanity-check-pure-c-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/sanity-check-pure-c-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/sanity-check-pure-c-1.c (revision 0) @@ -0,0 +1,16 @@ +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +#include +int main() { + char *x = (char*)malloc(10 * sizeof(char)); + 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:7|\[?\]\[?\]: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:6|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ + Index: gcc/testsuite/c-c++-common/asan/clone-test-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/clone-test-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/clone-test-1.c (revision 0) @@ -0,0 +1,47 @@ +/* Regression test for: + http://code.google.com/p/address-sanitizer/issues/detail?id=37 */ + +/* { dg-do run } */ +/* { dg-options "-D_GNU_SOURCE" } */ +/* { dg-require-effective-target "clone" } */ +/* { dg-shouldfail "asan" } */ + +#include +#include +#include +#include +#include +#include +#include + +int Child(void *arg) { + char x[32] = {0}; /* Stack gets poisoned. */ + printf("Child: %p\n", x); + _exit(1); /* NoReturn, stack will remain unpoisoned unless we do something. */ +} + +int main(int argc, char **argv) { + int i; + const int kStackSize = 1 << 20; + char child_stack[kStackSize + 1]; + char *sp = child_stack + kStackSize; /* Stack grows down. */ + printf("Parent: %p\n", sp); + pid_t clone_pid = clone(Child, sp, CLONE_FILES | CLONE_VM, NULL, 0, 0, 0); + int status; + pid_t wait_result = waitpid(clone_pid, &status, __WCLONE); + if (wait_result < 0) { + perror("waitpid"); + return 0; + } + 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"); + return ret; + } + return 0; +} + +/* { dg-output "PASSED" } */ Index: gcc/testsuite/c-c++-common/asan/heap-overflow-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/heap-overflow-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/heap-overflow-1.c (revision 0) @@ -0,0 +1,20 @@ +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +#include +#include +int main(int argc, char **argv) { + char *x = (char*)malloc(10 * sizeof(char)); + memset(x, 0, 10); + int res = x[argc * 10]; /* 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:9|\[?\]\[?\]: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:7|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ + Index: gcc/testsuite/c-c++-common/asan/sleep-before-dying-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/sleep-before-dying-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/sleep-before-dying-1.c (revision 0) @@ -0,0 +1,13 @@ +/* { dg-do run } */ +/* { dg-env-var ASAN_OPTIONS "sleep_before_dying=1" } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O2 -m64" } } */ +/* { dg-shouldfail "asan" } */ + +#include +int main() { + char *x = (char*)malloc(10 * sizeof(char)); + free(x); + return x[5]; +} + +/* { dg-output "Sleeping for 1 second" } */