mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-11 10:40:47 +08:00
use-after-scope: handle writes to a poisoned variable
2017-01-23 Martin Liska <mliska@suse.cz> * gcc.dg/asan/use-after-scope-10.c: New test. * gcc.dg/asan/use-after-scope-11.c: New test. * g++.dg/asan/use-after-scope-5.C: New test. 2017-01-23 Jakub Jelinek <jakub@redhat.com> Martin Liska <mliska@suse.cz> * asan.h: Define ASAN_USE_AFTER_SCOPE_ATTRIBUTE. * asan.c (asan_expand_poison_ifn): Support stores and use appropriate ASAN report function. * internal-fn.c (expand_ASAN_POISON_USE): New function. * internal-fn.def (ASAN_POISON_USE): Declare. * tree-into-ssa.c (maybe_add_asan_poison_write): New function. (maybe_register_def): Create ASAN_POISON_USE when sanitizing. * tree-ssa-dce.c (eliminate_unnecessary_stmts): Remove ASAN_POISON calls w/o LHS. * tree-ssa.c (execute_update_addresses_taken): Create clobber for ASAN_MARK (UNPOISON, &x, ...) in order to prevent usage of a LHS from ASAN_MARK (POISON, &x, ...) coming to a PHI node. * gimplify.c (asan_poison_variables): Add attribute use_after_scope_memory to variables that really needs to live in memory. * tree-ssa.c (is_asan_mark_p): Do not rewrite into SSA when having the attribute. From-SVN: r244793
This commit is contained in:
parent
a51368fad9
commit
f6b9f2ffc1
@ -1,3 +1,24 @@
|
||||
2017-01-23 Jakub Jelinek <jakub@redhat.com>
|
||||
Martin Liska <mliska@suse.cz>
|
||||
|
||||
* asan.h: Define ASAN_USE_AFTER_SCOPE_ATTRIBUTE.
|
||||
* asan.c (asan_expand_poison_ifn): Support stores and use
|
||||
appropriate ASAN report function.
|
||||
* internal-fn.c (expand_ASAN_POISON_USE): New function.
|
||||
* internal-fn.def (ASAN_POISON_USE): Declare.
|
||||
* tree-into-ssa.c (maybe_add_asan_poison_write): New function.
|
||||
(maybe_register_def): Create ASAN_POISON_USE when sanitizing.
|
||||
* tree-ssa-dce.c (eliminate_unnecessary_stmts): Remove
|
||||
ASAN_POISON calls w/o LHS.
|
||||
* tree-ssa.c (execute_update_addresses_taken): Create clobber
|
||||
for ASAN_MARK (UNPOISON, &x, ...) in order to prevent usage of a LHS
|
||||
from ASAN_MARK (POISON, &x, ...) coming to a PHI node.
|
||||
* gimplify.c (asan_poison_variables): Add attribute
|
||||
use_after_scope_memory to variables that really needs to live
|
||||
in memory.
|
||||
* tree-ssa.c (is_asan_mark_p): Do not rewrite into SSA when
|
||||
having the attribute.
|
||||
|
||||
2017-01-23 Martin Liska <mliska@suse.cz>
|
||||
|
||||
* asan.c (create_asan_shadow_var): New function.
|
||||
|
19
gcc/asan.c
19
gcc/asan.c
@ -3094,6 +3094,8 @@ create_asan_shadow_var (tree var_decl,
|
||||
return *slot;
|
||||
}
|
||||
|
||||
/* Expand ASAN_POISON ifn. */
|
||||
|
||||
bool
|
||||
asan_expand_poison_ifn (gimple_stmt_iterator *iter,
|
||||
bool *need_commit_edge_insert,
|
||||
@ -3107,8 +3109,8 @@ asan_expand_poison_ifn (gimple_stmt_iterator *iter,
|
||||
return true;
|
||||
}
|
||||
|
||||
tree shadow_var = create_asan_shadow_var (SSA_NAME_VAR (poisoned_var),
|
||||
shadow_vars_mapping);
|
||||
tree shadow_var = create_asan_shadow_var (SSA_NAME_VAR (poisoned_var),
|
||||
shadow_vars_mapping);
|
||||
|
||||
bool recover_p;
|
||||
if (flag_sanitize & SANITIZE_USER_ADDRESS)
|
||||
@ -3122,16 +3124,16 @@ asan_expand_poison_ifn (gimple_stmt_iterator *iter,
|
||||
ASAN_MARK_POISON),
|
||||
build_fold_addr_expr (shadow_var), size);
|
||||
|
||||
use_operand_p use_p;
|
||||
gimple *use;
|
||||
imm_use_iterator imm_iter;
|
||||
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, poisoned_var)
|
||||
FOR_EACH_IMM_USE_STMT (use, imm_iter, poisoned_var)
|
||||
{
|
||||
gimple *use = USE_STMT (use_p);
|
||||
if (is_gimple_debug (use))
|
||||
continue;
|
||||
|
||||
int nargs;
|
||||
tree fun = report_error_func (false, recover_p, tree_to_uhwi (size),
|
||||
bool store_p = gimple_call_internal_p (use, IFN_ASAN_POISON_USE);
|
||||
tree fun = report_error_func (store_p, recover_p, tree_to_uhwi (size),
|
||||
&nargs);
|
||||
|
||||
gcall *call = gimple_build_call (fun, 1,
|
||||
@ -3160,7 +3162,10 @@ asan_expand_poison_ifn (gimple_stmt_iterator *iter,
|
||||
else
|
||||
{
|
||||
gimple_stmt_iterator gsi = gsi_for_stmt (use);
|
||||
gsi_insert_before (&gsi, call, GSI_NEW_STMT);
|
||||
if (store_p)
|
||||
gsi_replace (&gsi, call, true);
|
||||
else
|
||||
gsi_insert_before (&gsi, call, GSI_NEW_STMT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,8 @@ extern hash_set <tree> *asan_used_labels;
|
||||
#define ASAN_STACK_FRAME_MAGIC 0x41b58ab3
|
||||
#define ASAN_STACK_RETIRED_MAGIC 0x45e0360e
|
||||
|
||||
#define ASAN_USE_AFTER_SCOPE_ATTRIBUTE "use after scope memory"
|
||||
|
||||
/* Various flags for Asan builtins. */
|
||||
enum asan_check_flags
|
||||
{
|
||||
|
@ -1206,8 +1206,21 @@ asan_poison_variables (hash_set<tree> *variables, bool poison, gimple_seq *seq_p
|
||||
|
||||
sorted_variables.qsort (sort_by_decl_uid);
|
||||
|
||||
for (unsigned i = 0; i < sorted_variables.length (); i++)
|
||||
asan_poison_variable (sorted_variables[i], poison, seq_p);
|
||||
unsigned i;
|
||||
tree var;
|
||||
FOR_EACH_VEC_ELT (sorted_variables, i, var)
|
||||
{
|
||||
asan_poison_variable (var, poison, seq_p);
|
||||
|
||||
/* Add use_after_scope_memory attribute for the variable in order
|
||||
to prevent re-written into SSA. */
|
||||
if (!lookup_attribute (ASAN_USE_AFTER_SCOPE_ATTRIBUTE,
|
||||
DECL_ATTRIBUTES (var)))
|
||||
DECL_ATTRIBUTES (var)
|
||||
= tree_cons (get_identifier (ASAN_USE_AFTER_SCOPE_ATTRIBUTE),
|
||||
integer_one_node,
|
||||
DECL_ATTRIBUTES (var));
|
||||
}
|
||||
}
|
||||
|
||||
/* Gimplify a BIND_EXPR. Just voidify and recurse. */
|
||||
|
@ -388,6 +388,14 @@ expand_ASAN_POISON (internal_fn, gcall *)
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* This should get expanded in the sanopt pass. */
|
||||
|
||||
static void
|
||||
expand_ASAN_POISON_USE (internal_fn, gcall *)
|
||||
{
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* This should get expanded in the tsan pass. */
|
||||
|
||||
static void
|
||||
|
@ -168,6 +168,7 @@ DEF_INTERNAL_FN (BUILTIN_EXPECT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
|
||||
DEF_INTERNAL_FN (ASAN_CHECK, ECF_TM_PURE | ECF_LEAF | ECF_NOTHROW, ".R...")
|
||||
DEF_INTERNAL_FN (ASAN_MARK, ECF_LEAF | ECF_NOTHROW, ".R..")
|
||||
DEF_INTERNAL_FN (ASAN_POISON, ECF_LEAF | ECF_NOTHROW | ECF_NOVOPS, NULL)
|
||||
DEF_INTERNAL_FN (ASAN_POISON_USE, ECF_LEAF | ECF_NOTHROW | ECF_NOVOPS, NULL)
|
||||
DEF_INTERNAL_FN (ADD_OVERFLOW, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
|
||||
DEF_INTERNAL_FN (SUB_OVERFLOW, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
|
||||
DEF_INTERNAL_FN (MUL_OVERFLOW, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
|
||||
|
@ -1,3 +1,9 @@
|
||||
2017-01-23 Martin Liska <mliska@suse.cz>
|
||||
|
||||
* gcc.dg/asan/use-after-scope-10.c: New test.
|
||||
* gcc.dg/asan/use-after-scope-11.c: New test.
|
||||
* g++.dg/asan/use-after-scope-5.C: New test.
|
||||
|
||||
2017-01-23 Martin Liska <mliska@suse.cz>
|
||||
|
||||
* gcc.dg/asan/use-after-scope-3.c: Add additional flags.
|
||||
|
23
gcc/testsuite/g++.dg/asan/use-after-scope-5.C
Normal file
23
gcc/testsuite/g++.dg/asan/use-after-scope-5.C
Normal file
@ -0,0 +1,23 @@
|
||||
// { dg-do run }
|
||||
|
||||
int *
|
||||
__attribute__((optimize(("-O0"))))
|
||||
fn1 (int *a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
void
|
||||
fn2 ()
|
||||
{
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
int *a;
|
||||
(a) = fn1 (a);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
fn2();
|
||||
}
|
22
gcc/testsuite/gcc.dg/asan/use-after-scope-10.c
Normal file
22
gcc/testsuite/gcc.dg/asan/use-after-scope-10.c
Normal file
@ -0,0 +1,22 @@
|
||||
// { dg-do run }
|
||||
// { dg-shouldfail "asan" }
|
||||
// { dg-additional-options "-O2 -fdump-tree-asan1" }
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int *ptr = 0;
|
||||
|
||||
{
|
||||
int a;
|
||||
ptr = &a;
|
||||
*ptr = 12345;
|
||||
}
|
||||
|
||||
*ptr = 12345;
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
// { dg-output "ERROR: AddressSanitizer: stack-use-after-scope on address.*(\n|\r\n|\r)" }
|
||||
// { dg-output "WRITE of size .*" }
|
||||
// { dg-output ".*'a' <== Memory access at offset \[0-9\]* is inside this variable.*" }
|
30
gcc/testsuite/gcc.dg/asan/use-after-scope-11.c
Normal file
30
gcc/testsuite/gcc.dg/asan/use-after-scope-11.c
Normal file
@ -0,0 +1,30 @@
|
||||
// { dg-do run }
|
||||
|
||||
#include <string.h>
|
||||
|
||||
char cc;
|
||||
char ptr[] = "sparta2";
|
||||
|
||||
void get(char **x)
|
||||
{
|
||||
*x = ptr;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
char *here = &cc;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
next_line:
|
||||
if (here == NULL)
|
||||
__builtin_abort();
|
||||
get (&here);
|
||||
if (strcmp (here, "sparta") == 0)
|
||||
goto next_line;
|
||||
else if (strcmp (here, "sparta2") == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "tree-ssa.h"
|
||||
#include "domwalk.h"
|
||||
#include "statistics.h"
|
||||
#include "asan.h"
|
||||
|
||||
#define PERCENT(x,y) ((float)(x) * 100.0 / (float)(y))
|
||||
|
||||
@ -1807,6 +1808,26 @@ maybe_replace_use_in_debug_stmt (use_operand_p use_p)
|
||||
}
|
||||
|
||||
|
||||
/* If DEF has x_5 = ASAN_POISON () as its current def, add
|
||||
ASAN_POISON_USE (x_5) stmt before GSI to denote the stmt writes into
|
||||
a poisoned (out of scope) variable. */
|
||||
|
||||
static void
|
||||
maybe_add_asan_poison_write (tree def, gimple_stmt_iterator *gsi)
|
||||
{
|
||||
tree cdef = get_current_def (def);
|
||||
if (cdef != NULL
|
||||
&& TREE_CODE (cdef) == SSA_NAME
|
||||
&& gimple_call_internal_p (SSA_NAME_DEF_STMT (cdef), IFN_ASAN_POISON))
|
||||
{
|
||||
gcall *call
|
||||
= gimple_build_call_internal (IFN_ASAN_POISON_USE, 1, cdef);
|
||||
gimple_set_location (call, gimple_location (gsi_stmt (*gsi)));
|
||||
gsi_insert_before (gsi, call, GSI_SAME_STMT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* If the operand pointed to by DEF_P is an SSA name in NEW_SSA_NAMES
|
||||
or OLD_SSA_NAMES, or if it is a symbol marked for renaming,
|
||||
register it as the current definition for the names replaced by
|
||||
@ -1837,7 +1858,11 @@ maybe_register_def (def_operand_p def_p, gimple *stmt,
|
||||
def = get_or_create_ssa_default_def (cfun, sym);
|
||||
}
|
||||
else
|
||||
def = make_ssa_name (def, stmt);
|
||||
{
|
||||
if (asan_sanitize_use_after_scope ())
|
||||
maybe_add_asan_poison_write (def, &gsi);
|
||||
def = make_ssa_name (def, stmt);
|
||||
}
|
||||
SET_DEF (def_p, def);
|
||||
|
||||
tree tracked_var = target_for_debug_bind (sym);
|
||||
|
@ -1367,10 +1367,18 @@ eliminate_unnecessary_stmts (void)
|
||||
update_stmt (stmt);
|
||||
release_ssa_name (name);
|
||||
|
||||
/* GOMP_SIMD_LANE without lhs is not needed. */
|
||||
if (gimple_call_internal_p (stmt)
|
||||
&& gimple_call_internal_fn (stmt) == IFN_GOMP_SIMD_LANE)
|
||||
remove_dead_stmt (&gsi, bb);
|
||||
/* GOMP_SIMD_LANE or ASAN_POISON without lhs is not
|
||||
needed. */
|
||||
if (gimple_call_internal_p (stmt))
|
||||
switch (gimple_call_internal_fn (stmt))
|
||||
{
|
||||
case IFN_GOMP_SIMD_LANE:
|
||||
case IFN_ASAN_POISON:
|
||||
remove_dead_stmt (&gsi, bb);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (gimple_call_internal_p (stmt))
|
||||
switch (gimple_call_internal_fn (stmt))
|
||||
|
@ -1590,6 +1590,10 @@ is_asan_mark_p (gimple *stmt)
|
||||
&& VAR_P (TREE_OPERAND (addr, 0)))
|
||||
{
|
||||
tree var = TREE_OPERAND (addr, 0);
|
||||
if (lookup_attribute (ASAN_USE_AFTER_SCOPE_ATTRIBUTE,
|
||||
DECL_ATTRIBUTES (var)))
|
||||
return false;
|
||||
|
||||
unsigned addressable = TREE_ADDRESSABLE (var);
|
||||
TREE_ADDRESSABLE (var) = 0;
|
||||
bool r = is_gimple_reg (var);
|
||||
@ -1911,7 +1915,16 @@ execute_update_addresses_taken (void)
|
||||
gsi_replace (&gsi, call, GSI_SAME_STMT);
|
||||
}
|
||||
else
|
||||
gsi_remove (&gsi, true);
|
||||
{
|
||||
/* In ASAN_MARK (UNPOISON, &b, ...) the variable
|
||||
is uninitialized. Avoid dependencies on
|
||||
previous out of scope value. */
|
||||
tree clobber
|
||||
= build_constructor (TREE_TYPE (var), NULL);
|
||||
TREE_THIS_VOLATILE (clobber) = 1;
|
||||
gimple *g = gimple_build_assign (var, clobber);
|
||||
gsi_replace (&gsi, g, GSI_SAME_STMT);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user