Commit bdea98ca by Max Ostapenko Committed by Maxim Ostapenko

Don't inline GCC memory builtins if ASan is enabled.

gcc/

2014-10-28  Max Ostapenko  <m.ostapenko@partner.samsung.com>

        * asan.h (asan_intercepted_p): New function.
        * asan.c (asan_mem_ref_hasher::hash): Remove MEM_REF access size from
        hash value construction.  Call iterative_hash_expr instead of explicit
        hash building.
        (asan_mem_ref_hasher::equal): Change condition.
        (has_mem_ref_been_instrumented): Likewise.
        (update_mem_ref_hash_table): Likewise.
        (maybe_update_mem_ref_hash_table): New function.
        (instrument_strlen_call): Removed.
        (get_mem_refs_of_builtin_call): Handle new parameter.
        (instrument_builtin_call): Call maybe_update_mem_ref_hash_table instead
        of instrument_mem_region_access if intercepted_p is true.
        (instrument_mem_region_access): Instrument only base with len instead of
        base and end with 1.
        (build_check_stmt): Remove start_instrumented and end_instrumented
        parameters.
        (enum asan_check_flags): Remove ASAN_CHECK_START_INSTRUMENTED and
        ASAN_CHECK_END_INSTRUMENTED.  Change ASAN_CHECK_LAST.
        (asan_expand_check_ifn): Remove start_instrumented and end_instrumented.
        * builtins.c (expand_builtin): Include asan.h.  Don't expand string/memory
        builtin functions that have interceptors if ASan is enabled.

gcc/testsuite/

        * c-c++-common/asan/no-redundant-instrumentation-1.c: Updated test.
        * c-c++-common/asan/no-redundant-instrumentation-4.c: Likewise.
        * c-c++-common/asan/no-redundant-instrumentation-5.c: Likewise.
        * c-c++-common/asan/no-redundant-instrumentation-6.c: Likewise.
        * c-c++-common/asan/no-redundant-instrumentation-7.c: Likewise.
        * c-c++-common/asan/no-redundant-instrumentation-8.c: Likewise.
        * c-c++-common/asan/no-redundant-instrumentation-2.c: Removed.
        * c-c++-common/asan/no-redundant-instrumentation-9.c: Likewise.
        * c-c++-common/asan/no-redundant-instrumentation-10.c: New test.
        * c-c++-common/asan/no-redundant-instrumentation-11.c: Likewise.
        * c-c++-common/asan/no-redundant-instrumentation-12.c: Likewise.
        * c-c++-common/asan/no-redundant-instrumentation-13.c: Likewise.
        * c-c++-common/asan/no-redundant-instrumentation-14.c: Likewise.
        * c-c++-common/asan/no-redundant-instrumentation-15.c: Likewise.
        * c-c++-common/asan/pr63638.c: Likewise.

From-SVN: r216783
parent 9ccaac11
2014-10-28 Max Ostapenko <m.ostapenko@partner.samsung.com>
* asan.h (asan_intercepted_p): New function.
* asan.c (asan_mem_ref_hasher::hash): Remove MEM_REF access size from
hash value construction. Call iterative_hash_expr instead of explicit
hash building.
(asan_mem_ref_hasher::equal): Change condition.
(has_mem_ref_been_instrumented): Likewise.
(update_mem_ref_hash_table): Likewise.
(maybe_update_mem_ref_hash_table): New function.
(instrument_strlen_call): Removed.
(get_mem_refs_of_builtin_call): Handle new parameter.
(instrument_builtin_call): Call maybe_update_mem_ref_hash_table instead
of instrument_mem_region_access if intercepted_p is true.
(instrument_mem_region_access): Instrument only base with len instead of
base and end with 1.
(build_check_stmt): Remove start_instrumented and end_instrumented
parameters.
(enum asan_check_flags): Remove ASAN_CHECK_START_INSTRUMENTED and
ASAN_CHECK_END_INSTRUMENTED. Change ASAN_CHECK_LAST.
(asan_expand_check_ifn): Remove start_instrumented and end_instrumented.
* builtins.c (expand_builtin): Include asan.h. Don't expand string/memory
builtin functions that have interceptors if ASan is enabled.
2014-10-28 Richard Biener <rguenther@suse.de>
PR middle-end/63665
......@@ -78,4 +78,28 @@ asan_red_zone_size (unsigned int size)
extern bool set_asan_shadow_offset (const char *);
/* Return TRUE if builtin with given FCODE will be intercepted by
libasan. */
static inline bool
asan_intercepted_p (enum built_in_function fcode)
{
return fcode == BUILT_IN_INDEX
|| fcode == BUILT_IN_MEMCHR
|| fcode == BUILT_IN_MEMCMP
|| fcode == BUILT_IN_MEMCPY
|| fcode == BUILT_IN_MEMMOVE
|| fcode == BUILT_IN_MEMSET
|| fcode == BUILT_IN_STRCASECMP
|| fcode == BUILT_IN_STRCAT
|| fcode == BUILT_IN_STRCHR
|| fcode == BUILT_IN_STRCMP
|| fcode == BUILT_IN_STRCPY
|| fcode == BUILT_IN_STRDUP
|| fcode == BUILT_IN_STRLEN
|| fcode == BUILT_IN_STRNCASECMP
|| fcode == BUILT_IN_STRNCAT
|| fcode == BUILT_IN_STRNCMP
|| fcode == BUILT_IN_STRNCPY;
}
#endif /* TREE_ASAN */
......@@ -62,6 +62,7 @@ along with GCC; see the file COPYING3. If not see
#include "value-prof.h"
#include "diagnostic-core.h"
#include "builtins.h"
#include "asan.h"
#include "ubsan.h"
#include "cilk.h"
......@@ -5765,6 +5766,14 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
int flags;
/* When ASan is enabled, we don't want to expand some memory/string
builtins and rely on libsanitizer's hooks. This allows us to avoid
redundant checks and be sure, that possible overflow will be detected
by ASan. */
if ((flag_sanitize & SANITIZE_ADDRESS) && asan_intercepted_p (fcode))
return expand_call (exp, target, ignore);
if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
......
2014-10-28 Max Ostapenko <m.ostapenko@partner.samsung.com>
* c-c++-common/asan/no-redundant-instrumentation-1.c: Updated test.
* c-c++-common/asan/no-redundant-instrumentation-4.c: Likewise.
* c-c++-common/asan/no-redundant-instrumentation-5.c: Likewise.
* c-c++-common/asan/no-redundant-instrumentation-6.c: Likewise.
* c-c++-common/asan/no-redundant-instrumentation-7.c: Likewise.
* c-c++-common/asan/no-redundant-instrumentation-8.c: Likewise.
* c-c++-common/asan/no-redundant-instrumentation-2.c: Removed.
* c-c++-common/asan/no-redundant-instrumentation-9.c: Likewise.
* c-c++-common/asan/no-redundant-instrumentation-10.c: New test.
* c-c++-common/asan/no-redundant-instrumentation-11.c: Likewise.
* c-c++-common/asan/no-redundant-instrumentation-12.c: Likewise.
* c-c++-common/asan/no-redundant-instrumentation-13.c: Likewise.
* c-c++-common/asan/no-redundant-instrumentation-14.c: Likewise.
* c-c++-common/asan/no-redundant-instrumentation-15.c: Likewise.
* c-c++-common/asan/pr63638.c: Likewise.
2014-10-28 Richard Biener <rguenther@suse.de>
PR middle-end/63665
......
......@@ -6,7 +6,7 @@
/* { dg-do compile } */
/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
extern char tab[4];
extern char tab[6];
static int
test0 ()
......@@ -35,17 +35,10 @@ test1 (int i)
the initialization. */
foo[i] = 1;
/*__builtin___asan_report_store_n called once here to instrument
the store to the memory region of tab. */
/* Instrument tab memory region. */
__builtin_memset (tab, 3, sizeof (tab));
/* There is no instrumentation for the two memset calls below. */
__builtin_memset (tab, 4, sizeof (tab));
__builtin_memset (tab, 5, sizeof (tab));
/* There is a call to __builtin___asan_report_store_n and a call
to __builtin___asan_report_load_n to instrument the store to
(subset of) the memory region of tab. */
/* Instrument tab[1] with access size 3. */
__builtin_memcpy (&tab[1], foo + i, 3);
/* This should not generate a __builtin___asan_report_load1 because
......@@ -63,6 +56,5 @@ main ()
}
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store1" 3 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 2 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load" 1 "sanopt" } } */
/* { dg-final { scan-tree-dump-not "__builtin___asan_report_load1" "sanopt" } } */
/* { dg-final { cleanup-tree-dump "sanopt" } } */
......@@ -5,13 +5,13 @@
void
foo (int *a, char *b, char *c)
{
/* One check for c[0], one check for a[], one check for c, two checks for b. */
/* One check for c[0], one check for a[]. */
__builtin_memmove (c, b, a[c[0]]);
/* For a total of 5 checks. */
/* For a total of 2 checks. */
int d = c[0] == 1;
}
/* { dg-final { scan-tree-dump-times "& 7" 5 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "& 7" 2 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 1 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 1 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load4" 1 "sanopt" } } */
/* { dg-final { cleanup-tree-dump "sanopt" } } */
......@@ -5,14 +5,12 @@
void
foo (int *a, char *b, char *c)
{
/* One check for b[0], one check for a[], 2 checks for c and one checks for b. */
__builtin_memmove (c, b, a[b[0]]);
/* For a total of 5 checks. */
/* One check for a[]. */
__builtin_memmove (c, b, a[0]);
/* For a total of 1 checks. */
int d = a[0] == 0;
}
/* { dg-final { scan-tree-dump-times "& 7" 5 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "& 7" 1 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load4" 1 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 1 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 1 "sanopt" } } */
/* { dg-final { cleanup-tree-dump "sanopt" } } */
......@@ -5,16 +5,15 @@
void
foo (int *a, char *b, char *c)
{
/* One check for c[0], one check for a[], one check for c and 2 checks for b. */
/* One check for c[0], one check for a[]. */
__builtin_memmove (c, b, a[c[0]]);
/* One check for a[], one check for c and one check for b. */
/* One check for b[0], one check for a[]. */
__builtin_memmove (c, b, a[b[0]]);
/* For a total of 8 checks. */
/* For a total of 4 checks. */
int d = c[0] == b[0];
}
/* { dg-final { scan-tree-dump-times "& 7" 8 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "& 7" 4 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 2 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load4" 2 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 2 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 2 "sanopt" } } */
/* { dg-final { cleanup-tree-dump "sanopt" } } */
......@@ -2,26 +2,22 @@
/* { dg-do compile } */
/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
char e[200];
char e[5];
struct S
extern struct S
{
char a[100];
char b[100];
int a;
char b;
} s;
int
foo (int *a, char *b, char *c)
{
/* 2 checks for s.a, 2 checks for e. */
int d = __builtin_memcmp (s.a, e, 100);
/* One check for s.a and one check for e. */
d += __builtin_memcmp (s.a, e, 200);
/* For a total of 6 checks. */
return d;
int d = __builtin_memcmp (&s.a, e, 4);
/* No check because s.a was instrumented above with access size 4. */
return s.a;
}
/* { dg-final { scan-tree-dump-times "& 7" 6 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 4 "sanopt" } } */
/* { dg-final { scan-tree-dump-not "__builtin___asan_report_store" "sanopt" } } */
/* { dg-final { scan-tree-dump-not "& 7" "sanopt" } } */
/* { dg-final { scan-tree-dump-not "__builtin___asan_report_load4" "sanopt" } } */
/* { dg-final { cleanup-tree-dump "sanopt" } } */
......@@ -5,16 +5,16 @@
char
foo (int *a, char *b, char *c)
{
/* One check for b[0], one check for a[], two checks for c and one check for b. */
/* One check for b[0], one check for a[]. */
__builtin_memmove (c, b, a[b[0]]);
/* One check for c[0], one check for a[]. */
__builtin_memmove (b, c, a[c[0]]);
/* No checks here. */
return c[0] + b[0];
/* For a total of 5 checks. */
/* For a total of 4 checks. */
}
/* { dg-final { scan-tree-dump-times "& 7" 5 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load4" 1 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 1 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 1 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "& 7" 4 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 2 "sanopt" } } */
/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load4" 2 "sanopt" } } */
/* { dg-final { cleanup-tree-dump "sanopt" } } */
......@@ -9,14 +9,8 @@ char a[2] = "0";
#ifdef __cplusplus
extern "C"
#endif
__attribute__((no_sanitize_address, noinline)) __SIZE_TYPE__
strlen (const char *p) {
__SIZE_TYPE__ n = 0;
for (; *p; ++n, ++p);
return n;
}
__SIZE_TYPE__
strlen (const char *p);
int main () {
char *p = &a[0];
......@@ -25,6 +19,6 @@ int main () {
return __builtin_strlen (a);
}
/* { 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 (\[^\n\r]*strlen-overflow-1.c:25|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 1 bytes inside of global variable" } */
/* { dg-output "READ of size 2 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*strlen-overflow-1.c:19|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of global variable" } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment