This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] asan testsuite (take 3)


On Wed, Nov 14, 2012 at 2:59 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Wed, Nov 14, 2012 at 11:12:05AM -0800, Mike Stump wrote:
>> On Nov 14, 2012, at 8:22 AM, Jakub Jelinek <jakub@redhat.com> wrote:
>> > On Wed, Nov 14, 2012 at 12:11:13PM +0100, Jakub Jelinek wrote:
>> >> Anyway, once asan_symbolize actually symbolizes the output, we could use
>> >> something like:
>> >> /* { dg-output "ERROR: AddressSanitizer stack-buffer-overflow.*" } */
>> >> /* { dg-output "    #0 0x\[0-9a-f\]+ (in _*(interceptor_|)memcmp |\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
>> >> /* { dg-output "    #1 0x\[0-9a-f\]+ (in _*main|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
>> >> (this way it will check function names if symbolizer was actually
>> >> successful, and just accept #0 0xdeadbeef (foobarbaz.so+0xbeef) style
>> >> if it wasn't), but will not accept other function names in the backtrace.
>> >
>> > Here it is even with symbolizer, written in (poor) tcl.  It will pass even
>> > if e.g. addr2line is replaced by a script that always fails, but if it
>> > succeeds, will fail if the dg-output regexps contain different function name
>> > than what is actually emitted.
>> >
>> > Ok for trunk?
>>
>> Ok.  If others would like to improve thisâ  :-)  feel free to step forward.
>
> Thanks, here is what I've committed, had to add a TEST_ALWAYS_FLAG restore
> in asan_finish, otherwise C tests after asan.exp would run with
> -faddress-sanitizer -g in the flags.

All of these tests failure for me because my addr2line is too old and
does not support dwarf4.  Can we move over to using libbacktrace in
libsanitzer instead of depending on addr2line here?

==21154== ERROR: AddressSanitizer stack-buffer-overflow on address
0x7fff572cddd4 at pc 0x2b7549a5c550 bp 0x7fff572cdd80 sp
0x7fff572cdd48
READ of size 1 at 0x7fff572cddd4 thread T0
    #0 0x2b7549a5c54f in BFD: Dwarf Error: found dwarf version '4',
this reader only handles version 2 and 3 information. memcmp
    #1 0x400a59 in BFD: Dwarf Error: found dwarf version '4', this
reader only handles version 2 and 3 information. main
    #2 0x2b754c697c4c in __libc_start_main
/home/aurel32/eglibc/eglibc-2.11.2/csu/libc-start.c:228


Thanks,
Andrew

>
> 2012-11-14  Jakub Jelinek  <jakub@redhat.com>
>
>         * lib/asan-dg.exp: New file.
>         * gcc.dg/asan/asan.exp: New file.
>         * g++.dg/dg.exp: Prune also asan tests.
>         * g++.dg/asan/asan.exp: New file.
>         * c-c++-common/asan/memcmp-1.c: New test.
>
> --- gcc/testsuite/lib/asan-dg.exp.jj    2012-11-14 21:04:53.520943144 +0100
> +++ gcc/testsuite/lib/asan-dg.exp       2012-11-14 21:21:03.215801626 +0100
> @@ -0,0 +1,176 @@
> +# Copyright (C) 2012 Free Software Foundation, Inc.
> +
> +# This program 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 of the License, or
> +# (at your option) any later version.
> +#
> +# This program 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/>.
> +
> +# Return 1 if compilation with -faddress-sanitizer is error-free for trivial
> +# code, 0 otherwise.
> +
> +proc check_effective_target_faddress_sanitizer {} {
> +    return [check_no_compiler_messages faddress_sanitizer object {
> +       void foo (void) { }
> +    } "-faddress-sanitizer"]
> +}
> +
> +#
> +# asan_link_flags -- compute library path and flags to find libasan.
> +# (originally from g++.exp)
> +#
> +
> +proc asan_link_flags { paths } {
> +    global srcdir
> +    global ld_library_path
> +    global shlib_ext
> +
> +    set gccpath ${paths}
> +    set flags ""
> +
> +    set shlib_ext [get_shlib_extension]
> +
> +    if { $gccpath != "" } {
> +      if { [file exists "${gccpath}/libsanitizer/asan/.libs/libasan.a"]
> +          || [file exists "${gccpath}/libsanitizer/asan/.libs/libasan.${shlib_ext}"] } {
> +         append flags " -L${gccpath}/libsanitizer/asan/.libs "
> +         append ld_library_path ":${gccpath}/libsanitizer/asan/.libs"
> +      }
> +    } else {
> +      global tool_root_dir
> +
> +      set libasan [lookfor_file ${tool_root_dir} libasan]
> +      if { $libasan != "" } {
> +         append flags "-L${libasan} "
> +         append ld_library_path ":${libasan}"
> +      }
> +    }
> +
> +    set_ld_library_path_env_vars
> +
> +    return "$flags"
> +}
> +
> +#
> +# asan_init -- called at the start of each subdir of tests
> +#
> +
> +proc asan_init { args } {
> +    global TEST_ALWAYS_FLAGS
> +    global ALWAYS_CXXFLAGS
> +    global TOOL_OPTIONS
> +    global asan_saved_TEST_ALWAYS_FLAGS
> +
> +    set link_flags ""
> +    if ![is_remote host] {
> +       if [info exists TOOL_OPTIONS] {
> +           set link_flags "[asan_link_flags [get_multilibs ${TOOL_OPTIONS}]]"
> +       } else {
> +           set link_flags "[asan_link_flags [get_multilibs]]"
> +       }
> +    }
> +
> +    if [info exists TEST_ALWAYS_FLAGS] {
> +       set asan_saved_TEST_ALWAYS_FLAGS $TEST_ALWAYS_FLAGS
> +    }
> +    if [info exists ALWAYS_CXXFLAGS] {
> +       set ALWAYS_CXXFLAGS [concat "{ldflags=$link_flags}" $ALWAYS_CXXFLAGS]
> +       set ALWAYS_CXXFLAGS [concat "{additional_flags=-faddress-sanitizer -g}" $ALWAYS_CXXFLAGS]
> +    } else {
> +       if [info exists TEST_ALWAYS_FLAGS] {
> +           set TEST_ALWAYS_FLAGS "$link_flags -faddress-sanitizer -g $TEST_ALWAYS_FLAGS"
> +       } else {
> +           set TEST_ALWAYS_FLAGS "$link_flags -faddress-sanitizer -g"
> +       }
> +    }
> +}
> +
> +#
> +# asan_finish -- called at the start of each subdir of tests
> +#
> +
> +proc asan_finish { args } {
> +    global TEST_ALWAYS_FLAGS
> +    global asan_saved_TEST_ALWAYS_FLAGS
> +
> +    if [info exists asan_saved_TEST_ALWAYS_FLAGS] {
> +       set TEST_ALWAYS_FLAGS $asan_saved_TEST_ALWAYS_FLAGS
> +    } else {
> +       unset TEST_ALWAYS_FLAGS
> +    }
> +}
> +
> +# Symbolize lines like
> +#   #2 0xdeadbeef (/some/path/libsanitizer.so.0.0.0+0xbeef)
> +# in $output using addr2line to
> +#   #2 0xdeadbeef in foobar file:123
> +proc asan_symbolize { output } {
> +    set addresses [regexp -inline -all -line "^ *#\[0-9\]+ 0x\[0-9a-f\]+ \[(\](\[^)\]+)\[+\](0x\[0-9a-f\]+)\[)\]$" "$output"]
> +    if { [llength $addresses] > 0 } {
> +       set addr2line_name [find_binutils_prog addr2line]
> +       set idx 1
> +       while { $idx < [llength $addresses] } {
> +           set key [lindex $addresses $idx]
> +           set val [lindex $addresses [expr $idx + 1]]
> +           lappend arr($key) $val
> +           set idx [expr $idx + 3]
> +       }
> +       foreach key [array names arr] {
> +           set args "-f -e $key $arr($key)"
> +           set status [remote_exec host "$addr2line_name" $args]
> +           if { [lindex $status 0] > 0 } continue
> +           set addr2line_output [regexp -inline -all -line "^\[^\n\r]*" [lindex $status 1]]
> +           set idx 0
> +           foreach val $arr($key) {
> +               if { [expr $idx + 1] < [llength $addr2line_output] } {
> +                   set fnname [lindex $addr2line_output $idx]
> +                   set fileline [lindex $addr2line_output [expr $idx + 1]]
> +                   if { "$fnname" != "??" } {
> +                       set newkey "$key+$val"
> +                       set repl($newkey) "$fnname $fileline"
> +                   }
> +               }
> +           }
> +       }
> +       set idx 0
> +       set new_output ""
> +       while {[regexp -start $idx -indices " #\[0-9\]+ 0x\[0-9a-f\]+ \[(\](\[^)\]+\[+\]0x\[0-9a-f\]+)\[)\]" "$output" -> addr] > 0} {
> +           set low [lindex $addr 0]
> +           set high [lindex $addr 1]
> +           set val [string range "$output" $low $high]
> +           append new_output [string range "$output" $idx [expr $low - 2]]
> +           if [info exists repl($val)] {
> +               append new_output "in $repl($val)"
> +           } else {
> +               append new_output "($val)"
> +           }
> +           set idx [expr $high + 2]
> +       }
> +       append new_output [string range "$output" $idx [string length "$output"]]
> +       return "$new_output"
> +    }
> +    return "$output"
> +}
> +
> +# Replace ${tool}_load with a wrapper so that we can symbolize the output.
> +if { [info procs ${tool}_load] != [list] \
> +      && [info procs saved_asan_${tool}_load] == [list] } {
> +    rename ${tool}_load saved_asan_${tool}_load
> +
> +    proc ${tool}_load { program args } {
> +       global tool
> +       set result [eval [list saved_asan_${tool}_load $program] $args]
> +       set output [lindex $result 1]
> +       set symbolized_output [asan_symbolize "$output"]
> +       set result [list [lindex $result 0] $symbolized_output]
> +       return $result
> +    }
> +}
> --- gcc/testsuite/gcc.dg/asan/asan.exp.jj       2012-11-14 21:04:53.520943144 +0100
> +++ gcc/testsuite/gcc.dg/asan/asan.exp  2012-11-14 21:07:25.213157962 +0100
> @@ -0,0 +1,38 @@
> +# 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/>.
> +
> +# GCC testsuite that uses the `dg.exp' driver.
> +
> +# Load support procs.
> +load_lib gcc-dg.exp
> +load_lib asan-dg.exp
> +
> +if ![check_effective_target_faddress_sanitizer] {
> +  return
> +}
> +
> +# Initialize `dg'.
> +dg-init
> +asan_init
> +
> +# Main loop.
> +gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c $srcdir/c-c++-common/asan/*.c]] ""
> +
> +# All done.
> +asan_finish
> +dg-finish
> --- gcc/testsuite/g++.dg/dg.exp.jj      2012-11-14 20:26:35.460378708 +0100
> +++ gcc/testsuite/g++.dg/dg.exp 2012-11-14 21:04:53.520943144 +0100
> @@ -1,4 +1,5 @@
> -#   Copyright (C) 2000, 2007, 2009, 2010 Free Software Foundation, Inc.
> +#   Copyright (C) 2000, 2007, 2009, 2010, 2011, 2012
> +#   Free Software Foundation, Inc.
>
>  # This program is free software; you can redistribute it and/or modify
>  # it under the terms of the GNU General Public License as published by
> @@ -50,6 +51,7 @@ set tests [prune $tests $srcdir/$subdir/
>  set tests [prune $tests $srcdir/$subdir/tm/*]
>  set tests [prune $tests $srcdir/$subdir/guality/*]
>  set tests [prune $tests $srcdir/$subdir/simulate-thread/*]
> +set tests [prune $tests $srcdir/$subdir/asan/*]
>
>  # Main loop.
>  g++-dg-runtest $tests $DEFAULT_CXXFLAGS
> --- gcc/testsuite/g++.dg/asan/asan.exp.jj       2012-11-14 21:04:53.520943144 +0100
> +++ gcc/testsuite/g++.dg/asan/asan.exp  2012-11-14 21:07:35.967092385 +0100
> @@ -0,0 +1,36 @@
> +# 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/>.
> +
> +# Load support procs.
> +load_lib g++-dg.exp
> +load_lib asan-dg.exp
> +
> +if ![check_effective_target_faddress_sanitizer] {
> +  return
> +}
> +
> +# Initialize `dg'.
> +dg-init
> +asan_init
> +
> +# Main loop.
> +gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C $srcdir/c-c++-common/asan/*.c]] ""
> +
> +# All done.
> +asan_finish
> +dg-finish
> --- gcc/testsuite/c-c++-common/asan/memcmp-1.c.jj       2012-11-14 21:04:53.521943120 +0100
> +++ gcc/testsuite/c-c++-common/asan/memcmp-1.c  2012-11-14 21:04:53.521943120 +0100
> @@ -0,0 +1,18 @@
> +/* { dg-do run } */
> +/* { dg-options "-fno-builtin-memcmp" } */
> +/* { dg-shouldfail "asan" } */
> +
> +#include <string.h>
> +
> +int
> +main (int argc, char **argv)
> +{
> +  char a1[] = {argc, 2, 3, 4};
> +  char a2[] = {1, 2*argc, 3, 4};
> +  int res = memcmp (a1, a2, 5 + argc);
> +  return res;
> +}
> +
> +/* { dg-output "ERROR: AddressSanitizer stack-buffer-overflow.*(\n|\r\n|\r)" } */
> +/* { dg-output "    #0 0x\[0-9a-f\]+ (in _*(interceptor_|)memcmp |\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> +/* { dg-output "    #1 0x\[0-9a-f\]+ (in _*main|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
>
>
>         Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]