From: Wei Mi <wmi@google.com>
To: Jakub Jelinek <jakub@redhat.com>
Cc: Mike Stump <mikestump@comcast.net>,
GCC Patches <gcc-patches@gcc.gnu.org>,
David Li <davidxl@google.com>,
Diego Novillo <dnovillo@google.com>,
Kostya Serebryany <kcc@google.com>,
Dodji Seketeli <dseketel@redhat.com>
Subject: Re: [PATCH] asan unit tests from llvm lit-test
Date: Tue, 04 Dec 2012 18:01:00 -0000 [thread overview]
Message-ID: <CA+4CFy43TjO_G=ZmvNTLUbOZCAMYm4Zq2q+jxTh=NtKNTHD1PQ@mail.gmail.com> (raw)
In-Reply-To: <20121203110018.GR2315@tucnak.redhat.com>
[-- Attachment #1: Type: text/plain, Size: 34695 bytes --]
Hi,
I updated the patch according to the comments. Please take a look. Thanks.
Wei.
> On Fri, Nov 30, 2012 at 12:35:35PM -0800, Wei Mi wrote:
>> 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))).
>
>> --- 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
>
> Why this? What is undesirable on the default torture options?
> Do those tests fail with lto or similar?
I change it to use the default torture options.
>
>> --- 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" }
>
> Can you please replace the two spaces after // with just one?
> Dejagnu directives are often quite long, and thus it is IMHO better to make
> the lines longer than necessary.
> For this test, don't you need
> // { dg-options "-fno-optimize-sibling-calls" }
> and __attribute__((noinline)) on the free method? Otherwise I'd expect
> that either at least at -O3 it could be all inlined, or if not inlined, then
> at least tail call optimized (and thus not showing up in the backtrace
> either).
>
Fixed.
>> +#include <stdlib.h>
>> +#include <stdio.h>
>> +
>> +template <int depth>
>> +struct DeepFree {
>> + static void free(char *x) {
>> + DeepFree<depth - 1>::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)" }
>
>> --- 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" }
>
> -mno-omit-leaf-frame-pointer is i?86/x86_64 options, so you need to leave it
> from dg-options and add
> // { dg-additional-options "-mno-omit-leaf-frame-pointer" { target { i?86-*-* x86_64-*-* } } }
>
Fixed.
>> --- 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
>
> Again, like I asked earlier.
Fixed.
>
>> +
>> # Main loop.
>> gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C $srcdir/c-c++-common/asan/*.c]] ""
>>
>> +source $srcdir/$subdir/special/special.exp
>
> Won't this cause double testing of the special tests? AFAIK dejagnu is
> looking recursively for all *.exp files, so once you'd source it when
> running asan.exp and again when dejagnu finds special.exp on its own.
> If that is the case, then you shouldn't source it here, and rename
> special.exp to say asan-special.exp, so that one can test all asan
> tests with just RUNTESTFLAGS="--target_board=unix\{-m32,-m64\} asan.exp asan-special.exp"
> but also make check will DTRT. Or perhaps name it also asan.exp, see if
> RUNTESTFLAGS="--target_board=unix\{-m32,-m64\} asan.exp"
> then will DTRT and also make check?
>
Yes, it will cause double tests in make check.
I rename special.exp to asan-special.exp and don't source it from asan.exp.
>> --- 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 <stdlib.h>
>> +#include <stdio.h>
>> +
>> +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));
>
> Ugh, why the * sizeof(char)? That is completely pointless...
>
Fixed.
>> --- 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 <stdlib.h>
>> +__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)
>
> Name it dlclose-test-1.so.cc instead?
Fixed.
>
>> +// { dg-skip-if "" { *-*-* } { "*" } { "" } }
>
>> --- 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" }
>
> My preference would be // { dg-do run { target { dlopen && mmap } } }
> In any case, no need for "s around the dlopen/mmap/pthread etc.
Fixed.
>> +
>> +#include <assert.h>
>> +#include <dlfcn.h>
>> +#include <stdio.h>
>> +#include <string.h>
>> +#include <sys/mman.h>
>> +
>> +#include <string>
>> +
>> +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" }
>
> Isn't printf("PASS\n"); and dg-output completely unnecessary here?
> If the test doesn't reach the return 0, the test will fail (the canonical
> way of failing is abort ();, but for asan I agree it is better to exit with
> non-zero status, because the asan multi-terrabyte mappings cause slowdowns
> e.g. with abrt or if cores are enabled) the execution test part, if it
> reaches there, it will pass the execution test, by testing dg-output you
> are adding another dejagnu accounted test (another pass/fail/unsupported
> item), but it tests exactly what has been tested before already.
Fixed.
>> 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 <dlfcn.h>
>> +#include <stdio.h>
>> +#include <string.h>
>> +
>> +#include <string>
>> +
>> +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
>> +# <http://www.gnu.org/licenses/>.
>> +
>> +# 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
>
> I'm missing hre cleaning up of the created shared libraries, are you sure
> they aren't kept in the g++/testsuite/g++/ directory after make check?
>
> Plus, if this *.exp file is renamed to asan.exp or asan-special.exp and
> not sourced in from the upper directory asan.exp, it needs to start/end with
> what asan.exp does.
>
Fixed.
>> +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
>
> Ah, it is here, but wonder what it will do for cross testing.
> Shouldn't that be remove_file ? delete where ? is either target, or host, or
> build (not sure which one). Mike?
>
Changed to remove-build-file.
>> --- 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)
>
> Again, *-so.cc ?
>
Fixed.
>> +// { dg-skip-if "" { *-*-* } { "*" } { "" } }
>
>> --- 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]
>
> For this, I'd appreciate Mike's input. If it is useful for all tests
> generally (I'd say it is, we could use it e.g. for testing some of the
> libgomp env vars), then it should stay here or so, otherwise it would need
> to be moved into asan-dg.exp and have asan in the name.
>
> More importantly, I'm wondering about dg-env-var vs. cross testing, I guess
> env var is set on host only, not remotely set on the target. So, either
> we should mark all tests that use dg-env-var with some special effective
> target that would be basically [is_native] - or what is the way to limit
> tests to native testing only, or dg-evn-var itself should arrange to just
> make the whole test unsupported if not native (don't call ${tool}_load
> at all and return something else?).
>
rename dg-env-var to dg-set-target-env-var. Add the following in ${tool}_load:
if { [llength $set_target_env_var] != 0 } {
if { [is_remote target] } {
return [list "unsupported" ""]
}
set-target-env-var
}
set result [eval [list saved_${tool}_load $program] $args]
if { [llength $set_target_env_var] != 0 } {
restore-target-env-var
}
>> 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" } } */
>
> The -m64 here is just wrong. If you want to run the test only
> for -O2 and x86_64-linux compilation (why?, what is so specific
> about it to that combination?), then you'd do
> /* { dg-do run { target { { i?86-*-* x86_64-*-* } && lp64 } } } */
> /* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
> or so. But again, why?
>
Fixed. remove -m64.
>> +/* { dg-env-var ASAN_OPTIONS "strip_path_prefix='/'" } */
>> +/* { dg-shouldfail "asan" } */
>> +
>> +#include <stdlib.h>
>> +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)" } */
>
>> --- 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" } } */
>
> As I said above. Why is this not tested for 32-bit testing?
> From the name, -O0/-O1 limit could make sense, but then even for -O2 and
> above it should do the same.
>
Fixed. remove -m64.
>> +__attribute__((always_inline))
>
> Please drop -Wno-attributes above, and instead DTRT, i.e.
> together with __attribute__((always_inline)) always use also inline keyword.
> always_inline attribute alone is invalid on functions not marked as inline.
>
remove -Wno-attributes. add inline keyword.
>> +void foo(int *x) {
>> + *x = 0;
>> +}
>> +
>> +int main() {
>> + int x;
>> + foo(&x);
>> + return x;
>> +}
>
> But of course, the test actually doesn't test anything at all, there is
> no check for it not being instrumented twice, you'd use
> dg-do compile test for it instead, and test assembly in dg-final or similar.
> Except that there are no memory accesses at all, at least for -O1
> by the time this reaches the asan pass I'm pretty sure it will be just
> int main() { return 0; }
> (perhaps with DEBUG x => 0 for -g).
> Then it will be very dependent on whether the foo function is emitted
> or not (which depends on C vs. C++ and for C on 89 vs 99 vs.
> -fgnu89-inline). So, for -O1 main won't contain any instrumented accesses,
> and foo either won't be emitted at all, or will contain one store.
> For -O0 for main it will contain one insturmented store, and for foo the
> same as for -O1. So you could
> /* { dg-final { scan-assembler-not "__asan_report_load" } } */
>
Added dg-do compile and dg-final.
>> 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 <stdio.h>
>> +#include <ucontext.h>
>> +#include <unistd.h>
>> +
>> +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))
>
> For GCC you need
> __attribute__((noinline, noclone))
> here, otherwise GCC could very well clone the function to
> NullDeref.isra.0 or similar, taking no arguments and doing
> the NULL dereference or __builtin_unreachable directly.
>
Fixed.
>> +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 <string.h>
>> +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 */
>
> I'd expect the compiler could eventually be smart enough to figure
> out the only valid access of YYY[something * 10] would be if something
> is 0 and thus optimize (one would be read before and forgotten) the
> access to YYY[0]. I'd write the test instead with volatile int ten = 10;
> and s/one/ten/g plus YYY[ten]; and XXX[ten / 10]; and similarly for ZZZ.
>
Fixed.
>> + res += XXX[one] + ZZZ[one];
>> + return res;
>
>> --- 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 <string.h>
>> +#include <stdlib.h>
>> +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" } } */
>
> Again, what is 64-bit specific on this test? If you want to run
> it just once, not iterate over all torture options, just do
> /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
>
Fixed.
>> +/* { dg-require-effective-target "setrlimit" } */
>> +/* { dg-shouldfail "asan" } */
>> +
>> +#include <stdlib.h>
>> +#include <assert.h>
>> +#include <sys/time.h>
>> +#include <sys/resource.h>
>> +
>> +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));
>
> Assert is too expensive with asan (see above).
> Just do
> if (setrlimit(RLIMIT_AS, &mmap_resource_limit)) return 1;
>
> return 0; wouldn't help here, as the output test would then fail.
>
>
Fixed.
>> --- 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 <stdlib.h>
>> +int main() {
>> + char *x = (char*)malloc(10 * sizeof(char));
>
> Again, why the sizeof(char)? It is always 1.
>
Fixed.
>> + 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 <stdio.h>
>> +
>> +__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" } */
>
> Doesn't this test in LLVM start with
> // XFAIL: *
> ? It does need the (for LLVM non-default?, for GCC not implemented yet)
> expensive use-after-return mode where all stack vars are malloced/freed,
> right?
> So, I'd just /* { dg-do run { xfail *-*-* } } */ it for now or not add at
> all.
>
I removed the test for now.
>> --- 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 } */
>
> -fno-builtin-malloc at least to dg-options?
>
Fixed.
>> +/* { dg-shouldfail "asan" } */
>> +
>> +#include <stdlib.h>
>> +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 } */
>
> Please use /* { dg-do run { target *-*-linux* } } */ above too.
> The test is really very Linux specific.
>
Fixed.
>> --- 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 <stdlib.h>
>> +#include <string.h>
>> +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;
>> +}
>
> What has been said earlier about argc used in tests...
> Plus -fno-builtin-malloc (and add -fno-builtin-free to all uses
> of -fno-builtin-malloc too for all tests).
>
Fixed.
>> --- 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" } } */
>
> As has been said several times. Fine to do it at one torture
> option instead of iterating, but don't limit that to -m64 (and if yes, not
> this way). Plus again dg-options -fno-builtin-malloc -fno-builtin-free.
Fixed.
>
> Jakub
[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 30295 bytes --]
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,21 @@
+// { dg-do run }
+// { dg-skip-if "" { *-*-* } { "*" } { "-O2" } }
+// { dg-options "-fno-builtin-malloc -fno-builtin-free" }
+// { dg-shouldfail "asan" }
+
+#include <stdio.h>
+#include <stdlib.h>
+
+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/shared-lib-test-1-so.cc
===================================================================
--- gcc/testsuite/g++.dg/asan/shared-lib-test-1-so.cc (revision 0)
+++ gcc/testsuite/g++.dg/asan/shared-lib-test-1-so.cc (revision 0)
@@ -0,0 +1,20 @@
+//===----------- 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.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+
+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/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,21 @@
+// { dg-do run }
+// { dg-options "-fno-omit-frame-pointer -fno-optimize-sibling-calls" }
+// { dg-additional-options "-mno-omit-leaf-frame-pointer" { target { i?86-*-* x86_64-*-* } } }
+// { dg-shouldfail "asan" }
+
+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/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,23 @@
+// ASan interceptor can be accessed with __interceptor_ prefix.
+
+// { dg-do run }
+// { dg-options "-fno-builtin-malloc -fno-builtin-free" }
+// { dg-shouldfail "asan" }
+
+#include <stdlib.h>
+#include <stdio.h>
+
+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);
+ 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/dlclose-test-1-so.cc
===================================================================
--- gcc/testsuite/g++.dg/asan/dlclose-test-1-so.cc (revision 0)
+++ gcc/testsuite/g++.dg/asan/dlclose-test-1-so.cc (revision 0)
@@ -0,0 +1,32 @@
+//===----------- 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
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+
+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/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 { target pthread } }
+// { dg-shouldfail "asan" }
+
+#include <pthread.h>
+
+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-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,24 @@
+// ASan interceptor can be accessed with __interceptor_ prefix.
+
+// { dg-do run }
+// { dg-options "-fno-builtin-free" }
+// { dg-shouldfail "asan" }
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+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/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,38 @@
+// Check that we can store lots of stack frames if asked to.
+
+// { dg-do run }
+// { dg-set-target-env-var ASAN_OPTIONS "malloc_context_size=120:redzone=512" }
+// { dg-options "-fno-omit-frame-pointer -fno-optimize-sibling-calls" }
+// { dg-additional-options "-mno-omit-leaf-frame-pointer" { target { i?86-*-* x86_64-*-* } } }
+// { dg-shouldfail "asan" }
+
+#include <stdlib.h>
+#include <stdio.h>
+
+template <int depth>
+struct DeepFree {
+ static void __attribute__((noinline))
+ free(char *x) {
+ DeepFree<depth - 1>::free(x);
+ }
+};
+
+template<>
+struct DeepFree<0> {
+ static void __attribute__((noinline))
+ 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/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 <stdlib.h>
+__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/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,22 @@
+// If user provides his own libc functions, ASan doesn't
+// intercept these functions.
+
+// { dg-do run }
+// { dg-options "-fno-builtin-malloc -fno-builtin-free" }
+
+#include <stdlib.h>
+#include <stdio.h>
+
+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/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,15 @@
+/* { dg-do run } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
+/* { dg-set-target-env-var ASAN_OPTIONS "strip_path_prefix='/'" } */
+/* { dg-options "-fno-builtin-malloc -fno-builtin-free" } */
+/* { dg-shouldfail "asan" } */
+
+#include <stdlib.h>
+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,17 @@
+/* This test checks that we are no instrumenting a memory access twice
+ (before and after inlining) */
+
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" "-O1" } } */
+/* { dg-final { scan-assembler-not "__asan_report_load" } } */
+
+__attribute__((always_inline))
+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,61 @@
+/* Check that ASan plays well with easy cases of makecontext/swapcontext. */
+
+/* { dg-do run { target swapcontext } } */
+
+#include <stdio.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+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, noclone))
+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 <string.h>
+volatile int ten = 10;
+
+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[ten]; /* BOOOM */
+ res += XXX[ten/10] + ZZZ[ten/10];
+ 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-malloc -fno-builtin-strncpy" } */
+/* { dg-shouldfail "asan" } */
+
+#include <string.h>
+#include <stdlib.h>
+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,21 @@
+/* Check that we properly report mmap failure. */
+
+/* { dg-do run { target setrlimit } } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
+/* { dg-shouldfail "asan" } */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+static volatile void *x;
+
+int main(int argc, char **argv) {
+ struct rlimit mmap_resource_limit = { 0, 0 };
+ if (setrlimit(RLIMIT_AS, &mmap_resource_limit)) return 1;
+ 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,18 @@
+/* { dg-do run } */
+/* { dg-options "-fno-builtin-memset" } */
+/* { dg-shouldfail "asan" } */
+
+volatile int ten = 10;
+
+#include <string.h>
+
+int main() {
+ char x[10];
+ memset(x, 0, 10);
+ int res = x[ten]; /* 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:12|\[?\]\[?\]:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "Address 0x\[0-9a-f\]+ is\[^\n\r]*frame <main>" } */
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 -fno-builtin-free" } */
+/* { dg-shouldfail "asan" } */
+
+#include <stdlib.h>
+int main() {
+ char *x = (char*)malloc(10);
+ 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/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,17 @@
+/* { dg-do run } */
+/* { dg-options "-fno-builtin-malloc -fno-builtin-free" } */
+/* { dg-shouldfail "asan" } */
+
+#include <stdlib.h>
+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:8|\[?\]\[?\]:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output " #0 \[^\n\r]*(interceptor_|)malloc\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #1 \[^\n\r]*(in main\[^\n\r]*(sanity-check-pure-c-1.c:7|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+
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 { target { *-*-linux* } } } */
+/* { dg-require-effective-target clone } */
+/* { dg-options "-D_GNU_SOURCE" } */
+/* { dg-shouldfail "asan" } */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sched.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+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,21 @@
+/* { dg-do run } */
+/* { dg-options "-fno-builtin-malloc -fno-builtin-free -fno-builtin-memset" } */
+/* { dg-shouldfail "asan" } */
+
+#include <stdlib.h>
+#include <string.h>
+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:10|\[?\]\[?\]:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ (in .*malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main .*(heap-overflow-1.c:8|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+
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,14 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var ASAN_OPTIONS "sleep_before_dying=1" } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
+/* { dg-options "-fno-builtin-malloc -fno-builtin-free" } */
+/* { dg-shouldfail "asan" } */
+
+#include <stdlib.h>
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return x[5];
+}
+
+/* { dg-output "Sleeping for 1 second" } */
Index: gcc/testsuite/lib/target-supports.exp
===================================================================
--- gcc/testsuite/lib/target-supports.exp (revision 194156)
+++ 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 194156)
+++ gcc/testsuite/lib/gcc-dg.exp (working copy)
@@ -254,7 +254,19 @@ if { [info procs ${tool}_load] != [list]
proc ${tool}_load { program args } {
global tool
global shouldfail
+ global set_target_env_var
+
+ set saved_target_env_var [list]
+ if { [llength $set_target_env_var] != 0 } {
+ if { [is_remote target] } {
+ return [list "unsupported" ""]
+ }
+ set-target-env-var
+ }
set result [eval [list saved_${tool}_load $program] $args]
+ if { [llength $set_target_env_var] != 0 } {
+ restore-target-env-var
+ }
if { $shouldfail != 0 } {
switch [lindex $result 0] {
"pass" { set status "fail" }
@@ -266,6 +278,37 @@ if { [info procs ${tool}_load] != [list]
}
}
+proc dg-set-target-env-var { args } {
+ global set_target_env_var
+ if { [llength $args] != 3 } {
+ error "[lindex $args 1]: need two arguments"
+ return
+ }
+ lappend set_target_env_var [list [lindex $args 1] [lindex $args 2]]
+}
+
+proc set-target-env-var { } {
+ global set_target_env_var
+ upvar 1 saved_target_env_var saved_target_env_var
+ foreach env_var $set_target_env_var {
+ set var [lindex $env_var 0]
+ set value [lindex $env_var 1]
+ if [info exists env($var)] {
+ lappend saved_target_env_var [list $var $env($var)]
+ }
+ setenv $var $value
+ }
+}
+
+proc restore-target-env-var { } {
+ upvar 1 saved_target_env_var saved_target_env_var
+ foreach env_var $saved_target_env_var {
+ set var [lindex $env_var 0]
+ set value [lindex $env_var 1]
+ unsetenv $var $value
+ }
+}
+
# Utility routines.
#
@@ -287,6 +330,10 @@ proc search_for { file pattern } {
# as c-torture does.
proc gcc-dg-runtest { testcases default-extra-flags } {
global runtests
+ global set_target_env_var
+
+ # Init set_target_env_var
+ set set_target_env_var [list]
# Some callers set torture options themselves; don't override those.
set existing_torture_options [torture-options-exist]
next prev parent reply other threads:[~2012-12-04 18:01 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-11-28 9:15 Wei Mi
2012-11-28 10:10 ` Konstantin Serebryany
2012-11-28 10:25 ` Jakub Jelinek
2012-11-28 10:41 ` Konstantin Serebryany
2012-11-28 11:03 ` Jakub Jelinek
2012-11-28 11:14 ` Konstantin Serebryany
2012-11-29 20:59 ` [PATCH] asan_test.cc from llvm Jakub Jelinek
2012-11-30 9:35 ` Konstantin Serebryany
2012-11-30 10:22 ` Jakub Jelinek
2012-11-30 10:55 ` Konstantin Serebryany
2012-11-30 14:52 ` Jakub Jelinek
2012-11-30 16:06 ` Jakub Jelinek
[not found] ` <CAKOQZ8y70goUL91pQJt_S=8W+Dn5VTZ5oRphvGuFwMMh41mkLg@mail.gmail.com>
2012-11-30 16:34 ` Jakub Jelinek
2012-12-03 7:07 ` Konstantin Serebryany
2012-12-03 9:18 ` Jakub Jelinek
2012-12-03 9:52 ` Konstantin Serebryany
2012-12-03 11:05 ` Jakub Jelinek
2012-12-03 11:42 ` Konstantin Serebryany
2012-11-28 11:25 ` [PATCH] asan unit tests from llvm lit-test Jakub Jelinek
2012-11-28 11:39 ` Konstantin Serebryany
2012-11-28 10:14 ` Jakub Jelinek
2012-11-30 21:05 ` Wei Mi
2012-12-03 7:16 ` Konstantin Serebryany
2012-12-03 11:01 ` Jakub Jelinek
2012-12-03 18:33 ` Wei Mi
2012-12-03 18:49 ` Konstantin Serebryany
2012-12-03 19:44 ` Jakub Jelinek
2012-12-03 19:09 ` Mike Stump
2012-12-03 19:37 ` Jakub Jelinek
2012-12-03 19:50 ` Mike Stump
[not found] ` <CAN=P9pgjjq66KS2DVkuOSeH2ejQPDcyKhwz5MdKyE3RB64E=xw@mail.gmail.com>
2012-12-04 7:34 ` Jakub Jelinek
2012-12-04 18:01 ` Wei Mi [this message]
2012-12-05 12:29 ` [PATCH] asan unit tests from llvm lit-test incremental changes Jakub Jelinek
2012-12-12 21:32 ` Dodji Seketeli
2012-12-12 21:31 ` Jakub Jelinek
2012-12-13 7:44 ` Konstantin Serebryany
2012-12-13 8:37 ` Jakub Jelinek
2012-12-13 10:23 ` Konstantin Serebryany
2012-12-13 15:22 ` Jakub Jelinek
2012-12-05 23:29 ` [asan] Fix up dg-set-target-env-var Jakub Jelinek
2012-12-06 0:23 ` Mike Stump
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CA+4CFy43TjO_G=ZmvNTLUbOZCAMYm4Zq2q+jxTh=NtKNTHD1PQ@mail.gmail.com' \
--to=wmi@google.com \
--cc=davidxl@google.com \
--cc=dnovillo@google.com \
--cc=dseketel@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jakub@redhat.com \
--cc=kcc@google.com \
--cc=mikestump@comcast.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).