asan.c (report_error_func): Add SLOW_P argument, use BUILT_IN_ASAN_*_N if set.

* asan.c (report_error_func): Add SLOW_P argument, use
	BUILT_IN_ASAN_*_N if set.
	(build_check_stmt): Likewise.
	(instrument_derefs): If T has insufficient alignment,
	force same handling as for odd sizes.

	* c-c++-common/asan/misalign-1.c: New test.
	* c-c++-common/asan/misalign-2.c: New test.

From-SVN: r211092
This commit is contained in:
Jakub Jelinek 2014-05-30 20:37:59 +02:00 committed by Jakub Jelinek
parent 40f9f6bb0e
commit b3f1051b11
5 changed files with 134 additions and 10 deletions

View File

@ -1,5 +1,11 @@
2014-05-30 Jakub Jelinek <jakub@redhat.com>
* asan.c (report_error_func): Add SLOW_P argument, use
BUILT_IN_ASAN_*_N if set.
(build_check_stmt): Likewise.
(instrument_derefs): If T has insufficient alignment,
force same handling as for odd sizes.
* sanitizer.def (BUILT_IN_ASAN_REPORT_LOAD_N,
BUILT_IN_ASAN_REPORT_STORE_N): New.
* asan.c (struct asan_mem_ref): Change access_size type to

View File

@ -1319,7 +1319,7 @@ asan_protect_global (tree decl)
IS_STORE is either 1 (for a store) or 0 (for a load). */
static tree
report_error_func (bool is_store, HOST_WIDE_INT size_in_bytes)
report_error_func (bool is_store, HOST_WIDE_INT size_in_bytes, bool slow_p)
{
static enum built_in_function report[2][6]
= { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
@ -1329,7 +1329,8 @@ report_error_func (bool is_store, HOST_WIDE_INT size_in_bytes)
BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } };
if ((size_in_bytes & (size_in_bytes - 1)) != 0
|| size_in_bytes > 16)
|| size_in_bytes > 16
|| slow_p)
return builtin_decl_implicit (report[is_store][5]);
return builtin_decl_implicit (report[is_store][exact_log2 (size_in_bytes)]);
}
@ -1508,7 +1509,8 @@ build_shadow_mem_access (gimple_stmt_iterator *gsi, location_t location,
static void
build_check_stmt (location_t location, tree base, gimple_stmt_iterator *iter,
bool before_p, bool is_store, HOST_WIDE_INT size_in_bytes)
bool before_p, bool is_store, HOST_WIDE_INT size_in_bytes,
bool slow_p = false)
{
gimple_stmt_iterator gsi;
basic_block then_bb, else_bb;
@ -1522,9 +1524,15 @@ build_check_stmt (location_t location, tree base, gimple_stmt_iterator *iter,
HOST_WIDE_INT real_size_in_bytes = size_in_bytes;
tree sz_arg = NULL_TREE;
if ((size_in_bytes & (size_in_bytes - 1)) != 0
|| size_in_bytes > 16)
real_size_in_bytes = 1;
if (size_in_bytes == 1)
slow_p = false;
else if ((size_in_bytes & (size_in_bytes - 1)) != 0
|| size_in_bytes > 16
|| slow_p)
{
real_size_in_bytes = 1;
slow_p = true;
}
/* Get an iterator on the point where we can add the condition
statement for the instrumentation. */
@ -1582,8 +1590,8 @@ build_check_stmt (location_t location, tree base, gimple_stmt_iterator *iter,
t = gimple_assign_lhs (gimple_seq_last (seq));
gimple_seq_set_location (seq, location);
gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
/* For weird access sizes, check first and last byte. */
if (real_size_in_bytes != size_in_bytes)
/* For weird access sizes or misaligned, check first and last byte. */
if (slow_p)
{
g = gimple_build_assign_with_ops (PLUS_EXPR,
make_ssa_name (uintptr_type, NULL),
@ -1626,7 +1634,7 @@ build_check_stmt (location_t location, tree base, gimple_stmt_iterator *iter,
/* Generate call to the run-time library (e.g. __asan_report_load8). */
gsi = gsi_start_bb (then_bb);
g = gimple_build_call (report_error_func (is_store, size_in_bytes),
g = gimple_build_call (report_error_func (is_store, size_in_bytes, slow_p),
sz_arg ? 2 : 1, base_addr, sz_arg);
gimple_set_location (g, location);
gsi_insert_after (&gsi, g, GSI_NEW_STMT);
@ -1722,8 +1730,31 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t,
base = build_fold_addr_expr (t);
if (!has_mem_ref_been_instrumented (base, size_in_bytes))
{
bool slow_p = false;
if (size_in_bytes > 1)
{
if ((size_in_bytes & (size_in_bytes - 1)) != 0
|| size_in_bytes > 16)
slow_p = true;
else
{
unsigned int align = get_object_alignment (t);
if (align < size_in_bytes * BITS_PER_UNIT)
{
/* On non-strict alignment targets, if
16-byte access is just 8-byte aligned,
this will result in misaligned shadow
memory 2 byte load, but otherwise can
be handled using one read. */
if (size_in_bytes != 16
|| STRICT_ALIGNMENT
|| align < 8 * BITS_PER_UNIT)
slow_p = true;
}
}
}
build_check_stmt (location, base, iter, /*before_p=*/true,
is_store, size_in_bytes);
is_store, size_in_bytes, slow_p);
update_mem_ref_hash_table (base, size_in_bytes);
update_mem_ref_hash_table (t, size_in_bytes);
}

View File

@ -1,5 +1,8 @@
2014-05-30 Jakub Jelinek <jakub@redhat.com>
* c-c++-common/asan/misalign-1.c: New test.
* c-c++-common/asan/misalign-2.c: New test.
* g++.dg/asan/asan_test.C: Add -std=c++11 and
-DSANITIZER_USE_DEJAGNU_GTEST=1 to dg-options, remove
-DASAN_USE_DEJAGNU_GTEST=1.

View File

@ -0,0 +1,42 @@
/* { dg-do run { target { ilp32 || lp64 } } } */
/* { dg-options "-O2" } */
/* { dg-shouldfail "asan" } */
struct S { int i; } __attribute__ ((packed));
__attribute__((noinline, noclone)) int
foo (struct S *s)
{
return s->i;
}
__attribute__((noinline, noclone)) int
bar (int *s)
{
return *s;
}
__attribute__((noinline, noclone)) struct S
baz (struct S *s)
{
return *s;
}
int
main ()
{
struct T { char a[3]; struct S b[3]; char c; } t;
int v = 5;
struct S *p = t.b;
asm volatile ("" : "+rm" (p));
p += 3;
if (bar (&v) != 5) __builtin_abort ();
volatile int w = foo (p);
return 0;
}
/* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*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 "\[^\n\r]*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 _*foo(\[^\n\r]*misalign-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*misalign-1.c:34|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */

View File

@ -0,0 +1,42 @@
/* { dg-do run { target { ilp32 || lp64 } } } */
/* { dg-options "-O2" } */
/* { dg-shouldfail "asan" } */
struct S { int i; } __attribute__ ((packed));
__attribute__((noinline, noclone)) int
foo (struct S *s)
{
return s->i;
}
__attribute__((noinline, noclone)) int
bar (int *s)
{
return *s;
}
__attribute__((noinline, noclone)) struct S
baz (struct S *s)
{
return *s;
}
int
main ()
{
struct T { char a[3]; struct S b[3]; char c; } t;
int v = 5;
struct S *p = t.b;
asm volatile ("" : "+rm" (p));
p += 3;
if (bar (&v) != 5) __builtin_abort ();
volatile struct S w = baz (p);
return 0;
}
/* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*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 "\[^\n\r]*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 _*baz(\[^\n\r]*misalign-2.c:22|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*misalign-2.c:34|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */