public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH, RFC] Introduce -fsanitize=use-after-scope
@ 2016-05-06 11:04 Martin Liška
  2016-05-06 11:08 ` [PATCH] Introduce tests for -fsanitize=use-after-scope Martin Liška
                   ` (3 more replies)
  0 siblings, 4 replies; 111+ messages in thread
From: Martin Liška @ 2016-05-06 11:04 UTC (permalink / raw)
  To: GCC Patches; +Cc: Jakub Jelinek

[-- Attachment #1: Type: text/plain, Size: 4419 bytes --]

Hello.

I've started working on the patch couple of month go, basically after
a brief discussion with Jakub on IRC.

I'm sending the initial version which can successfully run instrumented
tramp3d, postgresql server and Inkscape. It catches the basic set of
examples which are added in following patch.

The implementation is quite straightforward as works in following steps:

1) Every local variable stack slot is poisoned at the very beginning of a function (RTL emission)
2) In gimplifier, once we spot a DECL_EXPR, a variable is unpoisoned (by emitting ASAN_MARK builtin)
and the variable is marked as addressable
3) Similarly, BIND_EXPR is the place where we poison the variable (scope exit)
4) At the very end of the function, we clean up the poisoned memory
5) The builtins are expanded to call to libsanitizer run-time library (__asan_poison_stack_memory, __asan_unpoison_stack_memory)
6) As the use-after-scope stuff is already included in libsanitizer, no change is needed for the library

Example:

int
main (void)
{
  char *ptr;
  {
    char my_char[9];
    ptr = &my_char[0];
  }

  *(ptr+9) = 'c';
}

./a.out 
=================================================================
==12811==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7ffec9bcff69 at pc 0x000000400a73 bp 0x7ffec9bcfef0 sp 0x7ffec9bcfee8
WRITE of size 1 at 0x7ffec9bcff69 thread T0
    #0 0x400a72 in main (/tmp/a.out+0x400a72)
    #1 0x7f100824860f in __libc_start_main (/lib64/libc.so.6+0x2060f)
    #2 0x400868 in _start (/tmp/a.out+0x400868)

Address 0x7ffec9bcff69 is located in stack of thread T0 at offset 105 in frame
    #0 0x400945 in main (/tmp/a.out+0x400945)

  This frame has 2 object(s):
    [32, 40) 'ptr'
    [96, 105) 'my_char' <== Memory access at offset 105 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-scope (/tmp/a.out+0x400a72) in main
Shadow bytes around the buggy address:
  0x100059371f90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100059371fa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100059371fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100059371fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100059371fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x100059371fe0: f1 f1 f1 f1 00 f4 f4 f4 f2 f2 f2 f2 f8[f8]f4 f4
  0x100059371ff0: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
  0x100059372000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100059372010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100059372020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100059372030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==12811==ABORTING

As mentioned, it's request for comment as it still has couple of limitations:
a) VLA are not supported, which should make sense as we are unable to allocate a stack slot for that
b) we can possibly strip some instrumentation in situations where a variable is introduced in a very first BB (RTL poisoning is superfluous).
Similarly for a very last BB of a function, we can strip end of scope poisoning (and RTL unpoisoning). I'll do that incrementally.
c) We require -fstack-reuse=none option, maybe it worth to warn a user if -fsanitize=use-after-scope is provided without the option?
d) An instrumented binary is quite slow (~20x for tramp3d) as every function call produces many memory read/writes. I'm wondering whether
we should provide a faster alternative (like instrument just variables that have address taken) ?

Patch can survive bootstrap and regression tests on x86_64-linux-gnu.

Thanks for feedback.
Martin

[-- Attachment #2: 0001-Introduce-fsanitize-use-after-scope.patch --]
[-- Type: text/x-patch, Size: 26301 bytes --]

From 242bcaf2fa7777ded33291d05a5c4c5306f849de Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Tue, 3 May 2016 15:35:22 +0200
Subject: [PATCH 1/2] Introduce -fsanitize=use-after-scope

gcc/ChangeLog:

2016-05-03  Martin Liska  <mliska@suse.cz>

	* asan.c (enum asan_check_flags): Cut the enum from here.
	(asan_poison_stack_variables): New function.
	(asan_emit_stack_protection): Poison stack variables.
	(asan_expand_mark_ifn): New function.
	* asan.h (enum asan_mark_flags): Paste here the enum from source
	file.
	(asan_sanitize_stack_p): Move function from cfgexpand.
	(asan_sanitize_use_after_scope): New function.
	(asan_no_sanitize_address_p): New function.
	* flag-types.h (enum sanitize_code): Introduce new enum value.
	* gimplify.c (asan_poison_variable): New function.
	(gimplify_bind_expr): Poison all local variables that go out
	of a scope.
	(gimplify_decl_expr): Unpoison a local vairable and mark the
	variable to live on a stack.
	(gimplify_expr): Unclobber all seen variables that can be
	poisoned due to a jump to a label.
	(gimplify_function_tree):
	* internal-fn.c (expand_ASAN_MARK): New function.
	* internal-fn.def: Define ASAN_MARK.
	* opts.c: Introduce use-after-scope as a new option value
	for -fsanitize.
	* sanitizer.def: Declare two new sanitizer builtins
	(__asan_poison_stack_memory, __asan_unpoison_stack_memory).
	* sanopt.c (pass_sanopt::execute): Call expansion of ASAN_MARKs.
	* tree-inline.c (setup_one_parameter): Record local variables
	introduced by inlining.
	(copy_decl_no_change): Likewise.
	* builtins.c: Include params.h header file.
	* gimplify.c: Include params.h header file.
	* opts-global.c: Include params.h header file.
	* sancov.c: Include params.h header file.
	* sanopt.c: Include params.h header file.
	* tree-streamer-in.c: Include params.h header file.
	* tsan.c: Include params.h header file.
	* ubsan.c: Include params.h header file.
	* varasm.c: Include params.h header file.
	* cfgexpand.c (asan_sanitize_stack_p): Use
	asan_no_sanitize_address_p function.

libsanitizer/ChangeLog:

2016-05-04  Martin Liska  <mliska@suse.cz>

	* asan/asan_poisoning.cc: Do not call PoisonShadow in case
	of zero size of aligned size.

gcc/ChangeLog:

2016-05-04  Martin Liska  <mliska@suse.cz>

gcc/c-family/ChangeLog:

2016-05-04  Martin Liska  <mliska@suse.cz>

	* c-ubsan.c: Include params.h header file.

gcc/cp/ChangeLog:

2016-05-04  Martin Liska  <mliska@suse.cz>

	* decl2.c: Include params.h header file.

Partial revert + fixed.
---
 gcc/asan.c                          | 100 ++++++++++++++++++++++++++++++++----
 gcc/asan.h                          |  41 +++++++++++++++
 gcc/builtins.c                      |   1 +
 gcc/c-family/c-ubsan.c              |   1 +
 gcc/cfgexpand.c                     |   3 +-
 gcc/cp/decl2.c                      |   1 +
 gcc/flag-types.h                    |   5 +-
 gcc/gimplify.c                      |  87 +++++++++++++++++++++++++++----
 gcc/internal-fn.c                   |   9 ++++
 gcc/internal-fn.def                 |   1 +
 gcc/opts-global.c                   |   1 +
 gcc/opts.c                          |   2 +
 gcc/sancov.c                        |   1 +
 gcc/sanitizer.def                   |   4 ++
 gcc/sanopt.c                        |   5 +-
 gcc/tree-inline.c                   |  15 +++++-
 gcc/tree-streamer-in.c              |   1 +
 gcc/tree-vect-patterns.c            |   3 +-
 gcc/tsan.c                          |   1 +
 gcc/ubsan.c                         |   1 +
 gcc/varasm.c                        |   1 +
 libsanitizer/asan/asan_poisoning.cc |   5 +-
 22 files changed, 260 insertions(+), 29 deletions(-)

diff --git a/gcc/asan.c b/gcc/asan.c
index 71095fb..0c1b92a 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "varasm.h"
 #include "stor-layout.h"
 #include "tree-iterator.h"
+#include "params.h"
 #include "asan.h"
 #include "dojump.h"
 #include "explow.h"
@@ -54,7 +55,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "cfgloop.h"
 #include "gimple-builder.h"
 #include "ubsan.h"
-#include "params.h"
 #include "builtins.h"
 #include "fnmatch.h"
 
@@ -313,6 +313,8 @@ asan_shadow_offset ()
 
 alias_set_type asan_shadow_set = -1;
 
+hash_set <tree> asan_inlined_variables;
+
 /* Pointer types to 1 resp. 2 byte integers in shadow memory.  A separate
    alias set is used for all shadow memory accesses.  */
 static GTY(()) tree shadow_ptr_types[2];
@@ -320,15 +322,6 @@ static GTY(()) tree shadow_ptr_types[2];
 /* Decl for __asan_option_detect_stack_use_after_return.  */
 static GTY(()) tree asan_detect_stack_use_after_return;
 
-/* Various flags for Asan builtins.  */
-enum asan_check_flags
-{
-  ASAN_CHECK_STORE = 1 << 0,
-  ASAN_CHECK_SCALAR_ACCESS = 1 << 1,
-  ASAN_CHECK_NON_ZERO_LEN = 1 << 2,
-  ASAN_CHECK_LAST = 1 << 3
-};
-
 /* Hashtable support for memory references used by gimple
    statements.  */
 
@@ -1020,6 +1013,45 @@ asan_function_start (void)
 			 current_function_funcdef_no);
 }
 
+/* Depending on POISON flag, emit a call to poison (or unpoison) stack memory
+   allocated for local variables, localted in OFFSETS.  LENGTH is number
+   of OFFSETS, BASE is the register holding the stack base,
+   against which OFFSETS array offsets are relative to.  BASE_OFFSET represents
+   an offset requested by alignment and similar stuff.  */
+
+static void
+asan_poison_stack_variables (rtx base, HOST_WIDE_INT base_offset,
+			     HOST_WIDE_INT *offsets, int length,
+			     tree *decls, bool poison)
+{
+  if (asan_sanitize_use_after_scope ())
+    for (int l = length - 2; l > 0; l -= 2)
+      {
+	tree decl = decls[l / 2 - 1];
+	if (asan_inlined_variables.contains (decl))
+	  {
+	    gcc_assert (DECL_ABSTRACT_ORIGIN (decl));
+	    continue;
+	  }
+
+	HOST_WIDE_INT var_offset = offsets[l];
+	HOST_WIDE_INT var_end_offset = offsets[l - 1];
+
+	rtx source = expand_binop (Pmode, add_optab, base,
+				   gen_int_mode
+				    (var_offset - base_offset, Pmode),
+				   NULL_RTX, 1, OPTAB_DIRECT);
+
+	rtx size = GEN_INT (var_end_offset - var_offset);
+	const char *fname = poison ?  "__asan_poison_stack_memory"
+	  :"__asan_unpoison_stack_memory";
+	rtx ret = init_one_libfunc (fname);
+	emit_library_call (ret, LCT_NORMAL, VOIDmode, 2, source, ptr_mode,
+			   size, TYPE_MODE (pointer_sized_int_node));
+      }
+}
+
+
 /* Insert code to protect stack vars.  The prologue sequence should be emitted
    directly, epilogue sequence returned.  BASE is the register holding the
    stack base, against which OFFSETS array offsets are relative to, OFFSETS
@@ -1228,6 +1260,11 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
 	}
       cur_shadow_byte = ASAN_STACK_MAGIC_MIDDLE;
     }
+
+  /* Poison stack variables at the very beginning of a function.  */
+  asan_poison_stack_variables (base, base_offset, offsets, length,
+			       decls, true);
+
   do_pending_stack_adjust ();
 
   /* Construct epilogue sequence.  */
@@ -1309,6 +1346,11 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
       asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
     }
 
+  /* Unpoison stack variables at the end of a function.  As the former
+     stack memory can be reused, we have to unpoison the memory.  */
+  asan_poison_stack_variables (base, base_offset, offsets, length, decls,
+			       false);
+
   do_pending_stack_adjust ();
   if (lab)
     emit_label (lab);
@@ -2573,6 +2615,44 @@ asan_finish_file (void)
   flag_sanitize |= SANITIZE_ADDRESS;
 }
 
+/* Expand the ASAN_MARK builtins.  */
+
+bool
+asan_expand_mark_ifn (gimple_stmt_iterator *iter)
+{
+  gimple *g = gsi_stmt (*iter);
+  location_t loc = gimple_location (g);
+  HOST_WIDE_INT flags = tree_to_shwi (gimple_call_arg (g, 0));
+  gcc_assert (flags < ASAN_MARK_LAST);
+  bool is_clobber = (flags & ASAN_MARK_CLOBBER) != 0;
+
+  tree base = gimple_call_arg (g, 1);
+  tree len = gimple_call_arg (g, 2);
+
+  HOST_WIDE_INT size_in_bytes
+    = tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
+  gcc_assert (size_in_bytes);
+
+  g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
+				  NOP_EXPR, base);
+  gimple_set_location (g, loc);
+  gsi_insert_before (iter, g, GSI_SAME_STMT);
+  tree base_addr = gimple_assign_lhs (g);
+
+  g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
+			   NOP_EXPR, len);
+  gimple_set_location (g, loc);
+  gsi_insert_before (iter, g, GSI_SAME_STMT);
+  tree sz_arg = gimple_assign_lhs (g);
+
+  tree fun = builtin_decl_implicit (is_clobber ? BUILT_IN_ASAN_CLOBBER_N
+				    : BUILT_IN_ASAN_UNCLOBBER_N);
+  g = gimple_build_call (fun, 2, base_addr, sz_arg);
+  gimple_set_location (g, loc);
+  gsi_replace (iter, g, false);
+  return false;
+}
+
 /* Expand the ASAN_{LOAD,STORE} builtins.  */
 
 bool
diff --git a/gcc/asan.h b/gcc/asan.h
index 7ec693f..573af2f 100644
--- a/gcc/asan.h
+++ b/gcc/asan.h
@@ -29,6 +29,7 @@ extern bool asan_protect_global (tree);
 extern void initialize_sanitizer_builtins (void);
 extern tree asan_dynamic_init_call (bool);
 extern bool asan_expand_check_ifn (gimple_stmt_iterator *, bool);
+extern bool asan_expand_mark_ifn (gimple_stmt_iterator *);
 
 extern gimple_stmt_iterator create_cond_insert_point
      (gimple_stmt_iterator *, bool, bool, bool, basic_block *, basic_block *);
@@ -36,6 +37,10 @@ extern gimple_stmt_iterator create_cond_insert_point
 /* Alias set for accessing the shadow memory.  */
 extern alias_set_type asan_shadow_set;
 
+/* Hash set of inlined variables that cannot be poisoned by use-after-cope
+   sanitizer.  */
+extern hash_set <tree> asan_inlined_variables;
+
 /* Shadow memory is found at
    (address >> ASAN_SHADOW_SHIFT) + asan_shadow_offset ().  */
 #define ASAN_SHADOW_SHIFT	3
@@ -59,6 +64,23 @@ extern alias_set_type asan_shadow_set;
 #define ASAN_STACK_FRAME_MAGIC		0x41b58ab3
 #define ASAN_STACK_RETIRED_MAGIC	0x45e0360e
 
+/* Various flags for Asan builtins.  */
+enum asan_check_flags
+{
+  ASAN_CHECK_STORE = 1 << 0,
+  ASAN_CHECK_SCALAR_ACCESS = 1 << 1,
+  ASAN_CHECK_NON_ZERO_LEN = 1 << 2,
+  ASAN_CHECK_LAST = 1 << 3
+};
+
+/* Flags for Asan check builtins.  */
+enum asan_mark_flags
+{
+  ASAN_MARK_CLOBBER = 1 << 0,
+  ASAN_MARK_UNCLOBBER = 1 << 1,
+  ASAN_MARK_LAST = 1 << 2
+};
+
 /* Return true if DECL should be guarded on the stack.  */
 
 static inline bool
@@ -105,4 +127,23 @@ asan_intercepted_p (enum built_in_function fcode)
 	 || fcode == BUILT_IN_STRNCMP
 	 || fcode == BUILT_IN_STRNCPY;
 }
+
+/* Return TRUE if we should instrument for use-after-scope sanity checking.  */
+
+static inline bool
+asan_sanitize_use_after_scope (void)
+{
+  return (flag_sanitize & SANITIZE_ADDRESS_USE_AFTER_SCOPE)
+    == SANITIZE_ADDRESS_USE_AFTER_SCOPE
+    && flag_stack_reuse == SR_NONE
+    && ASAN_STACK;
+}
+
+static inline bool
+asan_no_sanitize_address_p (void)
+{
+  return lookup_attribute ("no_sanitize_address",
+			   DECL_ATTRIBUTES (current_function_decl));
+}
+
 #endif /* TREE_ASAN */
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 3d89baf..15b5553 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -58,6 +58,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "value-prof.h"
 #include "builtins.h"
+#include "params.h"
 #include "asan.h"
 #include "cilk.h"
 #include "tree-chkp.h"
diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c
index 4022bdf..1a49e58 100644
--- a/gcc/c-family/c-ubsan.c
+++ b/gcc/c-family/c-ubsan.c
@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "c-family/c-common.h"
 #include "ubsan.h"
 #include "c-family/c-ubsan.h"
+#include "params.h"
 #include "asan.h"
 #include "stor-layout.h"
 #include "builtins.h"
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 21f21c9..1f77cfb 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -876,8 +876,7 @@ asan_sanitize_stack_p (void)
 {
   return ((flag_sanitize & SANITIZE_ADDRESS)
 	  && ASAN_STACK
-	  && !lookup_attribute ("no_sanitize_address",
-				DECL_ATTRIBUTES (current_function_decl)));
+	  && !asan_no_sanitize_address_p ());
 }
 
 /* A subroutine of expand_used_vars.  Binpack the variables into
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 0ea326d..d341478 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "dumpfile.h"
 #include "intl.h"
 #include "c-family/c-ada-spec.h"
+#include "params.h"
 #include "asan.h"
 
 extern cpp_reader *parse_in;
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index 8201676..c7c69ba 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -253,6 +253,7 @@ enum sanitize_code {
   SANITIZE_OBJECT_SIZE = 1UL << 20,
   SANITIZE_VPTR = 1UL << 21,
   SANITIZE_BOUNDS_STRICT = 1UL << 22,
+  SANITIZE_USE_AFTER_SCOPE = 1UL << 23,
   SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE
 		       | SANITIZE_VLA | SANITIZE_NULL | SANITIZE_RETURN
 		       | SANITIZE_SI_OVERFLOW | SANITIZE_BOOL | SANITIZE_ENUM
@@ -261,7 +262,9 @@ enum sanitize_code {
 		       | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
 		       | SANITIZE_OBJECT_SIZE | SANITIZE_VPTR,
   SANITIZE_NONDEFAULT = SANITIZE_FLOAT_DIVIDE | SANITIZE_FLOAT_CAST
-			| SANITIZE_BOUNDS_STRICT
+			| SANITIZE_BOUNDS_STRICT,
+  SANITIZE_ADDRESS_USE_AFTER_SCOPE = SANITIZE_ADDRESS
+			| SANITIZE_USE_AFTER_SCOPE
 };
 
 /* flag_vtable_verify initialization levels. */
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index e223e59..305faaa 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -59,6 +59,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-walk.h"
 #include "langhooks-def.h"	/* FIXME: for lhd_set_decl_assembler_name */
 #include "builtins.h"
+#include "params.h"
+#include "asan.h"
+
+/* Hash set of poisoned variables in a bind expr.  */
+static hash_set <tree> asan_poisoned_variables (13);
 
 enum gimplify_omp_var_data
 {
@@ -1075,6 +1080,29 @@ build_stack_save_restore (gcall **save, gcall **restore)
 			 1, tmp_var);
 }
 
+/* Generate IFN_ASAN_MARK internal call that depending on POISON flag
+   either poisons or unpoisons a DECL.  Created statement is appended
+   to SEQ_P gimple sequence.  */
+
+static void
+asan_poison_variable (tree decl, bool poison, gimple_seq *seq_p)
+{
+  /* When within an OMP context, do not emit ASAN_MARK internal fns.  */
+  if (gimplify_omp_ctxp)
+    return;
+
+  tree unit_size = DECL_SIZE_UNIT (decl);
+  tree base = build_fold_addr_expr (decl);
+
+  HOST_WIDE_INT flags = poison ? ASAN_MARK_CLOBBER : ASAN_MARK_UNCLOBBER;
+
+  gimplify_seq_add_stmt
+    (seq_p, gimple_build_call_internal (IFN_ASAN_MARK, 3,
+					build_int_cst (integer_type_node,
+						       flags),
+					base, unit_size));
+}
+
 /* Gimplify a BIND_EXPR.  Just voidify and recurse.  */
 
 static enum gimplify_status
@@ -1177,6 +1205,10 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
   /* Add clobbers for all variables that go out of scope.  */
   for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
     {
+      if (asan_sanitize_use_after_scope ()
+	  && asan_poisoned_variables.contains (t))
+	asan_poisoned_variables.remove (t);
+
       if (TREE_CODE (t) == VAR_DECL
 	  && !is_global_var (t)
 	  && DECL_CONTEXT (t) == current_function_decl
@@ -1185,17 +1217,25 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
 	  && !DECL_HAS_VALUE_EXPR_P (t)
 	  /* Only care for variables that have to be in memory.  Others
 	     will be rewritten into SSA names, hence moved to the top-level.  */
-	  && !is_gimple_reg (t)
-	  && flag_stack_reuse != SR_NONE)
+	  && !is_gimple_reg (t))
 	{
-	  tree clobber = build_constructor (TREE_TYPE (t), NULL);
-	  gimple *clobber_stmt;
-	  TREE_THIS_VOLATILE (clobber) = 1;
-	  clobber_stmt = gimple_build_assign (t, clobber);
-	  gimple_set_location (clobber_stmt, end_locus);
-	  gimplify_seq_add_stmt (&cleanup, clobber_stmt);
-
-	  if (flag_openacc && oacc_declare_returns != NULL)
+	  if (flag_stack_reuse != SR_NONE)
+	    {
+	      tree clobber = build_constructor (TREE_TYPE (t), NULL);
+	      gimple *clobber_stmt;
+	      TREE_THIS_VOLATILE (clobber) = 1;
+	      clobber_stmt = gimple_build_assign (t, clobber);
+	      gimple_set_location (clobber_stmt, end_locus);
+	      gimplify_seq_add_stmt (&cleanup, clobber_stmt);
+	    }
+
+	  if (asan_sanitize_use_after_scope ()
+	      && !asan_no_sanitize_address_p ())
+	      asan_poison_variable (t, true, &cleanup);
+
+	  if (flag_stack_reuse != SR_NONE
+	      && flag_openacc
+	      && oacc_declare_returns != NULL)
 	    {
 	      tree *c = oacc_declare_returns->get (t);
 	      if (c != NULL)
@@ -1467,6 +1507,21 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
 				   STACK_CHECK_MAX_VAR_SIZE) > 0))
 	gimplify_vla_decl (decl, seq_p);
 
+      tree unit_size = DECL_SIZE_UNIT (decl);
+      if (asan_sanitize_use_after_scope ()
+	  && !asan_no_sanitize_address_p ()
+	  && TREE_CODE (unit_size) == INTEGER_CST
+	  && DECL_NAME (decl) != NULL
+	  && IDENTIFIER_POINTER (DECL_NAME (decl)) != NULL
+	  && !TREE_STATIC (decl))
+	{
+	  TREE_ADDRESSABLE (decl) = 1;
+	  DECL_GIMPLE_REG_P (decl) = 0;
+
+	  asan_poisoned_variables.add (decl);
+	  asan_poison_variable (decl, false, seq_p);
+	}
+
       /* Some front ends do not explicitly declare all anonymous
 	 artificial variables.  We compensate here by declaring the
 	 variables, though it would be better if the front ends would
@@ -10526,6 +10581,14 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 		      == current_function_decl);
 	  gimplify_seq_add_stmt (pre_p,
 			  gimple_build_label (LABEL_EXPR_LABEL (*expr_p)));
+
+	  /* TODO: make a stable sorting of the hash table.  */
+	  if (asan_sanitize_use_after_scope ()
+	      && !asan_no_sanitize_address_p ())
+	    for (hash_set <tree>::iterator it
+		 = asan_poisoned_variables.begin ();
+		 it != asan_poisoned_variables.end (); ++it)
+	      asan_poison_variable (*it, false, pre_p);
 	  break;
 
 	case CASE_LABEL_EXPR:
@@ -11586,7 +11649,11 @@ gimplify_function_tree (tree fndecl)
       && !needs_to_live_in_memory (ret))
     DECL_GIMPLE_REG_P (ret) = 1;
 
+  gcc_checking_assert (!asan_sanitize_use_after_scope ()
+		       || asan_poisoned_variables.elements () == 0);
   bind = gimplify_body (fndecl, true);
+  gcc_checking_assert (!asan_sanitize_use_after_scope ()
+		       || asan_poisoned_variables.elements () == 0);
 
   /* The tree body of the function is no longer needed, replace it
      with the new GIMPLE body.  */
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index e70c73a..14fd4b3 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -234,6 +234,15 @@ expand_ASAN_CHECK (internal_fn, gcall *)
   gcc_unreachable ();
 }
 
+/* This should get expanded in the sanopt pass.  */
+
+static void
+expand_ASAN_MARK (internal_fn, gcall *)
+{
+  gcc_unreachable ();
+}
+
+
 /* This should get expanded in the tsan pass.  */
 
 static void
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index a62f3e8..48b8700 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -158,6 +158,7 @@ DEF_INTERNAL_FN (UBSAN_OBJECT_SIZE, ECF_LEAF | ECF_NOTHROW, NULL)
 DEF_INTERNAL_FN (ABNORMAL_DISPATCHER, ECF_NORETURN, NULL)
 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_TM_PURE | ECF_LEAF | ECF_NOTHROW, ".R..")
 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)
diff --git a/gcc/opts-global.c b/gcc/opts-global.c
index b7e5232..963b542 100644
--- a/gcc/opts-global.c
+++ b/gcc/opts-global.c
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "plugin.h"
 #include "toplev.h"
 #include "context.h"
+#include "params.h"
 #include "asan.h"
 
 typedef const char *const_char_p; /* For DEF_VEC_P.  */
diff --git a/gcc/opts.c b/gcc/opts.c
index 649b84b..40dcf3d 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -1444,6 +1444,8 @@ const struct sanitizer_opts_s sanitizer_opts[] =
 {
 #define SANITIZER_OPT(name, flags) { #name, flags, sizeof #name - 1 }
   SANITIZER_OPT (address, SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS),
+  SANITIZER_OPT (use-after-scope, SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS
+		 | SANITIZE_USE_AFTER_SCOPE),
   SANITIZER_OPT (kernel-address, SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS),
   SANITIZER_OPT (thread, SANITIZE_THREAD),
   SANITIZER_OPT (leak, SANITIZE_LEAK),
diff --git a/gcc/sancov.c b/gcc/sancov.c
index f3211dd..655ff64 100644
--- a/gcc/sancov.c
+++ b/gcc/sancov.c
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-cfg.h"
 #include "tree-pass.h"
 #include "tree-iterator.h"
+#include "params.h"
 #include "asan.h"
 
 namespace {
diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def
index 303c1e4..1c142e9 100644
--- a/gcc/sanitizer.def
+++ b/gcc/sanitizer.def
@@ -165,6 +165,10 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT,
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_AFTER_DYNAMIC_INIT,
 		      "__asan_after_dynamic_init",
 		      BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_CLOBBER_N, "__asan_poison_stack_memory",
+		      BT_FN_VOID_PTR_PTRMODE, 0)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_UNCLOBBER_N, "__asan_unpoison_stack_memory",
+		      BT_FN_VOID_PTR_PTRMODE, 0)
 
 /* Thread Sanitizer */
 DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_INIT, "__tsan_init", 
diff --git a/gcc/sanopt.c b/gcc/sanopt.c
index 2660453..43488a9 100644
--- a/gcc/sanopt.c
+++ b/gcc/sanopt.c
@@ -29,9 +29,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-pretty-print.h"
 #include "fold-const.h"
 #include "gimple-iterator.h"
+#include "params.h"
 #include "asan.h"
 #include "ubsan.h"
-#include "params.h"
 #include "tree-hash-traits.h"
 
 
@@ -704,6 +704,9 @@ pass_sanopt::execute (function *fun)
 		case IFN_ASAN_CHECK:
 		  no_next = asan_expand_check_ifn (&gsi, use_calls);
 		  break;
+		case IFN_ASAN_MARK:
+		  no_next = asan_expand_mark_ifn (&gsi);
+		  break;
 		default:
 		  break;
 		}
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 015a907..4b6d6e2 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -57,6 +57,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "cfgloop.h"
 #include "builtins.h"
 #include "tree-chkp.h"
+#include "params.h"
+#include "asan.h"
 
 
 /* I'm not real happy about this, but we need to handle gimple and
@@ -3214,10 +3216,14 @@ setup_one_parameter (copy_body_data *id, tree p, tree value, tree fn,
 	    }
 	}
       else
-        init_stmt = gimple_build_assign (var, rhs);
+	init_stmt = gimple_build_assign (var, rhs);
+
+      /* Record an inlined variable if we sanitize for use-after-scope.  */
+      if (asan_sanitize_use_after_scope ())
+	asan_inlined_variables.add (var);
 
       if (bb && init_stmt)
-        insert_init_stmt (id, bb, init_stmt);
+	insert_init_stmt (id, bb, init_stmt);
     }
   return init_stmt;
 }
@@ -5439,6 +5445,11 @@ copy_decl_no_change (tree decl, copy_body_data *id)
 
   copy = copy_node (decl);
 
+  if (TREE_CODE (decl) == VAR_DECL
+      && asan_inlined_variables.contains (decl)
+      && asan_sanitize_use_after_scope ())
+    asan_inlined_variables.add (copy);
+
   /* The COPY is not abstract; it will be generated in DST_FN.  */
   DECL_ABSTRACT_P (copy) = false;
   lang_hooks.dup_lang_specific_decl (copy);
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index 2ad2f92..99397eb 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "ipa-chkp.h"
 #include "gomp-constants.h"
+#include "params.h"
 #include "asan.h"
 
 
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 27080d2..14a6081 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -3570,7 +3570,8 @@ vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_in,
 {
   gimple *last_stmt = stmts->pop ();
   enum tree_code rhs_code;
-  tree lhs, rhs1, rhs2, tmp, rhs1_type, rhs2_type, vectype1, vectype2;
+  tree lhs = NULL_TREE, rhs1, rhs2, tmp, rhs1_type, rhs2_type;
+  tree vectype1, vectype2;
   stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
   stmt_vec_info pattern_stmt_info;
   vec_info *vinfo = stmt_vinfo->vinfo;
diff --git a/gcc/tsan.c b/gcc/tsan.c
index 47764bc..bdd002b 100644
--- a/gcc/tsan.c
+++ b/gcc/tsan.c
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-iterator.h"
 #include "tree-ssa-propagate.h"
 #include "tree-ssa-loop-ivopts.h"
+#include "params.h"
 #include "tsan.h"
 #include "asan.h"
 #include "builtins.h"
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index 802341e..cd4953a 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "cfgloop.h"
 #include "ubsan.h"
 #include "expr.h"
+#include "params.h"
 #include "asan.h"
 #include "gimplify-me.h"
 #include "dfp.h"
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 4a7124e..47e5215 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -50,6 +50,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "debug.h"
 #include "common/common-target.h"
+#include "params.h"
 #include "asan.h"
 #include "rtl-iter.h"
 
diff --git a/libsanitizer/asan/asan_poisoning.cc b/libsanitizer/asan/asan_poisoning.cc
index 39f7487..bdadf37 100644
--- a/libsanitizer/asan/asan_poisoning.cc
+++ b/libsanitizer/asan/asan_poisoning.cc
@@ -292,8 +292,9 @@ uptr __asan_load_cxx_array_cookie(uptr *p) {
 static void PoisonAlignedStackMemory(uptr addr, uptr size, bool do_poison) {
   if (size == 0) return;
   uptr aligned_size = size & ~(SHADOW_GRANULARITY - 1);
-  PoisonShadow(addr, aligned_size,
-               do_poison ? kAsanStackUseAfterScopeMagic : 0);
+  if (aligned_size != 0)
+    PoisonShadow(addr, aligned_size,
+		 do_poison ? kAsanStackUseAfterScopeMagic : 0);
   if (size == aligned_size)
     return;
   s8 end_offset = (s8)(size - aligned_size);
-- 
2.8.1


^ permalink raw reply	[flat|nested] 111+ messages in thread

end of thread, other threads:[~2017-01-26 20:47 UTC | newest]

Thread overview: 111+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-06 11:04 [PATCH, RFC] Introduce -fsanitize=use-after-scope Martin Liška
2016-05-06 11:08 ` [PATCH] Introduce tests for -fsanitize=use-after-scope Martin Liška
2016-05-11 12:56   ` Martin Liška
2016-05-06 11:16 ` [PATCH, RFC] Introduce -fsanitize=use-after-scope Martin Liška
2016-05-06 11:48 ` Yury Gribov
2016-05-06 12:39   ` Jakub Jelinek
2016-05-06 13:07     ` Martin Liška
2016-05-06 14:22     ` Yury Gribov
2016-05-06 14:39       ` Jakub Jelinek
2016-05-10 15:03         ` Martin Liška
2016-05-10 15:15           ` Jakub Jelinek
2016-05-06 13:17   ` Martin Liška
2016-05-06 13:25     ` Jakub Jelinek
2016-05-06 14:41       ` Martin Liška
2016-05-06 14:46         ` Jakub Jelinek
2016-05-06 12:22 ` Jakub Jelinek
2016-05-11 12:54   ` Martin Liška
2016-05-12 10:42     ` Jakub Jelinek
2016-05-12 14:12       ` Martin Liška
2016-08-12 12:42         ` Martin Liška
2016-08-18 13:36         ` Jakub Jelinek
2016-10-03  9:27           ` [PATCH, RFC] Introduce -fsanitize=use-after-scope (v2) Martin Liška
2016-10-03  9:30             ` [PATCH, 02/N] Introduce tests for -fsanitize-address-use-after-scope Martin Liška
2016-11-07 10:04               ` [PATCH, 02/N] Introduce tests for -fsanitize-address-use-after-scope (v3) Martin Liška
2016-11-07 10:09                 ` Jakub Jelinek
2016-10-03  9:39             ` [PATCH, RFC] Introduce -fsanitize=use-after-scope (v2) Jakub Jelinek
2016-10-07 11:13             ` Jakub Jelinek
2016-10-12 14:08               ` Martin Liška
2016-10-21 14:26                 ` Jakub Jelinek
2016-10-25 13:18                   ` Martin Liška
2016-10-27 14:40                   ` Martin Liška
2016-10-27 17:24                     ` Jakub Jelinek
2016-11-01 14:48                       ` Martin Liška
2016-11-01 14:54                         ` Jakub Jelinek
2016-11-01 15:01                           ` Martin Liška
2016-11-02  9:36                           ` Martin Liška
2016-11-02  9:59                             ` Jakub Jelinek
2016-11-02 10:09                               ` Martin Liška
2016-11-02 10:11                               ` Jakub Jelinek
2016-11-02 14:20                                 ` Marek Polacek
2016-11-02 14:27                                   ` Martin Liška
2016-11-02 14:35                                     ` Jakub Jelinek
2016-11-04  9:17                                       ` Martin Liška
2016-11-04  9:33                                         ` Jakub Jelinek
2016-11-04 10:59                                           ` Martin Liška
2016-11-07 10:03                                             ` [PATCH, RFC] Introduce -fsanitize=use-after-scope (v3) Martin Liška
2016-11-07 10:08                                               ` Jakub Jelinek
2016-11-08  8:58                                                 ` Question about lambda function variables Martin Liška
2016-11-08  9:12                                                   ` Jakub Jelinek
2016-11-08  9:35                                                     ` Martin Liška
2016-11-07 16:07                                               ` Fix build of jit (was Re: [PATCH, RFC] Introduce -fsanitize=use-after-scope (v3)) David Malcolm
2016-11-07 16:17                                                 ` Jakub Jelinek
2016-11-08  9:38                                                   ` Martin Liška
2016-11-08  9:41                                                     ` Jakub Jelinek
2016-11-08 12:00                                                       ` [PATCH] use-after-scope fallout Martin Liška
2016-11-08 12:10                                                         ` Jakub Jelinek
2016-11-08 18:05                                                         ` David Malcolm
2016-11-01 14:54                       ` [PATCH, RFC] Introduce -fsanitize=use-after-scope (v2) Martin Liška
2016-11-01 15:12                         ` Jakub Jelinek
2016-11-02  9:40                           ` Richard Biener
2016-11-02  9:44                             ` Martin Liška
2016-11-02  9:52                             ` Jakub Jelinek
2016-11-02 12:36                               ` Richard Biener
2016-11-02 12:56                                 ` Jakub Jelinek
2016-11-02 12:59                                   ` Richard Biener
2016-11-02 13:06                                     ` Jakub Jelinek
2016-11-02 13:16                                       ` Richard Biener
2016-11-02 14:38                                         ` Martin Liška
2016-11-02 14:51                                           ` Jakub Jelinek
2016-11-02 15:25                                             ` Martin Liška
2016-11-03 13:34                                             ` Martin Liška
2016-11-03 13:44                                               ` Jakub Jelinek
2016-11-03 14:02                                                 ` Martin Liška
2016-11-03 14:04                                                   ` Jakub Jelinek
2016-11-03 14:18                                                     ` Martin Liška
2016-11-16 12:25                                         ` [RFC][PATCH] Speed-up use-after-scope (re-writing to SSA) Martin Liška
2016-11-16 12:53                                           ` Martin Liška
2016-11-16 13:07                                           ` Jakub Jelinek
2016-11-16 16:01                                             ` Martin Liška
2016-11-16 16:28                                               ` Jakub Jelinek
2016-11-22 11:55                                                 ` Martin Liška
2016-11-23 13:57                                                   ` Martin Liška
2016-11-23 14:14                                                     ` Jakub Jelinek
2016-12-01 16:30                                                       ` Martin Liška
2016-12-02 12:29                                                         ` Richard Biener
2016-12-08 12:51                                                           ` Martin Liška
2016-12-13 14:16                                                             ` Richard Biener
2016-12-20 11:34                                                 ` [PATCH] Speed-up use-after-scope (re-writing to SSA) (version 2) Martin Liška
2016-12-21  9:19                                                   ` Jakub Jelinek
2016-12-22 17:11                                                     ` Martin Liška
2016-12-22 17:28                                                       ` Jakub Jelinek
2017-01-09 14:58                                                         ` Martin Liška
2017-01-16 14:20                                                           ` Jakub Jelinek
2017-01-17 16:22                                                             ` Martin Liška
2017-01-17 16:55                                                               ` Jakub Jelinek
2017-01-18 15:37                                                                 ` Martin Liška
2017-01-19 16:43                                                                   ` Jakub Jelinek
2017-01-20 11:55                                                                     ` Martin Liška
2017-01-20 14:27                                                                       ` Martin Liška
2017-01-20 14:30                                                                         ` Jakub Jelinek
2017-01-20 14:42                                                                           ` Markus Trippelsdorf
2017-01-23  9:38                                                                           ` Martin Liška
2017-01-23  9:39                                                                             ` Jakub Jelinek
2017-01-23 12:07                                                                               ` Martin Liška
2017-01-26  9:04                                                                             ` Thomas Schwinge
2017-01-26 10:55                                                                               ` Jakub Jelinek
2017-01-26 20:45                                                                                 ` Thomas Schwinge
2017-01-26 20:52                                                                                   ` Jakub Jelinek
2016-11-16 16:09                                             ` [RFC][PATCH] Speed-up use-after-scope (re-writing to SSA) Martin Liška
2016-11-02  9:52                           ` [PATCH, RFC] Introduce -fsanitize=use-after-scope (v2) Martin Liška
2016-09-03 15:23         ` [PATCH, RFC] Introduce -fsanitize=use-after-scope Jakub Jelinek

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).