From patchwork Wed Nov 28 09:15:20 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wei Mi X-Patchwork-Id: 202397 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 2BEC92C008F for ; Wed, 28 Nov 2012 20:15:43 +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=1354698944; h=Comment: DomainKey-Signature:Received:Received:Received:Received: MIME-Version:Received:Received: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=tG08ypC iKLK8FinoUZ2yTekF8So=; b=blCwaNZy7kjtbzKDoepP3Ur3FMnWi9so6zUZpaP V7ATsRKRQ8pGBfQVjcOTwEKi4X2cxjfx35jCggM1kn8NcxxfAa1HZi6L4j4IQui2 dLk3aX4tjvrM0AYgvLK0FDbcSav2Z5dw1RpW5DXbnUg1JEW4sF1PPjf5wwm2Rw+P wiTI= 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: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=tYy3g+6cPe2AOaxnByQurQ1UsjgxnjR0QFzaXKwBdyYP/LQTMLejFYqY0hxK5u EV+YidwAdTXOjcLfAswsqgbJ45066fcopSJZ3lNZSV3B8aIDX9eLZ9gA7URvMVbM kwvbpKBEfyb+TbqHu1LW0TcTBEc7GvqgAYs5r9MlogJ8o=; Received: (qmail 16944 invoked by alias); 28 Nov 2012 09:15:38 -0000 Received: (qmail 16927 invoked by uid 22791); 28 Nov 2012 09:15:34 -0000 X-SWARE-Spam-Status: No, hits=-5.4 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, KHOP_RCVD_TRUST, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE, RP_MATCHES_RCVD, 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; Wed, 28 Nov 2012 09:15:21 +0000 Received: by mail-qa0-f47.google.com with SMTP id t11so4535762qaa.20 for ; Wed, 28 Nov 2012 01:15:20 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:date:message-id:subject:from:to:cc:content-type :x-gm-message-state; bh=NYV7/fZHL45lxqGfiwwR46BtxuigQZldtamHGJChXxM=; b=PQy4pBcIcb2NJuD3Fpgdo2U4h0oHxyhXEnhM4ExEGNs+qzqrRfLvFFjuomkxDW+51l nXiaQ8ZVrq33Qt6AdOSR8u5zGc5eClCbqtIyKIdRJeCfceAqeE+JpYAPhw80sx/dU5Bl nGMjMr3q1oWJJhqgOHPzw/ZeKXJ2cZi/U33zkZrTELPmFN6wC/pSn40JgT/ESa2PYpRw RdiMcPGML9aJuWZqtDwdmckk9gaLa865LmcDouNui1BdRIHlfBEpccCxU6jZ3S4vZC/B 8X24C9+CsmB+SxIuspYPMFVcwiANF7hD3q7BVwdZfOcHthpK/T8lCsIDjwFt2WhTU8qp 1oew== MIME-Version: 1.0 Received: by 10.229.78.200 with SMTP id m8mr4409103qck.96.1354094120224; Wed, 28 Nov 2012 01:15:20 -0800 (PST) Received: by 10.49.132.225 with HTTP; Wed, 28 Nov 2012 01:15:20 -0800 (PST) Date: Wed, 28 Nov 2012 01:15:20 -0800 Message-ID: Subject: [PATCH] asan unit tests from llvm lit-test From: Wei Mi To: GCC Patches Cc: David Li , Diego Novillo , Jakub Jelinek , Kostya Serebryany , Dodji Seketeli X-Gm-Message-State: ALoCoQkFaUB07UOprIjEByE9Wtg/4yz1SoeekDBZujru7CWeLpOaQk9DbQbkD6hpREiwlTrCHmCJ8sKwPo0mlOHI4RaUcuYA1R4GUDsCaFOjZpw406ubpHYsQ21O/uLvvQQwBFL0cx08kVXgIgVo1cv5ry3TgO5OQCjk/PRvaiePnxyx/rucVY0oi3tP0XPCk7r8tciDTKOP 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 Hi, I try to migrate the left asan lit-tests from llvm (class3). This is a preliminary version patch. Please forgive it has many mistakes. 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. Thanks, Wei. gcc/testsuite/ 2012-11-28 Wei Mi * gcc.dg/asan/asan.exp: Case by case processing for some special testcases. * g++.dg/asan/asan.exp: Likewise. * lib/asan-dg.exp: Likewise. * 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. * g++.dg/asan/Helpers: Likewise. * g++.dg/asan/Helpers/initialization-blacklist-1.tmp: Likewise. * g++.dg/asan/Helpers/initialization-blacklist-extra-1.C: Likewise. * g++.dg/asan/deep-thread-stack-1.C: Likewise. * g++.dg/asan/shared-lib-test-1.C: Likewise. * g++.dg/asan/deep-stack-uaf-1.C: Likewise. * g++.dg/asan/on-error-callback-1.C: Likewise. * g++.dg/asan/initialization-blacklist-1.C: Likewise. * g++.dg/asan/initialization-nobug-1.C: Likewise. * g++.dg/asan/large-func-test-1.C: Likewise. * g++.dg/asan/SharedLibs: Likewise. * g++.dg/asan/SharedLibs/dlclose-test-1-so.C: Likewise. * g++.dg/asan/SharedLibs/shared-lib-test-1-so.C: Likewise. * g++.dg/asan/dlclose-test-1.C: Likewise. * g++.dg/asan/malloc-hook-1.C: Likewise. * g++.dg/asan/symbolize-callback-1.C: Likewise. * g++.dg/asan/default-options-1.C: Likewise. * g++.dg/asan/deep-tail-call-1.C: Likewise. * c-c++-common/asan/linux: Likewise. * c-c++-common/asan/linux/initialization-bug-any-order-1.c: Likewise. * c-c++-common/asan/linux/rlimit-mmap-test-1.c: Likewise. * c-c++-common/asan/linux/swapcontext-test-1.c: Likewise. * c-c++-common/asan/linux/clone-test-1.c: Likewise. * c-c++-common/asan/sleep-before-dying-1.c: Likewise. * c-c++-common/asan/Helpers: Likewise. * c-c++-common/asan/Helpers/blacklist-extra-1.c: Likewise. * c-c++-common/asan/Helpers/interface_symbols.sh: Likewise. * c-c++-common/asan/Helpers/initialization-bug-extra-1.c: Likewise. * c-c++-common/asan/Helpers/blacklist-1.tmp: Likewise. * c-c++-common/asan/interface-symbols-1.c: Likewise. * c-c++-common/asan/strip-path-prefix-1.c: Likewise. * c-c++-common/asan/force-inline-opt0-1.c: Likewise. * c-c++-common/asan/null-deref-1.c: Likewise. * c-c++-common/asan/global-overflow-1.c: Likewise. * c-c++-common/asan/initialization-bug-1.c: Likewise. * c-c++-common/asan/strncpy-overflow-1.c: Likewise. * c-c++-common/asan/stack-overflow-1.c: Likewise. * c-c++-common/asan/blacklist-1.c: Likewise. * c-c++-common/asan/use-after-free-1.c: Likewise. * c-c++-common/asan/sanity-check-pure-c-1.c: Likewise. * c-c++-common/asan/stack-use-after-return-1.c: Likewise. * c-c++-common/asan/heap-overflow-1.c: Likewise. Index: gcc/testsuite/gcc.dg/asan/asan.exp =================================================================== --- gcc/testsuite/gcc.dg/asan/asan.exp (revision 193881) +++ gcc/testsuite/gcc.dg/asan/asan.exp (working copy) @@ -16,8 +16,6 @@ # along with GCC; see the file COPYING3. If not see # . -# GCC testsuite that uses the `dg.exp' driver. - # Load support procs. load_lib gcc-dg.exp load_lib asan-dg.exp @@ -30,8 +28,89 @@ if ![check_effective_target_faddress_san dg-init asan_init +set default_asan_torture_options [list { -O0 -m32 } { -O1 -m32 } { -O2 -m32 } { -O3 -m32 } \ + { -O0 -m64 } { -O1 -m64 } { -O2 -m64 } { -O3 -m64 }] + +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 "*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]] + } + return $result + } +} + # Main loop. -gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c $srcdir/c-c++-common/asan/*.c]] "" +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 }] + } elseif { [string match "*initialization-bug-1.c" $srcfile] } { + set asan_torture_options [list { -O0 -m32 } { -O0 -m64 }] + } elseif { [string match "*interface-symbols-1.c" $srcfile] } { + set asan_torture_options [list { -O2 }] + } elseif { [string match "*sleep-before-dying-1.c" $srcfile] } { + setenv ASAN_OPTIONS "sleep_before_dying=1" + set asan_torture_options [list { -O2 }] + } elseif { [string match "*strip-path-prefix-1.c" $srcfile] } { + setenv ASAN_OPTIONS "strip_path_prefix='/'" + set asan_torture_options [list { -O2 }] + } elseif { [string match "*initialization-bug-any-order-1.c" $srcfile] } { + set asan_torture_options [list { -O0 }] + set-torture-options $asan_torture_options + global subtest + set subtest "subtest1" + gcc-dg-runtest $srcfile "" + set subtest "subtest2" + } elseif { [string match "*rlimit-mmap-test-1.c" $srcfile] } { + set asan_torture_options [list { }] + set-torture-options $asan_torture_options + } + + set-torture-options $asan_torture_options + gcc-dg-runtest $srcfile "" + + if { [string match "*sleep-before-dying-1.c" $srcfile] + || [string match "*strip-path-prefix-1.c" $srcfile] } { + unsetenv ASAN_OPTIONS + } +} # All done. asan_finish Index: gcc/testsuite/g++.dg/asan/Helpers/initialization-blacklist-1.tmp =================================================================== --- gcc/testsuite/g++.dg/asan/Helpers/initialization-blacklist-1.tmp (revision 0) +++ gcc/testsuite/g++.dg/asan/Helpers/initialization-blacklist-1.tmp (revision 0) @@ -0,0 +1,2 @@ +global-init:*badGlobal* +global-init-type:*badNamespace::BadClass* Index: gcc/testsuite/g++.dg/asan/Helpers/initialization-blacklist-extra-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/Helpers/initialization-blacklist-extra-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/Helpers/initialization-blacklist-extra-1.C (revision 0) @@ -0,0 +1,15 @@ +int zero_init() { return 0; } +int badGlobal = zero_init(); +int readBadGlobal() { return badGlobal; } + +namespace badNamespace { +class BadClass { + public: + BadClass() { value = 0; } + int value; +}; +// Global object with non-trivial constructor. +BadClass bad_object; +} // namespace badNamespace + +int accessBadObject() { return badNamespace::bad_object.value; } 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,55 @@ +/* { dg-do run } */ +/* { 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/shared-lib-test-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/shared-lib-test-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/shared-lib-test-1.C (revision 0) @@ -0,0 +1,33 @@ +/* { dg-do run } */ +/* { 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:26|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ 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,32 @@ +// Check that we can store lots of stack frames if asked to. + +/* { dg-do run } */ +/* { 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/on-error-callback-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/on-error-callback-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/on-error-callback-1.C (revision 0) @@ -0,0 +1,18 @@ +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +#include +#include + +extern "C" +void __asan_on_error() { + fprintf(stderr, "__asan_on_error called"); +} + +int main() { + char *x = (char*)malloc(10 * sizeof(char)); + free(x); + return x[5]; +} + +/* { dg-output "__asan_on_error called.*(\n|\r\n|\r)" } */ Index: gcc/testsuite/g++.dg/asan/initialization-blacklist-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/initialization-blacklist-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/initialization-blacklist-1.C (revision 0) @@ -0,0 +1,15 @@ +/* { dg-do run } */ +/* { dg-options "-asan-initialization-order" } */ +/* { dg-additional-sources "Helpers/initialization-blacklist-extra-1.C" } */ + +// Function is defined in another TU. +int readBadGlobal(); +int x = readBadGlobal(); // init-order bug. + +// Function is defined in another TU. +int accessBadObject(); +int y = accessBadObject(); // init-order bug. + +int main(int argc, char **argv) { + return argc + x + y - 1; +} Index: gcc/testsuite/g++.dg/asan/asan.exp =================================================================== --- gcc/testsuite/g++.dg/asan/asan.exp (revision 193881) +++ gcc/testsuite/g++.dg/asan/asan.exp (working copy) @@ -28,8 +28,124 @@ if ![check_effective_target_faddress_san dg-init asan_init +# Compiling dlclose-test-1.C needs to build dlclose-test-so-1.so beforehand. +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 "*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]] + } elseif { [string match "*initialization-blacklist-1.C" $source] } { + set blacklist_options $options + set blist_tmp [glob $srcdir/$subdir/Helpers/initialization-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]] + } elseif { [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/SharedLibs/dlclose-test-1-so.C] + set result [eval [list saved_asan_target_compile \ + $auxfile \ + "dlclose-test-1.exe-so.so" \ + "executable" $dlclose_so_options]] + set result [eval [list saved_asan_target_compile \ + $source $dest $type $options]] + file delete "dlclose-test-1.exe-so.so" + } 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/SharedLibs/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]] + file delete "shared-lib-test-1.exe-so.so" + } 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]] + } + return $result + } +} + +set default_asan_torture_options [list { -O0 -m32 } { -O1 -m32 } { -O2 -m32 } { -O3 -m32 } \ + { -O0 -m64 } { -O1 -m64 } { -O2 -m64 } { -O3 -m64 }] + # Main loop. -gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C $srcdir/c-c++-common/asan/*.c]] "" +foreach srcfile [lsort [glob -nocomplain \ + $srcdir/$subdir/*.C \ + $srcdir/$subdir/linux/*.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 "*deep-stack-uaf-1.C" $srcfile] } { + setenv ASAN_OPTIONS "malloc_context_size=120:redzone=512" + } elseif { [string match "*force-inline-opt0-1.c" $srcfile] } { + set asan_torture_options [list { -O0 -m64 } { -O1 -m64 }] + } elseif { [string match "*initialization-bug-1.c" $srcfile] } { + set asan_torture_options [list { -O0 -m32 } { -O0 -m64 }] + } elseif { [string match "*interface-symbols-1.c" $srcfile] + || [string match "*symbolize-callback-1.C" $srcfile] + || [string match "*malloc-hook-1.C" $srcfile] } { + set asan_torture_options [list { -O2 }] + } elseif { [string match "*sleep-before-dying-1.c" $srcfile] } { + setenv ASAN_OPTIONS "sleep_before_dying=1" + set asan_torture_options [list { -O2 }] + } elseif { [string match "*strip-path-prefix-1.c" $srcfile] } { + setenv ASAN_OPTIONS "strip_path_prefix='/'" + set asan_torture_options [list { -O2 }] + } elseif { [string match "*initialization-bug-any-order-1.c" $srcfile] } { + set asan_torture_options [list { -O0 }] + set-torture-options $asan_torture_options + global subtest + set subtest "subtest1" + gcc-dg-runtest $srcfile "" + set subtest "subtest2" + } elseif { [string match "*rlimit-mmap-test-1.c" $srcfile] } { + set asan_torture_options [list { }] + } + + set-torture-options $asan_torture_options + gcc-dg-runtest $srcfile "" + + if { [string match "*deep-stack-uaf-1.C" $srcfile] + || [string match "*sleep-before-dying-1.c" $srcfile] + || [string match "*strip-path-prefix-1.c" $srcfile] } { + unsetenv ASAN_OPTIONS + } +} # All done. asan_finish Index: gcc/testsuite/g++.dg/asan/initialization-nobug-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/initialization-nobug-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/initialization-nobug-1.C (revision 0) @@ -0,0 +1,51 @@ +// A collection of various initializers which shouldn't trip up initialization +// order checking. If successful, this will just return 0. + +/* { dg-do run } */ +/* { dg-options "--std=c++11 -asan-initialization-order" } */ + +// Simple access: +// Make sure that accessing a global in the same TU is safe + +bool condition = true; +int initializeSameTU() { + return condition ? 0x2a : 052; +} +int sameTU = initializeSameTU(); + +// Linker initialized: +// Check that access to linker initialized globals originating from a different +// TU's initializer is safe. + +int A = (1 << 1) + (1 << 3) + (1 << 5), B; +int getAB() { + return A * B; +} + +// Function local statics: +// Check that access to function local statics originating from a different +// TU's initializer is safe. + +int countCalls() { + static int calls; + return ++calls; +} + +// Constexpr: +// We need to check that a global variable initialized with a constexpr +// constructor can be accessed during dynamic initialization (as a constexpr +// constructor implies that it was initialized during constant initialization, +// not dynamic initialization). + +class Integer { + private: + int value; + + public: + constexpr Integer(int x = 0) : value(x) {} + int getValue() {return value;} +}; +Integer coolestInteger(42); +int getCoolestInteger() { return coolestInteger.getValue(); } + +int main() { return 0; } 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,46 @@ +/* { 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 _*main\[^\n\r]*(large-func-test-1.C:33|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ Index: gcc/testsuite/g++.dg/asan/SharedLibs/dlclose-test-1-so.C =================================================================== --- gcc/testsuite/g++.dg/asan/SharedLibs/dlclose-test-1-so.C (revision 0) +++ gcc/testsuite/g++.dg/asan/SharedLibs/dlclose-test-1-so.C (revision 0) @@ -0,0 +1,33 @@ +//===----------- dlclose-test-so.cc -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// 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 +//===----------------------------------------------------------------------===// +#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/SharedLibs/shared-lib-test-1-so.C =================================================================== --- gcc/testsuite/g++.dg/asan/SharedLibs/shared-lib-test-1-so.C (revision 0) +++ gcc/testsuite/g++.dg/asan/SharedLibs/shared-lib-test-1-so.C (revision 0) @@ -0,0 +1,21 @@ +//===----------- shared-lib-test-so.cc --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// 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. +// +//===----------------------------------------------------------------------===// +#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/dlclose-test-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/dlclose-test-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/dlclose-test-1.C (revision 0) @@ -0,0 +1,67 @@ +// 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 } */ + +#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/malloc-hook-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/malloc-hook-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/malloc-hook-1.C (revision 0) @@ -0,0 +1,24 @@ +/* { dg-do run } */ +#include +#include + +extern "C" { +// Note: avoid calling functions that allocate memory in malloc/free +// to avoid infinite recursion. +void __asan_malloc_hook(void *ptr, size_t sz) { + write(1, "MallocHook\n", sizeof("MallocHook\n")); +} +void __asan_free_hook(void *ptr) { + write(1, "FreeHook\n", sizeof("FreeHook\n")); +} +} // extern "C" + +int main() { + volatile int *x = new int; + *x = 0; + delete x; + return 0; +} + +/* { dg-output "MallocHook(\n|\r\n|\r)" } */ +/* { dg-output "FreeHook(\n|\r\n|\r)" } */ 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,19 @@ +/* { dg-do run } */ +/* { 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/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,16 @@ +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +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/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/linux/interception-test-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/linux/interception-test-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/linux/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/linux/interception-failure-test-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/linux/interception-failure-test-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/linux/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/linux/interception-malloc-test-1.C =================================================================== --- gcc/testsuite/g++.dg/asan/linux/interception-malloc-test-1.C (revision 0) +++ gcc/testsuite/g++.dg/asan/linux/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/lib/asan-dg.exp =================================================================== --- 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" } } Index: gcc/testsuite/c-c++-common/asan/interface-symbols-1.c =================================================================== --- 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; } 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,12 @@ +/* { 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 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,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)) +void foo(int *x) { + *x = 0; +} + +int main() { + int x; + foo(&x); + return x; +} 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 crashed 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.cc:6|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #1 0x\[0-9a-f\]+ (in \[^\n\r]*main\[^\n\r]*(null_deref.cc: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,20 @@ +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +#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]; + 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:18|\[(\])\[^\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/initialization-bug-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/initialization-bug-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/initialization-bug-1.c (revision 0) @@ -0,0 +1,50 @@ +// Test to make sure basic initialization order errors are caught. + +// RUN: %clangxx_asan -m64 -O0 %s %p/Helpers/initialization-bug-extra2.cc\ +// RUN: -mllvm -asan-initialization-order -o %t && %t 2>&1 \ +// RUN: | %symbolize | FileCheck %s +// RUN: %clangxx_asan -m32 -O0 %s %p/Helpers/initialization-bug-extra2.cc\ +// RUN: -mllvm -asan-initialization-order -o %t && %t 2>&1 \ +// RUN: | %symbolize | FileCheck %s + +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ +/* { dg-options "-asan-initialization-order" } */ +/* { dg-additional-sources "Helpers/initialization-bug-extra-1.c" } */ + +// Do not test with optimization -- the error may be optimized away. + +#include + +// The structure of the test is: +// "x", "y", "z" are dynamically initialized globals. +// Value of "x" depends on "y", value of "y" depends on "z". +// "x" and "z" are defined in this TU, "y" is defined in another one. +// Thus we shoud stably report initialization order fiasco independently of +// the translation unit order. + +int initZ() { + return 5; +} +int z = initZ(); + +// 'y' is a dynamically initialized global residing in a different TU. This +// dynamic initializer will read the value of 'y' before main starts. The +// result is undefined behavior, which should be caught by initialization order +// checking. +extern int y; +int __attribute__((noinline)) initX() { + return y + 1; +} + +// This initializer begins our initialization order problems. +static int x = initX(); + +int main() { + // ASan should have caused an exit before main runs. + return 0; +} + +/* { dg-output "AddressSanitizer: initialization-order-fiasco.*(\n|\r\n|\r)" } */ +/* { dg-output "READ of size .* at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */ +/* { dg-output "0x\[0-9a-f\]+ is located 0 bytes inside of global variable .*(y|z).*(\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,22 @@ +/* { dg-do run } */ +/* { 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)" } */ + + 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,14 @@ +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +#include +int main(int argc, char **argv) { + char x[10]; + memset(x, 0, 10); + int res = x[argc * 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:8|\[?\]\[?\]:0)|\[(\]).*(\n|\r\n|\r)" } */ +/* { dg-output "Address 0x\[0-9a-f\]+ is\[^\n\r]*frame
" } */ Index: gcc/testsuite/c-c++-common/asan/blacklist-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/blacklist-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/blacklist-1.c (revision 0) @@ -0,0 +1,27 @@ +// Test the blacklist functionality of ASan + +/* { dg-do run } */ +/* { dg-additional-sources "Helpers/blacklist-extra-1.c" } */ + +// badGlobal is accessed improperly, but we blacklisted it. +int badGlobal; +int readBadGlobal() { + return (&badGlobal)[1]; +} + +// A function which is broken, but excluded in the blacklist. +int brokenFunction(int argc) { + char x[10] = {0}; + return x[argc * 10]; // BOOM +} + +// This function is defined in Helpers/blacklist-extra-1.c, a source file which +// is blacklisted by name +int externalBrokenFunction(int x); + +int main(int argc, char **argv) { + brokenFunction(argc); + int x = readBadGlobal(); + externalBrokenFunction(argc); + return 0; +} 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,21 @@ +/* { dg-do run } */ +/* { 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:8|\[?]\[?]: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:7|\[?]\[?]: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:6|\[?]\[?]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ 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/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:28|\[?\]\[?\]:)" } */ +/* { dg-output "is located in frame <\[^\n\r]*Func1\[^\n\r]*> of T0's stack" } */ + 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/linux/initialization-bug-any-order-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/linux/initialization-bug-any-order-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/linux/initialization-bug-any-order-1.c (revision 0) @@ -0,0 +1,38 @@ +// Test to make sure basic initialization order errors are caught. +// Check that on Linux initialization order bugs are caught +// independently on order in which we list source files. + +// Do not test with optimization -- the error may be optimized away. + +/* { dg-do run } */ +/* { options "-asan-initialization-order" } */ +/* { dg-shouldfail "asan" } */ + +#include + +int initZ() { + return 5; +} +int z = initZ(); + +// 'y' is a dynamically initialized global residing in a different TU. This +// dynamic initializer will read the value of 'y' before main starts. The +// result is undefined behavior, which should be caught by initialization order +// checking. +extern int y; +int __attribute__((noinline)) initX() { + return y + 1; +} + +// This initializer begins our initialization order problems. +static int x = initX(); + +int main() { + // ASan should have caused an exit before main runs. + return 0; +} + +/* { dg-output "AddressSanitizer initialization-order-fiasco\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "READ of size \[^\n\r]* at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in \[^\n\r]*initX\[^\n\r]*(initialization-bug-any-order-1.c:31|\[?\]\[?\]:)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "0x\[0-9a-f\]+ is located 0 bytes inside of global variable \[^\n\r]*y\[^\n\r]*" } */ Index: gcc/testsuite/c-c++-common/asan/linux/rlimit-mmap-test-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/linux/rlimit-mmap-test-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/linux/rlimit-mmap-test-1.c (revision 0) @@ -0,0 +1,21 @@ +// Check that we properly report mmap failure. +// RUN: %clangxx_asan %s -o %t && %t 2>&1 | FileCheck %s + +/* { dg-do run } */ +/* { 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/linux/swapcontext-test-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/linux/swapcontext-test-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/linux/swapcontext-test-1.c (revision 0) @@ -0,0 +1,61 @@ +// Check that ASan plays well with easy cases of makecontext/swapcontext. + +/* { dg-do run } */ + +#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/linux/clone-test-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/linux/clone-test-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/linux/clone-test-1.c (revision 0) @@ -0,0 +1,46 @@ +// Regression test for: +// http://code.google.com/p/address-sanitizer/issues/detail?id=37 + +/* { dg-do run } */ +/* { dg-options "-D_GNU_SOURCE" } */ +/* { 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/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,11 @@ +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +#include +int main() { + char *x = (char*)malloc(10 * sizeof(char)); + free(x); + return x[5]; +} + +/* { dg-output "Sleeping for 1 second" } */ Index: gcc/testsuite/c-c++-common/asan/Helpers/interface_symbols.sh =================================================================== --- gcc/testsuite/c-c++-common/asan/Helpers/interface_symbols.sh (revision 0) +++ gcc/testsuite/c-c++-common/asan/Helpers/interface_symbols.sh (revision 0) @@ -0,0 +1,16 @@ +nm $1 | egrep " [TW] " | sed "s/.* T //" | sed "s/.* W //" \ + | grep "__asan_" | sed "s/___asan_/__asan_/" > 1.t +cat $2 | sed "s/\/\/.*//" | sed "s/typedef.*//" \ +| grep "__asan_.*(" | sed "s/.* __asan_/__asan_/;s/(.*//" > 2.t +echo __asan_report_load1 >> 2.t +echo __asan_report_load2 >> 2.t +echo __asan_report_load4 >> 2.t +echo __asan_report_load8 >> 2.t +echo __asan_report_load16 >> 2.t +echo __asan_report_store1 >> 2.t +echo __asan_report_store2 >> 2.t +echo __asan_report_store4 >> 2.t +echo __asan_report_store8 >> 2.t +echo __asan_report_store16 >> 2.t +cat 2.t | sort -u | diff 1.t - +rm 1.t 2.t Property changes on: gcc/testsuite/c-c++-common/asan/Helpers/interface_symbols.sh ___________________________________________________________________ Added: svn:executable + * Index: gcc/testsuite/c-c++-common/asan/Helpers/initialization-bug-extra-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/Helpers/initialization-bug-extra-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/Helpers/initialization-bug-extra-1.c (revision 0) @@ -0,0 +1,6 @@ +// 'z' is dynamically initialized global from different TU. +extern int z; +int __attribute__((noinline)) initY() { + return z + 1; +} +int y = initY(); Index: gcc/testsuite/c-c++-common/asan/Helpers/blacklist-1.tmp =================================================================== --- gcc/testsuite/c-c++-common/asan/Helpers/blacklist-1.tmp (revision 0) +++ gcc/testsuite/c-c++-common/asan/Helpers/blacklist-1.tmp (revision 0) @@ -0,0 +1,3 @@ +fun:*brokenFunction* +global:*badGlobal* +src:*blacklist-extra-1.c Index: gcc/testsuite/c-c++-common/asan/Helpers/blacklist-extra-1.c =================================================================== --- gcc/testsuite/c-c++-common/asan/Helpers/blacklist-extra-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/Helpers/blacklist-extra-1.c (revision 0) @@ -0,0 +1,5 @@ +// This function is broken, but this file is blacklisted +int externalBrokenFunction(int argc) { + char x[10] = {0}; + return x[argc * 10]; // BOOM +}