public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Enable -fsanitize-recover for KASan
@ 2014-09-05  6:54 Yury Gribov
  2014-09-05  7:32 ` Dmitry Vyukov
                   ` (2 more replies)
  0 siblings, 3 replies; 73+ messages in thread
From: Yury Gribov @ 2014-09-05  6:54 UTC (permalink / raw)
  To: GCC Patches
  Cc: Jakub Jelinek, Konstantin Serebryany, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

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

Hi all,

This patch enables -fsanitize-recover for KASan by default. This causes 
KASan to continue execution after error in case of inline 
instrumentation. This feature is needed because
- reports during early bootstrap won't even be printed
- needed to run all tests w/o rebooting machine for every test
- needed for interactive work on desktop

Bootstrapped and regtested on x64.

Ok to commit?

-Y

[-- Attachment #2: asan-recover-1.diff --]
[-- Type: text/x-diff, Size: 11892 bytes --]

commit d470f4d1214cbcbebb818778e6f554b346ee43d5
Author: Yury Gribov <y.gribov@samsung.com>
Date:   Fri Aug 29 16:43:42 2014 +0400

    2014-09-05  Yury Gribov  <y.gribov@samsung.com>
    
    gcc/
    	* asan.c (report_error_func): Optionally call recoverable
    	routines.
    	(asan_expand_check_ifn): Likewise.
    	(check_func): Fix formatting.
    	* common.opt (fsanitize-recover): Disable by default.
    	* sanitizer.def: New builtins.
    	* opts.c (common_handle_option): Enable flag_sanitize_recover
    	for UBSan and KASan by default.
    	* flag-types.h (SANITIZE_UNDEFINED_NONDEFAULT): Rename.
    	* gcc.c (sanitize_spec_function): Likewise.
    	* opts.c (common_handle_option): Likewise.
    
    gcc/testsuite/
    	* c-c++-common/asan/recovery-1.c: New test.
    	* c-c++-common/asan/recovery-2.c: New test.
    	* c-c++-common/asan/recovery-common.inc: New file.

diff --git a/gcc/asan.c b/gcc/asan.c
index e6820ea..1d0a26a 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -1373,22 +1373,36 @@ 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, int *nargs)
-{
-  static enum built_in_function report[2][6]
-    = { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
-	  BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
-	  BUILT_IN_ASAN_REPORT_LOAD16, BUILT_IN_ASAN_REPORT_LOAD_N },
-	{ BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2,
-	  BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
-	  BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } };
+report_error_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
+		   int *nargs)
+{
+  static enum built_in_function report[2][2][6]
+    = { { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
+	    BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
+	    BUILT_IN_ASAN_REPORT_LOAD16, BUILT_IN_ASAN_REPORT_LOAD_N },
+	  { BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2,
+	    BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
+	    BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } },
+	{ { BUILT_IN_ASAN_REPORT_RECOVER_LOAD1,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD2,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD4,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD8,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD16,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD_N },
+	  { BUILT_IN_ASAN_REPORT_RECOVER_STORE1,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE2,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE4,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE8,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE16,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE_N } } };
   if (size_in_bytes == -1)
     {
       *nargs = 2;
-      return builtin_decl_implicit (report[is_store][5]);
+      return builtin_decl_implicit (report[recover_p][is_store][5]);
     }
   *nargs = 1;
-  return builtin_decl_implicit (report[is_store][exact_log2 (size_in_bytes)]);
+  int size_log2 = exact_log2 (size_in_bytes);
+  return builtin_decl_implicit (report[recover_p][is_store][size_log2]);
 }
 
 /* Construct a function tree for __asan_{load,store}{1,2,4,8,16,_n}.
@@ -1399,11 +1413,11 @@ check_func (bool is_store, int size_in_bytes, int *nargs)
 {
   static enum built_in_function check[2][6]
     = { { BUILT_IN_ASAN_LOAD1, BUILT_IN_ASAN_LOAD2,
-      BUILT_IN_ASAN_LOAD4, BUILT_IN_ASAN_LOAD8,
-      BUILT_IN_ASAN_LOAD16, BUILT_IN_ASAN_LOADN },
+	  BUILT_IN_ASAN_LOAD4, BUILT_IN_ASAN_LOAD8,
+	  BUILT_IN_ASAN_LOAD16, BUILT_IN_ASAN_LOADN },
 	{ BUILT_IN_ASAN_STORE1, BUILT_IN_ASAN_STORE2,
-      BUILT_IN_ASAN_STORE4, BUILT_IN_ASAN_STORE8,
-      BUILT_IN_ASAN_STORE16, BUILT_IN_ASAN_STOREN } };
+	  BUILT_IN_ASAN_STORE4, BUILT_IN_ASAN_STORE8,
+	  BUILT_IN_ASAN_STORE16, BUILT_IN_ASAN_STOREN } };
   if (size_in_bytes == -1)
     {
       *nargs = 2;
@@ -2574,9 +2588,10 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
   /* Get an iterator on the point where we can add the condition
      statement for the instrumentation.  */
   basic_block then_bb, else_bb;
+  bool create_then_fallthru_edge = flag_sanitize_recover != 0;
   gsi = create_cond_insert_point (&gsi, /*before_p*/false,
 				  /*then_more_likely_p=*/false,
-				  /*create_then_fallthru_edge=*/false,
+				  create_then_fallthru_edge,
 				  &then_bb,
 				  &else_bb);
 
@@ -2675,7 +2690,9 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
   /* Generate call to the run-time library (e.g. __asan_report_load8).  */
   gsi = gsi_start_bb (then_bb);
   int nargs;
-  tree fun = report_error_func (is_store, size_in_bytes, &nargs);
+  tree fun = report_error_func (is_store,
+				/*recover_p*/flag_sanitize_recover != 0,
+				size_in_bytes, &nargs);
   g = gimple_build_call (fun, nargs, base_addr, len);
   gimple_set_location (g, loc);
   gsi_insert_after (&gsi, g, GSI_NEW_STMT);
diff --git a/gcc/builtins.def b/gcc/builtins.def
index cd823a3..261373c 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -176,7 +176,7 @@ along with GCC; see the file COPYING3.  If not see
   DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE,    \
 	       true, true, true, ATTRS, true, \
 	      (flag_sanitize & (SANITIZE_ADDRESS | SANITIZE_THREAD \
-				| SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT)))
+				| SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT)))
 
 #undef DEF_CILKPLUS_BUILTIN
 #define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS)  \
diff --git a/gcc/common.opt b/gcc/common.opt
index 9c9434f..eb8d7e3 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -884,8 +884,8 @@ Common Joined RejectNegative Var(common_deferred_options) Defer
 -fasan-shadow-offset=<string>	Use custom shadow memory offset.
 
 fsanitize-recover
-Common Report Var(flag_sanitize_recover) Init(1)
-After diagnosing undefined behavior attempt to continue execution
+Common Report Var(flag_sanitize_recover)
+After diagnosing error attempt to continue execution
 
 fsanitize-undefined-trap-on-error
 Common Report Var(flag_sanitize_undefined_trap_on_error) Init(0)
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index 135c343..7b4d7e4 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -238,7 +238,7 @@ enum sanitize_code {
 		       | SANITIZE_VLA | SANITIZE_NULL | SANITIZE_RETURN
 		       | SANITIZE_SI_OVERFLOW | SANITIZE_BOOL | SANITIZE_ENUM
 		       | SANITIZE_BOUNDS | SANITIZE_ALIGNMENT,
-  SANITIZE_NONDEFAULT = SANITIZE_FLOAT_DIVIDE | SANITIZE_FLOAT_CAST
+  SANITIZE_UNDEFINED_NONDEFAULT = SANITIZE_FLOAT_DIVIDE | SANITIZE_FLOAT_CAST
 };
 
 /* flag_vtable_verify initialization levels. */
diff --git a/gcc/gcc.c b/gcc/gcc.c
index c550d9d..b2031ed 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -8236,7 +8236,7 @@ sanitize_spec_function (int argc, const char **argv)
   if (strcmp (argv[0], "thread") == 0)
     return (flag_sanitize & SANITIZE_THREAD) ? "" : NULL;
   if (strcmp (argv[0], "undefined") == 0)
-    return ((flag_sanitize & (SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT))
+    return ((flag_sanitize & (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT))
 	    && !flag_sanitize_undefined_trap_on_error) ? "" : NULL;
   if (strcmp (argv[0], "leak") == 0)
     return ((flag_sanitize
diff --git a/gcc/opts.c b/gcc/opts.c
index 496c073..027b648 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -1545,6 +1545,12 @@ common_handle_option (struct gcc_options *opts,
 	if (flag_sanitize & SANITIZE_NULL)
 	  opts->x_flag_delete_null_pointer_checks = 0;
 
+	/* UBSan and KASan enable recovery by default.  */
+	opts->x_flag_sanitize_recover
+	  = !!(flag_sanitize & (SANITIZE_UNDEFINED
+				| SANITIZE_UNDEFINED_NONDEFAULT
+				| SANITIZE_KERNEL_ADDRESS));
+
 	/* Kernel ASan implies normal ASan but does not yet support
 	   all features.  */
 	if (flag_sanitize & SANITIZE_KERNEL_ADDRESS)
diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def
index 1f5ef21..c06823e 100644
--- a/gcc/sanitizer.def
+++ b/gcc/sanitizer.def
@@ -57,6 +57,44 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE16, "__asan_report_store16",
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE_N, "__asan_report_store_n",
 		      BT_FN_VOID_PTR_PTRMODE,
 		      ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD1,
+		      "__asan_report_recover_load1",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD2,
+		      "__asan_report_recover_load2",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD4,
+		      "__asan_report_recover_load4",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD8,
+		      "__asan_report_recover_load8",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD16,
+		      "__asan_report_recover_load16",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD_N,
+		      "__asan_report_recover_load_n",
+		      BT_FN_VOID_PTR_PTRMODE,
+		      ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE1,
+		      "__asan_report_recover_store1",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE2,
+		      "__asan_report_recover_store2",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE4,
+		      "__asan_report_recover_store4",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE8,
+		      "__asan_report_recover_store8",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE16,
+		      "__asan_report_recover_store16",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE_N,
+		      "__asan_report_recover_store_n",
+		      BT_FN_VOID_PTR_PTRMODE,
+		      ATTR_TMPURE_NOTHROW_LEAF_LIST)
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD1, "__asan_load1",
 		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD2, "__asan_load2",
diff --git a/gcc/testsuite/c-c++-common/asan/recovery-1.c b/gcc/testsuite/c-c++-common/asan/recovery-1.c
new file mode 100644
index 0000000..ac3d5a7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/recovery-1.c
@@ -0,0 +1,8 @@
+/* Check that -fsanitize-recover is disabled for ASan by default.  */
+
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include "recovery-common.inc"
+
+/* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
diff --git a/gcc/testsuite/c-c++-common/asan/recovery-2.c b/gcc/testsuite/c-c++-common/asan/recovery-2.c
new file mode 100644
index 0000000..001eb0a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/recovery-2.c
@@ -0,0 +1,6 @@
+/* Check that -fsanitize-recover works for ASan.  */
+
+/* { dg-do run } */
+/* { dg-options "-fsanitize-recover" } */
+
+#include "recovery-common.inc"
diff --git a/gcc/testsuite/c-c++-common/asan/recovery-common.inc b/gcc/testsuite/c-c++-common/asan/recovery-common.inc
new file mode 100644
index 0000000..43f0e10
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/recovery-common.inc
@@ -0,0 +1,31 @@
+#include <sanitizer/asan_interface.h>
+
+#define NREPORTS 5
+
+static int counter = NREPORTS;
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void __attribute__((used))
+__asan_report_recover_store4 (void *p)
+{
+  --counter;
+}
+ 
+void __attribute__((noinline, noclone))
+foo (int *p)
+{
+  *p = 0;
+}
+
+int main ()
+{
+  int x, i;
+  __asan_poison_memory_region (&x, sizeof (x));
+  for (i = 0; i < NREPORTS; ++i)
+    foo (&x);
+  if (counter != 0)
+    __builtin_abort ();
+  return 0;
+}

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

* Re: [PATCH] Enable -fsanitize-recover for KASan
  2014-09-05  6:54 [PATCH] Enable -fsanitize-recover for KASan Yury Gribov
@ 2014-09-05  7:32 ` Dmitry Vyukov
  2014-09-05  8:12   ` Yury Gribov
  2014-09-05  9:05 ` Andrey Ryabinin
  2014-09-15  9:38 ` [PATCH][PING] " Yury Gribov
  2 siblings, 1 reply; 73+ messages in thread
From: Dmitry Vyukov @ 2014-09-05  7:32 UTC (permalink / raw)
  To: Yury Gribov
  Cc: GCC Patches, Jakub Jelinek, Konstantin Serebryany,
	Andrey Ryabinin, Konstantin Khlebnikov

On Fri, Sep 5, 2014 at 10:54 AM, Yury Gribov <y.gribov@samsung.com> wrote:
> Hi all,
>
> This patch enables -fsanitize-recover for KASan by default. This causes
> KASan to continue execution after error in case of inline instrumentation.
> This feature is needed because
> - reports during early bootstrap won't even be printed
> - needed to run all tests w/o rebooting machine for every test
> - needed for interactive work on desktop
>
> Bootstrapped and regtested on x64.
>
> Ok to commit?


Can we do it w/o doubling number of runtime entry points?
Looks like a wrong way to pass global options to runtime. If we need
to pass several other options, number of entry points will sky rocket.
I vaguely remember there are some globals that compiler uses to
communicate configuration (version, shadow base) to runtime. Can we
use them to enable recover mode in runtime?

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

* Re: [PATCH] Enable -fsanitize-recover for KASan
  2014-09-05  7:32 ` Dmitry Vyukov
@ 2014-09-05  8:12   ` Yury Gribov
  2014-09-05  8:23     ` Dmitry Vyukov
  0 siblings, 1 reply; 73+ messages in thread
From: Yury Gribov @ 2014-09-05  8:12 UTC (permalink / raw)
  To: Dmitry Vyukov
  Cc: GCC Patches, Jakub Jelinek, Konstantin Serebryany,
	Andrey Ryabinin, Konstantin Khlebnikov

On 09/05/2014 11:32 AM, Dmitry Vyukov wrote:
> Can we do it w/o doubling number of runtime entry points?

I didn't find a good way to achieve this. See, normal asan reporting 
functions
have a noreturn attribute (defined in sanitizer.def) which can't be changed
depending on cmdline flag.

> Looks like a wrong way to pass global options to runtime.
> If we need
> to pass several other options, number of entry points will sky rocket.

We only need new definitions if functions look significantly different 
for compiler
(noreturn, etc.).

> I vaguely remember there are some globals that compiler uses to
> communicate configuration (version, shadow base) to runtime.

This would make the recovery setting global then.
It may be desirable to have per-object (or even per-function) options 
(or maybe not).

-Y

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

* Re: [PATCH] Enable -fsanitize-recover for KASan
  2014-09-05  8:12   ` Yury Gribov
@ 2014-09-05  8:23     ` Dmitry Vyukov
  2014-09-05  8:33       ` Yury Gribov
  0 siblings, 1 reply; 73+ messages in thread
From: Dmitry Vyukov @ 2014-09-05  8:23 UTC (permalink / raw)
  To: Yury Gribov
  Cc: GCC Patches, Jakub Jelinek, Konstantin Serebryany,
	Andrey Ryabinin, Konstantin Khlebnikov

On Fri, Sep 5, 2014 at 12:12 PM, Yury Gribov <y.gribov@samsung.com> wrote:
> On 09/05/2014 11:32 AM, Dmitry Vyukov wrote:
>>
>> Can we do it w/o doubling number of runtime entry points?
>
>
> I didn't find a good way to achieve this. See, normal asan reporting
> functions
> have a noreturn attribute (defined in sanitizer.def) which can't be changed
> depending on cmdline flag.


I have not looked at the code in detail. But it looks weird to me that
in a general-purpose programming language we can't alter an attribute
of an in-memory object. I would expect that the attribute is just a
field in a struct describing the functionm and the field can be freely
set/reset. Is not it the case?



>> Looks like a wrong way to pass global options to runtime.
>> If we need
>> to pass several other options, number of entry points will sky rocket.
>
>
> We only need new definitions if functions look significantly different for
> compiler
> (noreturn, etc.).
>
>> I vaguely remember there are some globals that compiler uses to
>> communicate configuration (version, shadow base) to runtime.
>
>
> This would make the recovery setting global then.
> It may be desirable to have per-object (or even per-function) options (or
> maybe not).


This makes sense.
Leaving for others to chime in.

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

* Re: [PATCH] Enable -fsanitize-recover for KASan
  2014-09-05  8:23     ` Dmitry Vyukov
@ 2014-09-05  8:33       ` Yury Gribov
  2014-09-05  9:28         ` Jakub Jelinek
  0 siblings, 1 reply; 73+ messages in thread
From: Yury Gribov @ 2014-09-05  8:33 UTC (permalink / raw)
  To: Dmitry Vyukov
  Cc: GCC Patches, Jakub Jelinek, Konstantin Serebryany,
	Andrey Ryabinin, Konstantin Khlebnikov

On 09/05/2014 12:23 PM, Dmitry Vyukov wrote:
>> I didn't find a good way to achieve this. See, normal asan reporting
>> functions
>> have a noreturn attribute (defined in sanitizer.def) which can't be changed
>> depending on cmdline flag.
> I have not looked at the code in detail. But it looks weird to me that
> in a general-purpose programming language we can't alter an attribute
> of an in-memory object.

Well, builtins are described by metadata in .def files
(those are not written in general purpose language).
Post-hacking generated trees sounds ugly...

-Y

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

* Re: [PATCH] Enable -fsanitize-recover for KASan
  2014-09-05  6:54 [PATCH] Enable -fsanitize-recover for KASan Yury Gribov
  2014-09-05  7:32 ` Dmitry Vyukov
@ 2014-09-05  9:05 ` Andrey Ryabinin
  2014-09-05  9:12   ` Yury Gribov
  2014-09-15  9:38 ` [PATCH][PING] " Yury Gribov
  2 siblings, 1 reply; 73+ messages in thread
From: Andrey Ryabinin @ 2014-09-05  9:05 UTC (permalink / raw)
  To: Yury Gribov, GCC Patches
  Cc: Jakub Jelinek, Konstantin Serebryany, Dmitry Vyukov,
	Konstantin Khlebnikov, Konstantin Khlebnikov

On 09/05/2014 10:54 AM, Yury Gribov wrote:
> Hi all,
> 
> This patch enables -fsanitize-recover for KASan by default. This causes KASan to continue execution after error in case of inline instrumentation. This feature is needed because
> - reports during early bootstrap won't even be printed
> - needed to run all tests w/o rebooting machine for every test
> - needed for interactive work on desktop
> 


I just add that this option is required for inline instrumentation in kernel.
There is some places in kernel where we validly touch poisoned memory
and we need to disable error reporting in runtime. For that we use per task variable and check it
__asan_report function and don't print anything if flag is raised.
So there is must be the way to return from report functions.

And how does it work if someone wants to try -fsanitize=address -fsanitize-recover.
Seems you didn't touch libsanitzer in this patch, so I guess this will cause link time error, right ?

> Bootstrapped and regtested on x64.
> 
> Ok to commit?
> 
> -Y

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

* Re: [PATCH] Enable -fsanitize-recover for KASan
  2014-09-05  9:05 ` Andrey Ryabinin
@ 2014-09-05  9:12   ` Yury Gribov
  0 siblings, 0 replies; 73+ messages in thread
From: Yury Gribov @ 2014-09-05  9:12 UTC (permalink / raw)
  To: Andrey Ryabinin, GCC Patches
  Cc: Jakub Jelinek, Konstantin Serebryany, Dmitry Vyukov,
	Konstantin Khlebnikov, Konstantin Khlebnikov

On 09/05/2014 12:59 PM, Andrey Ryabinin wrote:
>And how does it work if someone wants to try -fsanitize=address 
-fsanitize-recover.
> Seems you didn't touch libsanitzer in this patch,
>so I guess this will cause link time error, right ?

Exactly, Asan team does not want recovery mode for userspace Asan.
BTW it may make sense to emit a friendly error message instead
of those link errors.

-Y

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

* Re: [PATCH] Enable -fsanitize-recover for KASan
  2014-09-05  8:33       ` Yury Gribov
@ 2014-09-05  9:28         ` Jakub Jelinek
  2014-09-05  9:32           ` Yury Gribov
  0 siblings, 1 reply; 73+ messages in thread
From: Jakub Jelinek @ 2014-09-05  9:28 UTC (permalink / raw)
  To: Yury Gribov
  Cc: Dmitry Vyukov, GCC Patches, Konstantin Serebryany,
	Andrey Ryabinin, Konstantin Khlebnikov

On Fri, Sep 05, 2014 at 12:33:54PM +0400, Yury Gribov wrote:
> On 09/05/2014 12:23 PM, Dmitry Vyukov wrote:
> >>I didn't find a good way to achieve this. See, normal asan reporting
> >>functions
> >>have a noreturn attribute (defined in sanitizer.def) which can't be changed
> >>depending on cmdline flag.
> >I have not looked at the code in detail. But it looks weird to me that
> >in a general-purpose programming language we can't alter an attribute
> >of an in-memory object.
> 
> Well, builtins are described by metadata in .def files
> (those are not written in general purpose language).
> Post-hacking generated trees sounds ugly...

Note, in ubsan you also have __ubsan_something and __ubsan_something_abort
entrypoints, the latter is noreturn and terminates program, the former
is not and is used for -fsanitize-recover.

Though, for that option the default is yes for ubsan purposes, while asan
wants a default to no, so it is unclear how to solve that.  Either different
option for asan recovery, or tristate option etc.

	Jakub

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

* Re: [PATCH] Enable -fsanitize-recover for KASan
  2014-09-05  9:28         ` Jakub Jelinek
@ 2014-09-05  9:32           ` Yury Gribov
  0 siblings, 0 replies; 73+ messages in thread
From: Yury Gribov @ 2014-09-05  9:32 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Dmitry Vyukov, GCC Patches, Konstantin Serebryany,
	Andrey Ryabinin, Konstantin Khlebnikov

On 09/05/2014 01:28 PM, Jakub Jelinek wrote:
> Though, for that option the default is yes for ubsan purposes, while asan
> wants a default to no, so it is unclear how to solve that.  Either different
> option for asan recovery, or tristate option etc.

Currently I force set it on encountering -fsanitize=... (true for UBSan 
and KASan, false otherwise).
Can do tristate as well.

-Y

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

* [PATCH][PING] Enable -fsanitize-recover for KASan
  2014-09-05  6:54 [PATCH] Enable -fsanitize-recover for KASan Yury Gribov
  2014-09-05  7:32 ` Dmitry Vyukov
  2014-09-05  9:05 ` Andrey Ryabinin
@ 2014-09-15  9:38 ` Yury Gribov
  2014-09-18 10:53   ` Jakub Jelinek
  2014-09-29 17:21   ` [PATCHv3][PING] " Yury Gribov
  2 siblings, 2 replies; 73+ messages in thread
From: Yury Gribov @ 2014-09-15  9:38 UTC (permalink / raw)
  To: GCC Patches
  Cc: Jakub Jelinek, Konstantin Serebryany, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

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

On 09/05/2014 10:54 AM, Yury Gribov wrote:
> Hi all,
>
> This patch enables -fsanitize-recover for KASan by default. This causes
> KASan to continue execution after error in case of inline
> instrumentation. This feature is needed because
> - reports during early bootstrap won't even be printed
> - needed to run all tests w/o rebooting machine for every test
> - needed for interactive work on desktop
>
> Bootstrapped and regtested on x64.
>
> Ok to commit?
>
> -Y

Rebased patch to current trunk.

-Y

[-- Attachment #2: asan-recover-2.diff --]
[-- Type: text/x-diff, Size: 12544 bytes --]

2014-09-15  Yury Gribov  <y.gribov@samsung.com>

gcc/
	* asan.c (report_error_func): Optionally call recoverable
	routines.
	(asan_expand_check_ifn): Likewise.
	(check_func): Fix formatting.
	* common.opt (fsanitize-recover): Disable by default.
	* sanitizer.def: New builtins.
	* opts.c (common_handle_option): Enable flag_sanitize_recover
	for UBSan and KASan by default.
	* flag-types.h (SANITIZE_UNDEFINED_NONDEFAULT): Rename.
	* gcc.c (sanitize_spec_function): Likewise.
	* opts.c (common_handle_option): Likewise.

gcc/testsuite/
	* c-c++-common/asan/recovery-1.c: New test.
	* c-c++-common/asan/recovery-2.c: New test.
	* c-c++-common/asan/recovery-common.inc: New file.

commit 080184e321b49641cd1e3bab2615eaf82164c683
Author: Yury Gribov <y.gribov@samsung.com>
Date:   Fri Aug 29 16:43:42 2014 +0400

    2014-09-04  Yury Gribov  <y.gribov@samsung.com>
    
    gcc/
    	* asan.c (report_error_func): Optionally call recoverable
    	routines.
    	(asan_expand_check_ifn): Likewise.
    	(check_func): Fix formatting.
    	* common.opt (fsanitize-recover): Disable by default.
    	* sanitizer.def: New builtins.
    	* opts.c (common_handle_option): Enable flag_sanitize_recover
    	for UBSan and KASan by default.
    	* flag-types.h (SANITIZE_UNDEFINED_NONDEFAULT): Rename.
    	* gcc.c (sanitize_spec_function): Likewise.
    	* opts.c (common_handle_option): Likewise.
    
    gcc/testsuite/
    	* c-c++-common/asan/recovery-1.c: New test.
    	* c-c++-common/asan/recovery-2.c: New test.
    	* c-c++-common/asan/recovery-common.inc: New file.

diff --git a/gcc/asan.c b/gcc/asan.c
index e6820ea..1d0a26a 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -1373,22 +1373,36 @@ 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, int *nargs)
-{
-  static enum built_in_function report[2][6]
-    = { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
-	  BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
-	  BUILT_IN_ASAN_REPORT_LOAD16, BUILT_IN_ASAN_REPORT_LOAD_N },
-	{ BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2,
-	  BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
-	  BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } };
+report_error_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
+		   int *nargs)
+{
+  static enum built_in_function report[2][2][6]
+    = { { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
+	    BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
+	    BUILT_IN_ASAN_REPORT_LOAD16, BUILT_IN_ASAN_REPORT_LOAD_N },
+	  { BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2,
+	    BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
+	    BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } },
+	{ { BUILT_IN_ASAN_REPORT_RECOVER_LOAD1,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD2,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD4,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD8,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD16,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD_N },
+	  { BUILT_IN_ASAN_REPORT_RECOVER_STORE1,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE2,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE4,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE8,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE16,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE_N } } };
   if (size_in_bytes == -1)
     {
       *nargs = 2;
-      return builtin_decl_implicit (report[is_store][5]);
+      return builtin_decl_implicit (report[recover_p][is_store][5]);
     }
   *nargs = 1;
-  return builtin_decl_implicit (report[is_store][exact_log2 (size_in_bytes)]);
+  int size_log2 = exact_log2 (size_in_bytes);
+  return builtin_decl_implicit (report[recover_p][is_store][size_log2]);
 }
 
 /* Construct a function tree for __asan_{load,store}{1,2,4,8,16,_n}.
@@ -1399,11 +1413,11 @@ check_func (bool is_store, int size_in_bytes, int *nargs)
 {
   static enum built_in_function check[2][6]
     = { { BUILT_IN_ASAN_LOAD1, BUILT_IN_ASAN_LOAD2,
-      BUILT_IN_ASAN_LOAD4, BUILT_IN_ASAN_LOAD8,
-      BUILT_IN_ASAN_LOAD16, BUILT_IN_ASAN_LOADN },
+	  BUILT_IN_ASAN_LOAD4, BUILT_IN_ASAN_LOAD8,
+	  BUILT_IN_ASAN_LOAD16, BUILT_IN_ASAN_LOADN },
 	{ BUILT_IN_ASAN_STORE1, BUILT_IN_ASAN_STORE2,
-      BUILT_IN_ASAN_STORE4, BUILT_IN_ASAN_STORE8,
-      BUILT_IN_ASAN_STORE16, BUILT_IN_ASAN_STOREN } };
+	  BUILT_IN_ASAN_STORE4, BUILT_IN_ASAN_STORE8,
+	  BUILT_IN_ASAN_STORE16, BUILT_IN_ASAN_STOREN } };
   if (size_in_bytes == -1)
     {
       *nargs = 2;
@@ -2574,9 +2588,10 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
   /* Get an iterator on the point where we can add the condition
      statement for the instrumentation.  */
   basic_block then_bb, else_bb;
+  bool create_then_fallthru_edge = flag_sanitize_recover != 0;
   gsi = create_cond_insert_point (&gsi, /*before_p*/false,
 				  /*then_more_likely_p=*/false,
-				  /*create_then_fallthru_edge=*/false,
+				  create_then_fallthru_edge,
 				  &then_bb,
 				  &else_bb);
 
@@ -2675,7 +2690,9 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
   /* Generate call to the run-time library (e.g. __asan_report_load8).  */
   gsi = gsi_start_bb (then_bb);
   int nargs;
-  tree fun = report_error_func (is_store, size_in_bytes, &nargs);
+  tree fun = report_error_func (is_store,
+				/*recover_p*/flag_sanitize_recover != 0,
+				size_in_bytes, &nargs);
   g = gimple_build_call (fun, nargs, base_addr, len);
   gimple_set_location (g, loc);
   gsi_insert_after (&gsi, g, GSI_NEW_STMT);
diff --git a/gcc/builtins.def b/gcc/builtins.def
index cd823a3..261373c 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -176,7 +176,7 @@ along with GCC; see the file COPYING3.  If not see
   DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE,    \
 	       true, true, true, ATTRS, true, \
 	      (flag_sanitize & (SANITIZE_ADDRESS | SANITIZE_THREAD \
-				| SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT)))
+				| SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT)))
 
 #undef DEF_CILKPLUS_BUILTIN
 #define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS)  \
diff --git a/gcc/common.opt b/gcc/common.opt
index 14b9d78..489a21e 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -884,8 +884,8 @@ Common Joined RejectNegative Var(common_deferred_options) Defer
 -fasan-shadow-offset=<string>	Use custom shadow memory offset.
 
 fsanitize-recover
-Common Report Var(flag_sanitize_recover) Init(1)
-After diagnosing undefined behavior attempt to continue execution
+Common Report Var(flag_sanitize_recover)
+After diagnosing error attempt to continue execution
 
 fsanitize-undefined-trap-on-error
 Common Report Var(flag_sanitize_undefined_trap_on_error) Init(0)
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index d0818e5..c9a6e17 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -242,7 +242,7 @@ enum sanitize_code {
 		       | SANITIZE_BOUNDS | SANITIZE_ALIGNMENT
 		       | SANITIZE_NONNULL_ATTRIBUTE
 		       | SANITIZE_RETURNS_NONNULL_ATTRIBUTE,
-  SANITIZE_NONDEFAULT = SANITIZE_FLOAT_DIVIDE | SANITIZE_FLOAT_CAST
+  SANITIZE_UNDEFINED_NONDEFAULT = SANITIZE_FLOAT_DIVIDE | SANITIZE_FLOAT_CAST
 };
 
 /* flag_vtable_verify initialization levels. */
diff --git a/gcc/gcc.c b/gcc/gcc.c
index c550d9d..b2031ed 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -8236,7 +8236,7 @@ sanitize_spec_function (int argc, const char **argv)
   if (strcmp (argv[0], "thread") == 0)
     return (flag_sanitize & SANITIZE_THREAD) ? "" : NULL;
   if (strcmp (argv[0], "undefined") == 0)
-    return ((flag_sanitize & (SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT))
+    return ((flag_sanitize & (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT))
 	    && !flag_sanitize_undefined_trap_on_error) ? "" : NULL;
   if (strcmp (argv[0], "leak") == 0)
     return ((flag_sanitize
diff --git a/gcc/opts.c b/gcc/opts.c
index 774a599..cd00a88 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -1551,6 +1551,12 @@ common_handle_option (struct gcc_options *opts,
 			     | SANITIZE_RETURNS_NONNULL_ATTRIBUTE))
 	  opts->x_flag_delete_null_pointer_checks = 0;
 
+	/* UBSan and KASan enable recovery by default.  */
+	opts->x_flag_sanitize_recover
+	  = !!(flag_sanitize & (SANITIZE_UNDEFINED
+				| SANITIZE_UNDEFINED_NONDEFAULT
+				| SANITIZE_KERNEL_ADDRESS));
+
 	/* Kernel ASan implies normal ASan but does not yet support
 	   all features.  */
 	if (flag_sanitize & SANITIZE_KERNEL_ADDRESS)
diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def
index bba28bd..c61fd25 100644
--- a/gcc/sanitizer.def
+++ b/gcc/sanitizer.def
@@ -57,6 +57,44 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE16, "__asan_report_store16",
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE_N, "__asan_report_store_n",
 		      BT_FN_VOID_PTR_PTRMODE,
 		      ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD1,
+		      "__asan_report_recover_load1",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD2,
+		      "__asan_report_recover_load2",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD4,
+		      "__asan_report_recover_load4",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD8,
+		      "__asan_report_recover_load8",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD16,
+		      "__asan_report_recover_load16",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD_N,
+		      "__asan_report_recover_load_n",
+		      BT_FN_VOID_PTR_PTRMODE,
+		      ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE1,
+		      "__asan_report_recover_store1",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE2,
+		      "__asan_report_recover_store2",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE4,
+		      "__asan_report_recover_store4",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE8,
+		      "__asan_report_recover_store8",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE16,
+		      "__asan_report_recover_store16",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE_N,
+		      "__asan_report_recover_store_n",
+		      BT_FN_VOID_PTR_PTRMODE,
+		      ATTR_TMPURE_NOTHROW_LEAF_LIST)
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD1, "__asan_load1",
 		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD2, "__asan_load2",
diff --git a/gcc/testsuite/c-c++-common/asan/recovery-1.c b/gcc/testsuite/c-c++-common/asan/recovery-1.c
new file mode 100644
index 0000000..ac3d5a7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/recovery-1.c
@@ -0,0 +1,8 @@
+/* Check that -fsanitize-recover is disabled for ASan by default.  */
+
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include "recovery-common.inc"
+
+/* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
diff --git a/gcc/testsuite/c-c++-common/asan/recovery-2.c b/gcc/testsuite/c-c++-common/asan/recovery-2.c
new file mode 100644
index 0000000..001eb0a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/recovery-2.c
@@ -0,0 +1,6 @@
+/* Check that -fsanitize-recover works for ASan.  */
+
+/* { dg-do run } */
+/* { dg-options "-fsanitize-recover" } */
+
+#include "recovery-common.inc"
diff --git a/gcc/testsuite/c-c++-common/asan/recovery-common.inc b/gcc/testsuite/c-c++-common/asan/recovery-common.inc
new file mode 100644
index 0000000..43f0e10
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/recovery-common.inc
@@ -0,0 +1,31 @@
+#include <sanitizer/asan_interface.h>
+
+#define NREPORTS 5
+
+static int counter = NREPORTS;
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void __attribute__((used))
+__asan_report_recover_store4 (void *p)
+{
+  --counter;
+}
+ 
+void __attribute__((noinline, noclone))
+foo (int *p)
+{
+  *p = 0;
+}
+
+int main ()
+{
+  int x, i;
+  __asan_poison_memory_region (&x, sizeof (x));
+  for (i = 0; i < NREPORTS; ++i)
+    foo (&x);
+  if (counter != 0)
+    __builtin_abort ();
+  return 0;
+}

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

* Re: [PATCH][PING] Enable -fsanitize-recover for KASan
  2014-09-15  9:38 ` [PATCH][PING] " Yury Gribov
@ 2014-09-18 10:53   ` Jakub Jelinek
  2014-09-18 13:14     ` Yury Gribov
  2014-09-18 23:47     ` Joseph S. Myers
  2014-09-29 17:21   ` [PATCHv3][PING] " Yury Gribov
  1 sibling, 2 replies; 73+ messages in thread
From: Jakub Jelinek @ 2014-09-18 10:53 UTC (permalink / raw)
  To: Yury Gribov, Joseph S. Myers
  Cc: GCC Patches, Konstantin Serebryany, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On Mon, Sep 15, 2014 at 01:38:42PM +0400, Yury Gribov wrote:
> --- a/gcc/builtins.def
> +++ b/gcc/builtins.def
> @@ -176,7 +176,7 @@ along with GCC; see the file COPYING3.  If not see
>    DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE,    \
>  	       true, true, true, ATTRS, true, \
>  	      (flag_sanitize & (SANITIZE_ADDRESS | SANITIZE_THREAD \
> -				| SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT)))
> +				| SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT)))

This is too long line after the change.

> --- a/gcc/gcc.c
> +++ b/gcc/gcc.c
> @@ -8236,7 +8236,7 @@ sanitize_spec_function (int argc, const char **argv)
>    if (strcmp (argv[0], "thread") == 0)
>      return (flag_sanitize & SANITIZE_THREAD) ? "" : NULL;
>    if (strcmp (argv[0], "undefined") == 0)
> -    return ((flag_sanitize & (SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT))
> +    return ((flag_sanitize & (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT))

Likewise.

> --- a/gcc/opts.c
> +++ b/gcc/opts.c
> @@ -1551,6 +1551,12 @@ common_handle_option (struct gcc_options *opts,
>  			     | SANITIZE_RETURNS_NONNULL_ATTRIBUTE))
>  	  opts->x_flag_delete_null_pointer_checks = 0;
>  
> +	/* UBSan and KASan enable recovery by default.  */
> +	opts->x_flag_sanitize_recover
> +	  = !!(flag_sanitize & (SANITIZE_UNDEFINED
> +				| SANITIZE_UNDEFINED_NONDEFAULT
> +				| SANITIZE_KERNEL_ADDRESS));
> +

Doesn't this override even user supplied -fsanitize-recover or
-fno-sanitize-recover ?  Have you tried both
-fno-sanitize-recover -fsanitize=kernel-address
and
-fsanitize=kernel-address -fno-sanitize-recover
option orders?

Seems for -fdelete-null-pointer-checks we got it wrong too,
IMHO for -fsanitize={null,{,returns-}nonnull-attribute,undefined}
we want to disable it unconditionally, regardless of whether
that option appears on the command line or not.
And we handle it right for 
-fdelete-null-pointer-checks -fsanitize=undefined
but not for
-fsanitize=undefined -fdelete-null-pointer-checks
Joseph, thoughts where to override it instead (I mean, after all
options are processed)?

In the -fsanitize-recover case, I'd on the other side think that
it should just override the default and not override explicit
user's decision.  Which could be done here, but supposedly guarded
with if (!opts_set->x_flag_sanitize_recover)?

I don't think your proposal will work properly though,
if one compiles with
-fsanitize=undefined -fsanitize=address
you'll just get userland asan with error recovery, which is highly
undesirable (not just that it changes the behavior from how it
behaved before, but especially because libasan doesn't contain
such entrypoints at all).
-fsanitize=undefined,address
or
-fsanitize=address,undefined
is normal supported mode and thus I think you either can't reuse
-fsanitize-recover option for what you want to do, or
asan.c needs to limit it to flag_sanitize & SANITIZE_KERNEL_ADDRESS
mode only.  Depends if you ever want to add recovery for userland
sanitization.

	Jakub

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

* Re: [PATCH][PING] Enable -fsanitize-recover for KASan
  2014-09-18 10:53   ` Jakub Jelinek
@ 2014-09-18 13:14     ` Yury Gribov
  2014-09-18 23:47     ` Joseph S. Myers
  1 sibling, 0 replies; 73+ messages in thread
From: Yury Gribov @ 2014-09-18 13:14 UTC (permalink / raw)
  To: Jakub Jelinek, Joseph S. Myers
  Cc: GCC Patches, Konstantin Serebryany, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov, Marek Polacek

Added Marek to comment on proposed UBSan option change.

On 09/18/2014 02:52 PM, Jakub Jelinek wrote:
>> --- a/gcc/opts.c
>> +++ b/gcc/opts.c
>> @@ -1551,6 +1551,12 @@ common_handle_option (struct gcc_options *opts,
>>   			     | SANITIZE_RETURNS_NONNULL_ATTRIBUTE))
>>   	  opts->x_flag_delete_null_pointer_checks = 0;
>>
>> +	/* UBSan and KASan enable recovery by default.  */
>> +	opts->x_flag_sanitize_recover
>> +	  = !!(flag_sanitize & (SANITIZE_UNDEFINED
>> +				| SANITIZE_UNDEFINED_NONDEFAULT
>> +				| SANITIZE_KERNEL_ADDRESS));
>> +
>
> Doesn't this override even user supplied -fsanitize-recover or
> -fno-sanitize-recover ?  Have you tried both
> -fno-sanitize-recover -fsanitize=kernel-address
> and
> -fsanitize=kernel-address -fno-sanitize-recover
> option orders?

I did and this worked in a seemingly logical way:
* -fsanitize=address (disable recovery)
* -fsanitize-recover -fsanitize=address (disable recovery)
* -fsanitize=address -fsanitize-recover (enable recovery)
* -fsanitize=kernel-address (enable recovery)
* -fno-sanitize-recover -fsanitize=kernel-address (enable recovery)
* -fsanitize=kernel-address -fno-sanitize-recover (enable recovery)

> Seems for -fdelete-null-pointer-checks we got it wrong too,
> IMHO for -fsanitize={null,{,returns-}nonnull-attribute,undefined}
> we want to disable it unconditionally, regardless of whether
> that option appears on the command line or not.

My understanding is that all 
-fsanitize=(address|kernel-address|undefined|you-name-it) are simply 
packs of options to enable. User may override any selected option from 
the pack if he so desires.

> I don't think your proposal will work properly though,
> if one compiles with
> -fsanitize=undefined -fsanitize=address
> you'll just get userland asan with error recovery, which is highly
> undesirable

Now that's a problem. Looks like I'll need a separate flag to achieve 
what I need (-fasan-recover? And maybe then rename -fsanitize-recover to 
-fubsan-recover for consistency?).

> or asan.c needs to limit it to flag_sanitize & SANITIZE_KERNEL_ADDRESS
> mode only.

We may want to UBsanitize kernel in future and this may cause the same 
problem as for userspace Asan/UBSan interaction you described above.

 > Depends if you ever want to add recovery for userland
 > sanitization.

Also kernel developers want both recoverable (more user-friendly) and 
non-recoverable (faster) Asan error handling.

-Y

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

* Re: [PATCH][PING] Enable -fsanitize-recover for KASan
  2014-09-18 10:53   ` Jakub Jelinek
  2014-09-18 13:14     ` Yury Gribov
@ 2014-09-18 23:47     ` Joseph S. Myers
  1 sibling, 0 replies; 73+ messages in thread
From: Joseph S. Myers @ 2014-09-18 23:47 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Yury Gribov, GCC Patches, Konstantin Serebryany, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On Thu, 18 Sep 2014, Jakub Jelinek wrote:

> Seems for -fdelete-null-pointer-checks we got it wrong too,
> IMHO for -fsanitize={null,{,returns-}nonnull-attribute,undefined}
> we want to disable it unconditionally, regardless of whether
> that option appears on the command line or not.
> And we handle it right for 
> -fdelete-null-pointer-checks -fsanitize=undefined
> but not for
> -fsanitize=undefined -fdelete-null-pointer-checks
> Joseph, thoughts where to override it instead (I mean, after all
> options are processed)?

finish_options is the obvious place to do that.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-09-15  9:38 ` [PATCH][PING] " Yury Gribov
  2014-09-18 10:53   ` Jakub Jelinek
@ 2014-09-29 17:21   ` Yury Gribov
  2014-09-29 17:44     ` Jakub Jelinek
  2014-10-23  7:15     ` [PATCHv4] " Yury Gribov
  1 sibling, 2 replies; 73+ messages in thread
From: Yury Gribov @ 2014-09-29 17:21 UTC (permalink / raw)
  To: GCC Patches
  Cc: Jakub Jelinek, Konstantin Serebryany, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

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

Hi all,

>> This patch enables -fsanitize-recover for KASan by default. This causes
>> KASan to continue execution after error in case of inline
>> instrumentation. This feature is needed because
>> - reports during early bootstrap won't even be printed
>> - needed to run all tests w/o rebooting machine for every test
>> - needed for interactive work on desktop

This is the third version of patch which renames -fsanitize-recover to 
-fubsan-recover and introduces -fasan-recover (enabled by default for 
KASan). It also moves flag handling to finish_options per Jakub's request.

Bootstrapped and regtested on x64.

-Y

[-- Attachment #2: asan-recover-3.diff --]
[-- Type: text/x-diff, Size: 37240 bytes --]

commit a9451a79bcdcab69856a38d228bec8986c0b0b2a
Author: Yury Gribov <y.gribov@samsung.com>
Date:   Fri Aug 29 16:43:42 2014 +0400

    2014-09-29  Yury Gribov  <y.gribov@samsung.com>
    
    gcc/
    	* asan.c (report_error_func): Optionally call recoverable
    	routines.
    	(asan_expand_check_ifn): Ditto.
    	(check_func): Fix formatting.
    	* common.opt (fasan-recover): New option.
    	(fubsan-recover): Rename.
    	* doc/invoke.texi (-fasan-recover): Document new option.
    	* sanitizer.def: New builtins.
    	* opts.c (common_handle_option): Move default initialization to
    	(finish_options): Here. Also initialize flag_asan_recover.
    	* flag-types.h (SANITIZE_UNDEFINED_NONDEFAULT): Rename.
    	* builtins.def: Ditto.
    	* gcc.c (sanitize_spec_function): Ditto.
    	* opts.c (common_handle_option): Ditto.
    	* ubsan.c (ubsan_expand_bounds_ifn): Rename flag.
    	(ubsan_expand_null_ifn): Ditto.
    	(ubsan_build_overflow_builtin): Ditto.
    	(instrument_bool_enum_load): Ditto.
    	(ubsan_instrument_float_cast): Ditto.
    	(instrument_nonnull_arg): Ditto.
    	(instrument_nonnull_return): Ditto.
    
    gcc/c-family/
    
    	* c-ubsan.c (ubsan_instrument_division): Rename flag_sanitize_recover
    	to flag_ubsan_recover.
    	(ubsan_instrument_shift): Ditto.
    	(ubsan_instrument_vla): Ditto.
    
    gcc/testsuite/
    	* c-c++-common/asan/recovery-1.c: New test.
    	* c-c++-common/ubsan/align-1.c: Rename flag.
    	* c-c++-common/ubsan/align-3.c: Ditto.
    	* c-c++-common/ubsan/bounds-1.c: Ditto.
    	* c-c++-common/ubsan/div-by-zero-7.c: Ditto.
    	* c-c++-common/ubsan/float-cast-overflow-10.c: Ditto.
    	* c-c++-common/ubsan/float-cast-overflow-7.c: Ditto.
    	* c-c++-common/ubsan/float-cast-overflow-8.c: Ditto.
    	* c-c++-common/ubsan/float-cast-overflow-9.c: Ditto.
    	* c-c++-common/ubsan/nonnull-2.c: Ditto.
    	* c-c++-common/ubsan/nonnull-3.c: Ditto.
    	* c-c++-common/ubsan/overflow-1.c: Ditto.
    	* c-c++-common/ubsan/overflow-add-1.c: Ditto.
    	* c-c++-common/ubsan/overflow-add-3.c: Ditto.
    	* c-c++-common/ubsan/overflow-mul-1.c: Ditto.
    	* c-c++-common/ubsan/overflow-mul-3.c: Ditto.
    	* c-c++-common/ubsan/overflow-negate-2.c: Ditto.
    	* c-c++-common/ubsan/overflow-sub-1.c: Ditto.
    	* c-c++-common/ubsan/pr59503.c: Ditto.
    	* c-c++-common/ubsan/pr60613-1.c: Ditto.
    	* c-c++-common/ubsan/save-expr-1.c: Ditto.
    	* c-c++-common/ubsan/shift-3.c: Ditto.
    	* c-c++-common/ubsan/shift-6.c: Ditto.
    	* c-c++-common/ubsan/undefined-1.c: Ditto.
    	* c-c++-common/ubsan/vla-2.c: Ditto.
    	* c-c++-common/ubsan/vla-3.c: Ditto.
    	* c-c++-common/ubsan/vla-4.c: Ditto.
    	* g++.dg/ubsan/cxx11-shift-1.C: Ditto.
    	* g++.dg/ubsan/return-2.C: Ditto.
    
    Conflicts:
    
    	gcc/doc/invoke.texi

diff --git a/gcc/asan.c b/gcc/asan.c
index 63f99f5..fb7a660 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -1376,22 +1376,36 @@ 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, int *nargs)
-{
-  static enum built_in_function report[2][6]
-    = { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
-	  BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
-	  BUILT_IN_ASAN_REPORT_LOAD16, BUILT_IN_ASAN_REPORT_LOAD_N },
-	{ BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2,
-	  BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
-	  BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } };
+report_error_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
+		   int *nargs)
+{
+  static enum built_in_function report[2][2][6]
+    = { { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
+	    BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
+	    BUILT_IN_ASAN_REPORT_LOAD16, BUILT_IN_ASAN_REPORT_LOAD_N },
+	  { BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2,
+	    BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
+	    BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } },
+	{ { BUILT_IN_ASAN_REPORT_RECOVER_LOAD1,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD2,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD4,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD8,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD16,
+	    BUILT_IN_ASAN_REPORT_RECOVER_LOAD_N },
+	  { BUILT_IN_ASAN_REPORT_RECOVER_STORE1,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE2,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE4,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE8,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE16,
+	    BUILT_IN_ASAN_REPORT_RECOVER_STORE_N } } };
   if (size_in_bytes == -1)
     {
       *nargs = 2;
-      return builtin_decl_implicit (report[is_store][5]);
+      return builtin_decl_implicit (report[recover_p][is_store][5]);
     }
   *nargs = 1;
-  return builtin_decl_implicit (report[is_store][exact_log2 (size_in_bytes)]);
+  int size_log2 = exact_log2 (size_in_bytes);
+  return builtin_decl_implicit (report[recover_p][is_store][size_log2]);
 }
 
 /* Construct a function tree for __asan_{load,store}{1,2,4,8,16,_n}.
@@ -1402,11 +1416,11 @@ check_func (bool is_store, int size_in_bytes, int *nargs)
 {
   static enum built_in_function check[2][6]
     = { { BUILT_IN_ASAN_LOAD1, BUILT_IN_ASAN_LOAD2,
-      BUILT_IN_ASAN_LOAD4, BUILT_IN_ASAN_LOAD8,
-      BUILT_IN_ASAN_LOAD16, BUILT_IN_ASAN_LOADN },
+	  BUILT_IN_ASAN_LOAD4, BUILT_IN_ASAN_LOAD8,
+	  BUILT_IN_ASAN_LOAD16, BUILT_IN_ASAN_LOADN },
 	{ BUILT_IN_ASAN_STORE1, BUILT_IN_ASAN_STORE2,
-      BUILT_IN_ASAN_STORE4, BUILT_IN_ASAN_STORE8,
-      BUILT_IN_ASAN_STORE16, BUILT_IN_ASAN_STOREN } };
+	  BUILT_IN_ASAN_STORE4, BUILT_IN_ASAN_STORE8,
+	  BUILT_IN_ASAN_STORE16, BUILT_IN_ASAN_STOREN } };
   if (size_in_bytes == -1)
     {
       *nargs = 2;
@@ -2586,9 +2600,10 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
   /* Get an iterator on the point where we can add the condition
      statement for the instrumentation.  */
   basic_block then_bb, else_bb;
+  bool create_then_fallthru_edge = flag_asan_recover != 0;
   gsi = create_cond_insert_point (&gsi, /*before_p*/false,
 				  /*then_more_likely_p=*/false,
-				  /*create_then_fallthru_edge=*/false,
+				  create_then_fallthru_edge,
 				  &then_bb,
 				  &else_bb);
 
@@ -2697,7 +2712,9 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
   /* Generate call to the run-time library (e.g. __asan_report_load8).  */
   gsi = gsi_start_bb (then_bb);
   int nargs;
-  tree fun = report_error_func (is_store, size_in_bytes, &nargs);
+  tree fun = report_error_func (is_store,
+				/*recover_p*/flag_asan_recover != 0,
+				size_in_bytes, &nargs);
   g = gimple_build_call (fun, nargs, base_addr, len);
   gimple_set_location (g, loc);
   gsi_insert_after (&gsi, g, GSI_NEW_STMT);
diff --git a/gcc/builtins.def b/gcc/builtins.def
index cd823a3..58b0b0e 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -176,7 +176,8 @@ along with GCC; see the file COPYING3.  If not see
   DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE,    \
 	       true, true, true, ATTRS, true, \
 	      (flag_sanitize & (SANITIZE_ADDRESS | SANITIZE_THREAD \
-				| SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT)))
+				| SANITIZE_UNDEFINED \
+				| SANITIZE_UNDEFINED_NONDEFAULT)))
 
 #undef DEF_CILKPLUS_BUILTIN
 #define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS)  \
diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c
index 3539c68..900afd9 100644
--- a/gcc/c-family/c-ubsan.c
+++ b/gcc/c-family/c-ubsan.c
@@ -104,7 +104,7 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
 				     NULL_TREE);
       data = build_fold_addr_expr_loc (loc, data);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= flag_ubsan_recover
 	  ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
 	  : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT;
       tt = builtin_decl_explicit (bcode);
@@ -199,7 +199,7 @@ ubsan_instrument_shift (location_t loc, enum tree_code code,
       data = build_fold_addr_expr_loc (loc, data);
 
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= flag_ubsan_recover
 	  ? BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS
 	  : BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS_ABORT;
       tt = builtin_decl_explicit (bcode);
@@ -229,7 +229,7 @@ ubsan_instrument_vla (location_t loc, tree size)
 				     NULL_TREE);
       data = build_fold_addr_expr_loc (loc, data);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= flag_ubsan_recover
 	  ? BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE
 	  : BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE_ABORT;
       tt = builtin_decl_explicit (bcode);
diff --git a/gcc/common.opt b/gcc/common.opt
index 90f6bd4..e9710e5 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -883,9 +883,13 @@ fasan-shadow-offset=
 Common Joined RejectNegative Var(common_deferred_options) Defer
 -fasan-shadow-offset=<string>	Use custom shadow memory offset.
 
-fsanitize-recover
-Common Report Var(flag_sanitize_recover) Init(1)
-After diagnosing undefined behavior attempt to continue execution
+fasan-recover
+Common Report Var(flag_asan_recover) Init(-1)
+After diagnosing memory error attempt to continue execution
+
+fubsan-recover
+Common Report Var(flag_ubsan_recover) Init(1)
+After diagnosing UBSan error attempt to continue execution
 
 fsanitize-undefined-trap-on-error
 Common Report Var(flag_sanitize_undefined_trap_on_error) Init(0)
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index d9bd1f7..c166ee6 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -296,7 +296,7 @@ Objective-C and Objective-C++ Dialects}.
 @item Debugging Options
 @xref{Debugging Options,,Options for Debugging Your Program or GCC}.
 @gccoptlist{-d@var{letters}  -dumpspecs  -dumpmachine  -dumpversion @gol
--fsanitize=@var{style} -fsanitize-recover @gol
+-fsanitize=@var{style} -fasan-recover -fubsan-recover @gol
 -fasan-shadow-offset=@var{string} -fsanitize-undefined-trap-on-error @gol
 -fdbg-cnt-list -fdbg-cnt=@var{counter-value-list} @gol
 -fdisable-ipa-@var{pass_name} @gol
@@ -5616,15 +5616,24 @@ This option forces GCC to use custom shadow offset in AddressSanitizer checks.
 It is useful for experimenting with different shadow memory layouts in
 kernel AddressSanitizer.
 
-@item -fsanitize-recover
-@opindex fsanitize-recover
+@item -fasan-recover
+@opindex fasan-recover
+By default @option{-fsanitize=kernel-address} sanitization 
+attempts to continue running after reporting memory error.
+This means multiple errors can be reported in a single Linux
+run.  The @option{-fno-asan-recover} can be used to alter
+this behavior, only the first detected error will be reported and
+kernel will panic afterwards.
+
+@item -fubsan-recover
+@opindex fubsan-recover
 By default @option{-fsanitize=undefined} sanitization (and its suboptions
 except for @option{-fsanitize=unreachable} and @option{-fsanitize=return})
 after reporting undefined behavior attempts to continue running the
 program as if no undefined behavior happened.  This means multiple undefined
 behavior runtime errors can be reported in a single program run, and the exit
 code of the program may indicate success even when undefined behavior
-has been reported.  The @option{-fno-sanitize-recover} can be used to alter
+has been reported.  The @option{-fno-ubsan-recover} can be used to alter
 this behavior, only the first detected undefined behavior will be reported
 and program will exit after that with non-zero exit code.
 
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index d0818e5..c9a6e17 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -242,7 +242,7 @@ enum sanitize_code {
 		       | SANITIZE_BOUNDS | SANITIZE_ALIGNMENT
 		       | SANITIZE_NONNULL_ATTRIBUTE
 		       | SANITIZE_RETURNS_NONNULL_ATTRIBUTE,
-  SANITIZE_NONDEFAULT = SANITIZE_FLOAT_DIVIDE | SANITIZE_FLOAT_CAST
+  SANITIZE_UNDEFINED_NONDEFAULT = SANITIZE_FLOAT_DIVIDE | SANITIZE_FLOAT_CAST
 };
 
 /* flag_vtable_verify initialization levels. */
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 47c4e28..f97cdb1 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -8557,7 +8557,8 @@ sanitize_spec_function (int argc, const char **argv)
   if (strcmp (argv[0], "thread") == 0)
     return (flag_sanitize & SANITIZE_THREAD) ? "" : NULL;
   if (strcmp (argv[0], "undefined") == 0)
-    return ((flag_sanitize & (SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT))
+    return ((flag_sanitize & (SANITIZE_UNDEFINED
+			      | SANITIZE_UNDEFINED_NONDEFAULT))
 	    && !flag_sanitize_undefined_trap_on_error) ? "" : NULL;
   if (strcmp (argv[0], "leak") == 0)
     return ((flag_sanitize
diff --git a/gcc/opts.c b/gcc/opts.c
index 774a599..54c3349 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -876,19 +876,50 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
   if (opts->x_dwarf_split_debug_info)
     opts->x_debug_generate_pub_sections = 2;
 
-  /* Userspace and kernel ASan conflict with each other and with TSan.  */
-
+  /* Userspace and kernel ASan conflict with each other.  */
   if ((flag_sanitize & SANITIZE_USER_ADDRESS)
       && (flag_sanitize & SANITIZE_KERNEL_ADDRESS))
     error_at (loc,
-              "-fsanitize=address is incompatible with "
-              "-fsanitize=kernel-address");
+	      "-fsanitize=address is incompatible with "
+	      "-fsanitize=kernel-address");
 
-  if ((flag_sanitize & SANITIZE_ADDRESS)
-      && (flag_sanitize & SANITIZE_THREAD))
+  /* And with TSan.  */
+  if ((flag_sanitize & SANITIZE_ADDRESS) && (flag_sanitize & SANITIZE_THREAD))
     error_at (loc,
-              "-fsanitize=address and -fsanitize=kernel-address "
-              "are incompatible with -fsanitize=thread");
+	      "-fsanitize=address and -fsanitize=kernel-address "
+	      "are incompatible with -fsanitize=thread");
+
+  /* When instrumenting the pointers, we don't want to remove
+     the null pointer checks.  */
+  if (flag_sanitize & (SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
+		       | SANITIZE_RETURNS_NONNULL_ATTRIBUTE))
+    opts->x_flag_delete_null_pointer_checks = 0;
+
+  /* Kernel ASan does not yet support all features.  */
+  if (flag_sanitize & SANITIZE_KERNEL_ADDRESS)
+    {
+      maybe_set_param_value (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD, 0,
+			     opts->x_param_values,
+			     opts_set->x_param_values);
+      maybe_set_param_value (PARAM_ASAN_GLOBALS, 0,
+			     opts->x_param_values,
+			     opts_set->x_param_values);
+      maybe_set_param_value (PARAM_ASAN_STACK, 0,
+			     opts->x_param_values,
+			     opts_set->x_param_values);
+      maybe_set_param_value (PARAM_ASAN_USE_AFTER_RETURN, 0,
+			     opts->x_param_values,
+			     opts_set->x_param_values);
+    }
+
+  /* KASan enables recovery by default.  */
+  if (opts->x_flag_asan_recover == -1)
+    opts->x_flag_asan_recover = !!(flag_sanitize & SANITIZE_KERNEL_ADDRESS);
+
+  /* Userspace ASan does not support recovery.  */
+  if (opts->x_flag_asan_recover && (flag_sanitize & SANITIZE_USER_ADDRESS))
+    warning_at (loc, 0,
+	      "-fsanitize=address does not support -fasan-recover");
 }
 
 #define LEFT_COLUMN	27
@@ -1545,30 +1576,6 @@ common_handle_option (struct gcc_options *opts,
 	    p = comma + 1;
 	  }
 
-	/* When instrumenting the pointers, we don't want to remove
-	   the null pointer checks.  */
-	if (flag_sanitize & (SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
-			     | SANITIZE_RETURNS_NONNULL_ATTRIBUTE))
-	  opts->x_flag_delete_null_pointer_checks = 0;
-
-	/* Kernel ASan implies normal ASan but does not yet support
-	   all features.  */
-	if (flag_sanitize & SANITIZE_KERNEL_ADDRESS)
-	  {
-	    maybe_set_param_value (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD, 0,
-				   opts->x_param_values,
-				   opts_set->x_param_values);
-	    maybe_set_param_value (PARAM_ASAN_GLOBALS, 0,
-				   opts->x_param_values,
-				   opts_set->x_param_values);
-	    maybe_set_param_value (PARAM_ASAN_STACK, 0,
-				   opts->x_param_values,
-				   opts_set->x_param_values);
-	    maybe_set_param_value (PARAM_ASAN_USE_AFTER_RETURN, 0,
-				   opts->x_param_values,
-				   opts_set->x_param_values);
-	  }
-
 	break;
       }
 
diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def
index 722311a..e00237e 100644
--- a/gcc/sanitizer.def
+++ b/gcc/sanitizer.def
@@ -57,6 +57,44 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE16, "__asan_report_store16",
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE_N, "__asan_report_store_n",
 		      BT_FN_VOID_PTR_PTRMODE,
 		      ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD1,
+		      "__asan_report_recover_load1",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD2,
+		      "__asan_report_recover_load2",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD4,
+		      "__asan_report_recover_load4",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD8,
+		      "__asan_report_recover_load8",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD16,
+		      "__asan_report_recover_load16",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_LOAD_N,
+		      "__asan_report_recover_load_n",
+		      BT_FN_VOID_PTR_PTRMODE,
+		      ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE1,
+		      "__asan_report_recover_store1",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE2,
+		      "__asan_report_recover_store2",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE4,
+		      "__asan_report_recover_store4",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE8,
+		      "__asan_report_recover_store8",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE16,
+		      "__asan_report_recover_store16",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_RECOVER_STORE_N,
+		      "__asan_report_recover_store_n",
+		      BT_FN_VOID_PTR_PTRMODE,
+		      ATTR_TMPURE_NOTHROW_LEAF_LIST)
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD1, "__asan_load1",
 		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD2, "__asan_load2",
diff --git a/gcc/testsuite/c-c++-common/asan/recovery-1.c b/gcc/testsuite/c-c++-common/asan/recovery-1.c
new file mode 100644
index 0000000..b037bde
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/recovery-1.c
@@ -0,0 +1,36 @@
+/* { dg-do run } */
+/* { dg-options "-w -fasan-recover" } */
+
+#include <sanitizer/asan_interface.h>
+
+#define NREPORTS 5
+
+static int counter = NREPORTS;
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void __attribute__((used))
+__asan_report_recover_store4 (void *p)
+{
+  --counter;
+}
+ 
+void __attribute__((noinline, noclone))
+foo (int *p)
+{
+  *p = 0;
+}
+
+int
+main ()
+{
+  int x, i;
+  __asan_poison_memory_region (&x, sizeof (x));
+  for (i = 0; i < NREPORTS; ++i)
+    foo (&x);
+  if (counter != 0)
+    __builtin_abort ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/c-c++-common/ubsan/align-1.c b/gcc/testsuite/c-c++-common/ubsan/align-1.c
index 2e40e83..878f969 100644
--- a/gcc/testsuite/c-c++-common/ubsan/align-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/align-1.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=undefined -fno-ubsan-recover" } */
 
 struct S { int a; char b; long long c; short d[10]; };
 struct T { char a; long long b; };
diff --git a/gcc/testsuite/c-c++-common/ubsan/align-3.c b/gcc/testsuite/c-c++-common/ubsan/align-3.c
index a509fa9..6fbece5 100644
--- a/gcc/testsuite/c-c++-common/ubsan/align-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/align-3.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=undefined -fno-ubsan-recover" } */
 
 int c;
 
diff --git a/gcc/testsuite/c-c++-common/ubsan/bounds-1.c b/gcc/testsuite/c-c++-common/ubsan/bounds-1.c
index aa192d3..ec831f3 100644
--- a/gcc/testsuite/c-c++-common/ubsan/bounds-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/bounds-1.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=bounds -fno-sanitize-recover -Wall" } */
+/* { dg-options "-fsanitize=bounds -fno-ubsan-recover -Wall" } */
 
 /* Don't fail on valid uses.  */
 
diff --git a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c
index b65a0bc..c1a0a3e 100644
--- a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c
+++ b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-div-by-zero -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-div-by-zero -fno-ubsan-recover" } */
 /* { dg-shouldfail "ubsan" } */
 
 #include <stdio.h>
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c
index e95f194..1697a6e 100644
--- a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c
@@ -1,6 +1,6 @@
 /* { dg-do run { target dfp } } */
 /* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
-/* { dg-options "-fsanitize=float-cast-overflow -fsanitize-recover" } */
+/* { dg-options "-fsanitize=float-cast-overflow -fubsan-recover" } */
 /* { dg-additional-options "-DUSE_INT128" { target int128 } } */
 /* FIXME: When _DecimalXX <-> {signed, unsigned} __int128 conversions are
    supported, -DBROKEN_DECIMAL_INT128 can be removed.  */
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c
index 3223d5e..68e0c73 100644
--- a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c
@@ -1,6 +1,6 @@
 /* { dg-do run } */
 /* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
-/* { dg-options "-fsanitize=float-cast-overflow -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=float-cast-overflow -fno-ubsan-recover" } */
 /* FIXME: When _DecimalXX <-> {signed, unsigned} __int128 conversions are
    supported, -DBROKEN_DECIMAL_INT128 can be removed.  */
 /* { dg-additional-options "-DUSE_DFP -DBROKEN_DECIMAL_INT128" { target dfp } } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c
index 5414a0b..d1a1c24 100644
--- a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c
@@ -1,6 +1,6 @@
 /* { dg-do run } */
 /* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
-/* { dg-options "-fsanitize=float-cast-overflow -fsanitize-recover -DUSE_FLT_DBL_LDBL" } */
+/* { dg-options "-fsanitize=float-cast-overflow -fubsan-recover -DUSE_FLT_DBL_LDBL" } */
 /* { dg-additional-options "-DUSE_INT128" { target int128 } } */
 
 #include "float-cast-overflow-7.h"
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c
index cadef31..502b11f 100644
--- a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c
@@ -1,6 +1,6 @@
 /* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */
 /* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
-/* { dg-options "-fsanitize=float-cast-overflow -fsanitize-recover -DUSE_FLOAT80 -DUSE_FLOAT128" } */
+/* { dg-options "-fsanitize=float-cast-overflow -fubsan-recover -DUSE_FLOAT80 -DUSE_FLOAT128" } */
 /* { dg-additional-options "-DUSE_INT128" { target int128 } } */
 
 #include "float-cast-overflow-8.c"
diff --git a/gcc/testsuite/c-c++-common/ubsan/nonnull-2.c b/gcc/testsuite/c-c++-common/ubsan/nonnull-2.c
index 49a5cf2..c414dfc 100644
--- a/gcc/testsuite/c-c++-common/ubsan/nonnull-2.c
+++ b/gcc/testsuite/c-c++-common/ubsan/nonnull-2.c
@@ -1,6 +1,6 @@
 /* { dg-do run } */
 /* { dg-shouldfail "ubsan" } */
-/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=undefined -fno-ubsan-recover" } */
 
 int q, r;
 void *a, *b, *c = (void *) &q, *d, *e, *f = (void *) &q, *g, *h;
diff --git a/gcc/testsuite/c-c++-common/ubsan/nonnull-3.c b/gcc/testsuite/c-c++-common/ubsan/nonnull-3.c
index 80018c2..7194594 100644
--- a/gcc/testsuite/c-c++-common/ubsan/nonnull-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/nonnull-3.c
@@ -1,6 +1,6 @@
 /* { dg-do run } */
 /* { dg-shouldfail "ubsan" } */
-/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=undefined -fno-ubsan-recover" } */
 
 int q, r;
 void *a, *b, *c = (void *) &q, *d, *e, *f = (void *) &q, *g, *h;
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-1.c b/gcc/testsuite/c-c++-common/ubsan/overflow-1.c
index b0ef259..da0a8a0 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-1.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -fno-ubsan-recover" } */
 
 #ifndef ASM1
 # define ASM1(a) /* Nothing */
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c b/gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c
index b009f5b..d16f7ab 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-ubsan-recover" } */
 
 #define SCHAR_MAX __SCHAR_MAX__
 #define SHRT_MAX __SHRT_MAX__
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-add-3.c b/gcc/testsuite/c-c++-common/ubsan/overflow-add-3.c
index 6475d10..9cd5793 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-add-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-add-3.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-ubsan-recover" } */
 /* { dg-shouldfail "ubsan" } */
 
 #define INT_MAX __INT_MAX__
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-mul-1.c b/gcc/testsuite/c-c++-common/ubsan/overflow-mul-1.c
index 22ea639..eb08b89 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-mul-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-mul-1.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-ubsan-recover" } */
 
 #define SCHAR_MAX __SCHAR_MAX__
 #define SHRT_MAX __SHRT_MAX__
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-mul-3.c b/gcc/testsuite/c-c++-common/ubsan/overflow-mul-3.c
index 896c0bc..ac74579 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-mul-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-mul-3.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -fno-ubsan-recover" } */
 
 __attribute__((noinline, noclone)) long long
 mul (long long x, long long y)
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-negate-2.c b/gcc/testsuite/c-c++-common/ubsan/overflow-negate-2.c
index 8b5ffa5..5665137 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-negate-2.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-negate-2.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-ubsan-recover" } */
 
 #define SCHAR_MIN (-__SCHAR_MAX__ - 1)
 #define SHRT_MIN (-__SHRT_MAX__ - 1)
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c b/gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c
index 2b10f9e..2734766 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-ubsan-recover" } */
 
 #define SCHAR_MAX __SCHAR_MAX__
 #define SCHAR_MIN (-__SCHAR_MAX__ - 1)
diff --git a/gcc/testsuite/c-c++-common/ubsan/pr59503.c b/gcc/testsuite/c-c++-common/ubsan/pr59503.c
index 81447d7..8ae0a9d 100644
--- a/gcc/testsuite/c-c++-common/ubsan/pr59503.c
+++ b/gcc/testsuite/c-c++-common/ubsan/pr59503.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -fno-ubsan-recover" } */
 
 int
 main (void)
diff --git a/gcc/testsuite/c-c++-common/ubsan/pr60613-1.c b/gcc/testsuite/c-c++-common/ubsan/pr60613-1.c
index 4c0810b..ce94d8b 100644
--- a/gcc/testsuite/c-c++-common/ubsan/pr60613-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/pr60613-1.c
@@ -1,6 +1,6 @@
 /* PR sanitizer/60613 */
 /* { dg-do run } */
-/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=undefined -fno-ubsan-recover" } */
 
 long long y;
 
diff --git a/gcc/testsuite/c-c++-common/ubsan/save-expr-1.c b/gcc/testsuite/c-c++-common/ubsan/save-expr-1.c
index 89ac58c..b808bed 100644
--- a/gcc/testsuite/c-c++-common/ubsan/save-expr-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/save-expr-1.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-fsanitize=shift -Wall -Werror -O -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=shift -Wall -Werror -O -fno-ubsan-recover" } */
 
 static int x;
 int
diff --git a/gcc/testsuite/c-c++-common/ubsan/shift-3.c b/gcc/testsuite/c-c++-common/ubsan/shift-3.c
index 67f1b69..4cba6fb 100644
--- a/gcc/testsuite/c-c++-common/ubsan/shift-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/shift-3.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=shift -w -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=shift -w -fno-ubsan-recover" } */
 
 int
 main (void)
diff --git a/gcc/testsuite/c-c++-common/ubsan/shift-6.c b/gcc/testsuite/c-c++-common/ubsan/shift-6.c
index e26e684..ce44de4 100644
--- a/gcc/testsuite/c-c++-common/ubsan/shift-6.c
+++ b/gcc/testsuite/c-c++-common/ubsan/shift-6.c
@@ -1,6 +1,6 @@
 /* PR sanitizer/58413 */
 /* { dg-do run { target int32plus } } */
-/* { dg-options "-fsanitize=shift -w -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=shift -w -fno-ubsan-recover" } */
 
 int x = 7;
 int
diff --git a/gcc/testsuite/c-c++-common/ubsan/undefined-1.c b/gcc/testsuite/c-c++-common/ubsan/undefined-1.c
index 201818d..1da4413 100644
--- a/gcc/testsuite/c-c++-common/ubsan/undefined-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/undefined-1.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=undefined -fno-ubsan-recover" } */
 
 int
 foo (int x, int y)
diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-2.c b/gcc/testsuite/c-c++-common/ubsan/vla-2.c
index c767042..c714950 100644
--- a/gcc/testsuite/c-c++-common/ubsan/vla-2.c
+++ b/gcc/testsuite/c-c++-common/ubsan/vla-2.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=vla-bound -Wall -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=vla-bound -Wall -Wno-unused-variable -fno-ubsan-recover" } */
 
 int
 main (void)
diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-3.c b/gcc/testsuite/c-c++-common/ubsan/vla-3.c
index 06c6939..9355d24 100644
--- a/gcc/testsuite/c-c++-common/ubsan/vla-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/vla-3.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=vla-bound -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=vla-bound -fno-ubsan-recover" } */
 
 /* Don't instrument the arrays here.  */
 int
diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-4.c b/gcc/testsuite/c-c++-common/ubsan/vla-4.c
index d47f26b..d87f5ad 100644
--- a/gcc/testsuite/c-c++-common/ubsan/vla-4.c
+++ b/gcc/testsuite/c-c++-common/ubsan/vla-4.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=vla-bound -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=vla-bound -fno-ubsan-recover" } */
 
 int
 main (void)
diff --git a/gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C b/gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C
index 23a7b15..67f1f3d 100644
--- a/gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C
+++ b/gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=shift -w -fno-sanitize-recover -std=c++11" } */
+/* { dg-options "-fsanitize=shift -w -fno-ubsan-recover -std=c++11" } */
 
 int
 main (void)
diff --git a/gcc/testsuite/g++.dg/ubsan/return-2.C b/gcc/testsuite/g++.dg/ubsan/return-2.C
index a182999..4f1fdb0 100644
--- a/gcc/testsuite/g++.dg/ubsan/return-2.C
+++ b/gcc/testsuite/g++.dg/ubsan/return-2.C
@@ -1,5 +1,5 @@
 // { dg-do run }
-// { dg-options "-fsanitize=return -fno-sanitize-recover" }
+// { dg-options "-fsanitize=return -fno-ubsan-recover" }
 
 struct S { S (); ~S (); };
 
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index e3128ad..bf0d3b2 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -630,7 +630,7 @@ ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
 			     NULL_TREE, NULL_TREE);
       data = build_fold_addr_expr_loc (loc, data);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= flag_ubsan_recover
 	  ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
 	  : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
       tree fn = builtin_decl_explicit (bcode);
@@ -733,7 +733,7 @@ ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
   else
     {
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= flag_ubsan_recover
 	  ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
 	  : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
       tree fn = builtin_decl_implicit (bcode);
@@ -886,22 +886,22 @@ ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
   switch (code)
     {
     case PLUS_EXPR:
-      fn_code = flag_sanitize_recover
+      fn_code = flag_ubsan_recover
 		? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
 		: BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
       break;
     case MINUS_EXPR:
-      fn_code = flag_sanitize_recover
+      fn_code = flag_ubsan_recover
 		? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
 		: BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
       break;
     case MULT_EXPR:
-      fn_code = flag_sanitize_recover
+      fn_code = flag_ubsan_recover
 		? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
 		: BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
       break;
     case NEGATE_EXPR:
-      fn_code = flag_sanitize_recover
+      fn_code = flag_ubsan_recover
 		? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
 		: BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
       break;
@@ -1078,7 +1078,7 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi)
 				     NULL_TREE);
       data = build_fold_addr_expr_loc (loc, data);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= flag_ubsan_recover
 	  ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
 	  : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
       tree fn = builtin_decl_explicit (bcode);
@@ -1200,7 +1200,7 @@ ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
 				     ubsan_type_descriptor (type), NULL_TREE,
 				     NULL_TREE);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= flag_ubsan_recover
 	  ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
 	  : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
       fn = builtin_decl_explicit (bcode);
@@ -1266,7 +1266,7 @@ instrument_nonnull_arg (gimple_stmt_iterator *gsi)
 					     NULL_TREE);
 	      data = build_fold_addr_expr_loc (loc[0], data);
 	      enum built_in_function bcode
-		= flag_sanitize_recover
+		= flag_ubsan_recover
 		  ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
 		  : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
 	      tree fn = builtin_decl_explicit (bcode);
@@ -1318,7 +1318,7 @@ instrument_nonnull_return (gimple_stmt_iterator *gsi)
 					 2, loc, NULL_TREE, NULL_TREE);
 	  data = build_fold_addr_expr_loc (loc[0], data);
 	  enum built_in_function bcode
-	    = flag_sanitize_recover
+	    = flag_ubsan_recover
 	      ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
 	      : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT;
 	  tree fn = builtin_decl_explicit (bcode);

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-09-29 17:21   ` [PATCHv3][PING] " Yury Gribov
@ 2014-09-29 17:44     ` Jakub Jelinek
  2014-09-29 21:20       ` Konstantin Serebryany
  2014-10-23  7:15     ` [PATCHv4] " Yury Gribov
  1 sibling, 1 reply; 73+ messages in thread
From: Jakub Jelinek @ 2014-09-29 17:44 UTC (permalink / raw)
  To: Yury Gribov
  Cc: GCC Patches, Konstantin Serebryany, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On Mon, Sep 29, 2014 at 09:21:11PM +0400, Yury Gribov wrote:
> >>This patch enables -fsanitize-recover for KASan by default. This causes
> >>KASan to continue execution after error in case of inline
> >>instrumentation. This feature is needed because
> >>- reports during early bootstrap won't even be printed
> >>- needed to run all tests w/o rebooting machine for every test
> >>- needed for interactive work on desktop
> 
> This is the third version of patch which renames -fsanitize-recover to
> -fubsan-recover and introduces -fasan-recover (enabled by default for
> KASan). It also moves flag handling to finish_options per Jakub's request.

As the -fsanitize-recover option comes from clang originally, I think
this needs coordination with them (whether clang will also rename the
option), and certainly keep -fsanitize-recover as a non-documented
compat option alias for -fubsan-recover.
So, can you please talk to the clang folks about it?

	Jakub

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-09-29 17:44     ` Jakub Jelinek
@ 2014-09-29 21:20       ` Konstantin Serebryany
  2014-09-29 22:37         ` Alexey Samsonov
       [not found]         ` <CAGSYnCPwbgZ++2Jt2vE6-ytveSJwSQPZT5umLeKPVWsVjWzwPQ@mail.gmail.com>
  0 siblings, 2 replies; 73+ messages in thread
From: Konstantin Serebryany @ 2014-09-29 21:20 UTC (permalink / raw)
  To: Jakub Jelinek, Alexey Samsonov
  Cc: Yury Gribov, GCC Patches, Dmitry Vyukov, Andrey Ryabinin,
	Konstantin Khlebnikov

+Alexey Samsonov

On Mon, Sep 29, 2014 at 10:43 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Mon, Sep 29, 2014 at 09:21:11PM +0400, Yury Gribov wrote:
>> >>This patch enables -fsanitize-recover for KASan by default. This causes
>> >>KASan to continue execution after error in case of inline
>> >>instrumentation. This feature is needed because
>> >>- reports during early bootstrap won't even be printed
>> >>- needed to run all tests w/o rebooting machine for every test
>> >>- needed for interactive work on desktop
>>
>> This is the third version of patch which renames -fsanitize-recover to
>> -fubsan-recover and introduces -fasan-recover (enabled by default for
>> KASan). It also moves flag handling to finish_options per Jakub's request.
>
> As the -fsanitize-recover option comes from clang originally, I think
> this needs coordination with them (whether clang will also rename the
> option), and certainly keep -fsanitize-recover as a non-documented
> compat option alias for -fubsan-recover.
> So, can you please talk to the clang folks about it?
>
>         Jakub

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-09-29 21:20       ` Konstantin Serebryany
@ 2014-09-29 22:37         ` Alexey Samsonov
       [not found]         ` <CAGSYnCPwbgZ++2Jt2vE6-ytveSJwSQPZT5umLeKPVWsVjWzwPQ@mail.gmail.com>
  1 sibling, 0 replies; 73+ messages in thread
From: Alexey Samsonov @ 2014-09-29 22:37 UTC (permalink / raw)
  To: Konstantin Serebryany
  Cc: Jakub Jelinek, Yury Gribov, GCC Patches, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

(resending in plain-text mode)

-fasan-recover doesn't look like a good idea - for instance, in Clang,
we never use "?san"
in flag names, preferring -fsanitize-whatever. What's the rationale
behind splitting
-fsanitize-recover in two flags (ASan- and UBSan- specific)?
Is there no way to keep a single -f(no-)sanitize-recover for that
purpose? Now it works
only for UBSan checks, but we may extend it to another sanitizers as well.

On Mon, Sep 29, 2014 at 2:20 PM, Konstantin Serebryany
<konstantin.s.serebryany@gmail.com> wrote:
> +Alexey Samsonov
>
> On Mon, Sep 29, 2014 at 10:43 AM, Jakub Jelinek <jakub@redhat.com> wrote:
>> On Mon, Sep 29, 2014 at 09:21:11PM +0400, Yury Gribov wrote:
>>> >>This patch enables -fsanitize-recover for KASan by default. This causes
>>> >>KASan to continue execution after error in case of inline
>>> >>instrumentation. This feature is needed because
>>> >>- reports during early bootstrap won't even be printed
>>> >>- needed to run all tests w/o rebooting machine for every test
>>> >>- needed for interactive work on desktop
>>>
>>> This is the third version of patch which renames -fsanitize-recover to
>>> -fubsan-recover and introduces -fasan-recover (enabled by default for
>>> KASan). It also moves flag handling to finish_options per Jakub's request.
>>
>> As the -fsanitize-recover option comes from clang originally, I think
>> this needs coordination with them (whether clang will also rename the
>> option), and certainly keep -fsanitize-recover as a non-documented
>> compat option alias for -fubsan-recover.
>> So, can you please talk to the clang folks about it?
>>
>>         Jakub



-- 
Alexey Samsonov, Mountain View, CA

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
       [not found]         ` <CAGSYnCPwbgZ++2Jt2vE6-ytveSJwSQPZT5umLeKPVWsVjWzwPQ@mail.gmail.com>
@ 2014-09-29 23:17           ` Jakub Jelinek
  2014-09-29 23:26             ` Alexey Samsonov
  0 siblings, 1 reply; 73+ messages in thread
From: Jakub Jelinek @ 2014-09-29 23:17 UTC (permalink / raw)
  To: Alexey Samsonov
  Cc: Konstantin Serebryany, Yury Gribov, GCC Patches, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On Mon, Sep 29, 2014 at 03:36:20PM -0700, Alexey Samsonov wrote:
> -fasan-recover doesn't look like a good idea - for instance, in Clang, we
> never use "?san"
> in flag names, preferring -fsanitize-whatever. What's the rationale behind
> splitting
> -fsanitize-recover in two flags (ASan- and UBSan- specific)?
> Is there no way to keep a single -f(no-)sanitize-recover for that purpose?
> Now it works
> only for UBSan checks, but we may extend it to another sanitizers as well.

The problem is that if we start using it for ASan, it needs to have a
different default, because ASan wants to abort by default, while UBSan
recover by default.  -fsanitize=kernel-address w (KASan) wants to recover
by default.  So, the option is either to never support recover for
-fsanitize=address, for ubsan keep -fsanitize-recover (by default) as is
and for kasan use that same switch, or have separate flags.

	Jakub

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-09-29 23:17           ` Jakub Jelinek
@ 2014-09-29 23:26             ` Alexey Samsonov
  2014-09-30  0:24               ` Konstantin Serebryany
  0 siblings, 1 reply; 73+ messages in thread
From: Alexey Samsonov @ 2014-09-29 23:26 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Konstantin Serebryany, Yury Gribov, GCC Patches, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On Mon, Sep 29, 2014 at 4:17 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Mon, Sep 29, 2014 at 03:36:20PM -0700, Alexey Samsonov wrote:
>> -fasan-recover doesn't look like a good idea - for instance, in Clang, we
>> never use "?san"
>> in flag names, preferring -fsanitize-whatever. What's the rationale behind
>> splitting
>> -fsanitize-recover in two flags (ASan- and UBSan- specific)?
>> Is there no way to keep a single -f(no-)sanitize-recover for that purpose?
>> Now it works
>> only for UBSan checks, but we may extend it to another sanitizers as well.
>
> The problem is that if we start using it for ASan, it needs to have a
> different default, because ASan wants to abort by default, while UBSan
> recover by default.  -fsanitize=kernel-address w (KASan) wants to recover
> by default.  So, the option is either to never support recover for
> -fsanitize=address, for ubsan keep -fsanitize-recover (by default) as is
> and for kasan use that same switch, or have separate flags.
>
>         Jakub

I don't think we ever going to support recovery for regular ASan
(Kostya, correct me if I'm wrong).
I see no problem in enabling -fsanitize-recover by default for
-fsanitize=undefined and
-fsanitize=kernel-address. We can, potentially, extend
-fsanitize-recover flag to take the same values as -fsanitize= one,
so that one can specify which sanitizers are recoverable, and which
are not, but I'd try to make this a last resort - this is too complex.

-- 
Alexey Samsonov, Mountain View, CA

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-09-29 23:26             ` Alexey Samsonov
@ 2014-09-30  0:24               ` Konstantin Serebryany
  2014-09-30  1:05                 ` Alexey Samsonov
                                   ` (2 more replies)
  0 siblings, 3 replies; 73+ messages in thread
From: Konstantin Serebryany @ 2014-09-30  0:24 UTC (permalink / raw)
  To: Alexey Samsonov
  Cc: Jakub Jelinek, Yury Gribov, GCC Patches, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On Mon, Sep 29, 2014 at 4:26 PM, Alexey Samsonov <samsonov@google.com> wrote:
> On Mon, Sep 29, 2014 at 4:17 PM, Jakub Jelinek <jakub@redhat.com> wrote:
>> On Mon, Sep 29, 2014 at 03:36:20PM -0700, Alexey Samsonov wrote:
>>> -fasan-recover doesn't look like a good idea - for instance, in Clang, we
>>> never use "?san"
>>> in flag names, preferring -fsanitize-whatever. What's the rationale behind
>>> splitting
>>> -fsanitize-recover in two flags (ASan- and UBSan- specific)?
>>> Is there no way to keep a single -f(no-)sanitize-recover for that purpose?
>>> Now it works
>>> only for UBSan checks, but we may extend it to another sanitizers as well.
>>
>> The problem is that if we start using it for ASan, it needs to have a
>> different default, because ASan wants to abort by default, while UBSan
>> recover by default.  -fsanitize=kernel-address w (KASan) wants to recover
>> by default.  So, the option is either to never support recover for
>> -fsanitize=address, for ubsan keep -fsanitize-recover (by default) as is
>> and for kasan use that same switch, or have separate flags.
>>
>>         Jakub
>
> I don't think we ever going to support recovery for regular ASan
> (Kostya, correct me if I'm wrong).

I hope so too.
Another point is that with asan-instrumentation-with-call-threshold=0
(instrumentation with callbacks)
we can and probably will allow to recover from errors (glibc demands that),
but that does not require any compile-time flag.


> I see no problem in enabling -fsanitize-recover by default for
> -fsanitize=undefined and

This becomes more interesting when we use asan and ubsan together.
Which default setting is stronger? :)

> -fsanitize=kernel-address. We can, potentially, extend
> -fsanitize-recover flag to take the same values as -fsanitize= one,
> so that one can specify which sanitizers are recoverable, and which
> are not, but I'd try to make this a last resort - this is too complex.
>
> --
> Alexey Samsonov, Mountain View, CA

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-09-30  0:24               ` Konstantin Serebryany
@ 2014-09-30  1:05                 ` Alexey Samsonov
  2014-09-30  1:49                   ` Konstantin Serebryany
  2014-09-30  5:40                 ` Jakub Jelinek
  2014-09-30  6:57                 ` [PATCHv3][PING] Enable -fsanitize-recover for KASan Yury Gribov
  2 siblings, 1 reply; 73+ messages in thread
From: Alexey Samsonov @ 2014-09-30  1:05 UTC (permalink / raw)
  To: Konstantin Serebryany
  Cc: Jakub Jelinek, Yury Gribov, GCC Patches, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On Mon, Sep 29, 2014 at 5:24 PM, Konstantin Serebryany
<konstantin.s.serebryany@gmail.com> wrote:
>
> On Mon, Sep 29, 2014 at 4:26 PM, Alexey Samsonov <samsonov@google.com> wrote:
> > On Mon, Sep 29, 2014 at 4:17 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> >> On Mon, Sep 29, 2014 at 03:36:20PM -0700, Alexey Samsonov wrote:
> >>> -fasan-recover doesn't look like a good idea - for instance, in Clang, we
> >>> never use "?san"
> >>> in flag names, preferring -fsanitize-whatever. What's the rationale behind
> >>> splitting
> >>> -fsanitize-recover in two flags (ASan- and UBSan- specific)?
> >>> Is there no way to keep a single -f(no-)sanitize-recover for that purpose?
> >>> Now it works
> >>> only for UBSan checks, but we may extend it to another sanitizers as well.
> >>
> >> The problem is that if we start using it for ASan, it needs to have a
> >> different default, because ASan wants to abort by default, while UBSan
> >> recover by default.  -fsanitize=kernel-address w (KASan) wants to recover
> >> by default.  So, the option is either to never support recover for
> >> -fsanitize=address, for ubsan keep -fsanitize-recover (by default) as is
> >> and for kasan use that same switch, or have separate flags.
> >>
> >>         Jakub
> >
> > I don't think we ever going to support recovery for regular ASan
> > (Kostya, correct me if I'm wrong).
>
> I hope so too.
> Another point is that with asan-instrumentation-with-call-threshold=0
> (instrumentation with callbacks)
> we can and probably will allow to recover from errors (glibc demands that),
> but that does not require any compile-time flag.


So, if we switch to instrumentation to callbacks (which are not
necessarily noreturn),
-fsanitize-recover is the thing we plan to support?

>
>
>
> > I see no problem in enabling -fsanitize-recover by default for
> > -fsanitize=undefined and
>
> This becomes more interesting when we use asan and ubsan together.
> Which default setting is stronger? :)

We can preserve the default behavior for each tool (no recovery for
ASan, recovery for UBSan)
unless recovery mode is explicitly specified.

>
> > -fsanitize=kernel-address. We can, potentially, extend
> > -fsanitize-recover flag to take the same values as -fsanitize= one,
> > so that one can specify which sanitizers are recoverable, and which
> > are not, but I'd try to make this a last resort - this is too complex.
> >
> > --
> > Alexey Samsonov, Mountain View, CA




-- 
Alexey Samsonov, Mountain View, CA

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-09-30  1:05                 ` Alexey Samsonov
@ 2014-09-30  1:49                   ` Konstantin Serebryany
  0 siblings, 0 replies; 73+ messages in thread
From: Konstantin Serebryany @ 2014-09-30  1:49 UTC (permalink / raw)
  To: Alexey Samsonov
  Cc: Jakub Jelinek, Yury Gribov, GCC Patches, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On Mon, Sep 29, 2014 at 6:05 PM, Alexey Samsonov <samsonov@google.com> wrote:
> On Mon, Sep 29, 2014 at 5:24 PM, Konstantin Serebryany
> <konstantin.s.serebryany@gmail.com> wrote:
>>
>> On Mon, Sep 29, 2014 at 4:26 PM, Alexey Samsonov <samsonov@google.com> wrote:
>> > On Mon, Sep 29, 2014 at 4:17 PM, Jakub Jelinek <jakub@redhat.com> wrote:
>> >> On Mon, Sep 29, 2014 at 03:36:20PM -0700, Alexey Samsonov wrote:
>> >>> -fasan-recover doesn't look like a good idea - for instance, in Clang, we
>> >>> never use "?san"
>> >>> in flag names, preferring -fsanitize-whatever. What's the rationale behind
>> >>> splitting
>> >>> -fsanitize-recover in two flags (ASan- and UBSan- specific)?
>> >>> Is there no way to keep a single -f(no-)sanitize-recover for that purpose?
>> >>> Now it works
>> >>> only for UBSan checks, but we may extend it to another sanitizers as well.
>> >>
>> >> The problem is that if we start using it for ASan, it needs to have a
>> >> different default, because ASan wants to abort by default, while UBSan
>> >> recover by default.  -fsanitize=kernel-address w (KASan) wants to recover
>> >> by default.  So, the option is either to never support recover for
>> >> -fsanitize=address, for ubsan keep -fsanitize-recover (by default) as is
>> >> and for kasan use that same switch, or have separate flags.
>> >>
>> >>         Jakub
>> >
>> > I don't think we ever going to support recovery for regular ASan
>> > (Kostya, correct me if I'm wrong).
>>
>> I hope so too.
>> Another point is that with asan-instrumentation-with-call-threshold=0
>> (instrumentation with callbacks)
>> we can and probably will allow to recover from errors (glibc demands that),
>> but that does not require any compile-time flag.
>
>
> So, if we switch to instrumentation to callbacks (which are not
> necessarily noreturn),
> -fsanitize-recover is the thing we plan to support?

Yes, but this will not involve any additional compile-time flag

>
>>
>>
>>
>> > I see no problem in enabling -fsanitize-recover by default for
>> > -fsanitize=undefined and
>>
>> This becomes more interesting when we use asan and ubsan together.
>> Which default setting is stronger? :)
>
> We can preserve the default behavior for each tool (no recovery for
> ASan, recovery for UBSan)
> unless recovery mode is explicitly specified.
>
>>
>> > -fsanitize=kernel-address. We can, potentially, extend
>> > -fsanitize-recover flag to take the same values as -fsanitize= one,
>> > so that one can specify which sanitizers are recoverable, and which
>> > are not, but I'd try to make this a last resort - this is too complex.
>> >
>> > --
>> > Alexey Samsonov, Mountain View, CA
>
>
>
>
> --
> Alexey Samsonov, Mountain View, CA

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-09-30  0:24               ` Konstantin Serebryany
  2014-09-30  1:05                 ` Alexey Samsonov
@ 2014-09-30  5:40                 ` Jakub Jelinek
  2014-09-30  7:07                   ` Yury Gribov
  2014-09-30  6:57                 ` [PATCHv3][PING] Enable -fsanitize-recover for KASan Yury Gribov
  2 siblings, 1 reply; 73+ messages in thread
From: Jakub Jelinek @ 2014-09-30  5:40 UTC (permalink / raw)
  To: Konstantin Serebryany
  Cc: Alexey Samsonov, Yury Gribov, GCC Patches, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On Mon, Sep 29, 2014 at 05:24:02PM -0700, Konstantin Serebryany wrote:
> > I don't think we ever going to support recovery for regular ASan
> > (Kostya, correct me if I'm wrong).
> 
> I hope so too.
> Another point is that with asan-instrumentation-with-call-threshold=0
> (instrumentation with callbacks)

The normal (non-recovery) callbacks are __attribute__((noreturn)) for
performance reasons, and you do need different callbacks and different
generated code if you want to recover (after the callback you need jump
back to a basic block after the conditional jump).
So, in that case you would need -fsanitize-recover=address.

> > I see no problem in enabling -fsanitize-recover by default for
> > -fsanitize=undefined and
> 
> This becomes more interesting when we use asan and ubsan together.

That is fairly common case.

	Jakub

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-09-30  0:24               ` Konstantin Serebryany
  2014-09-30  1:05                 ` Alexey Samsonov
  2014-09-30  5:40                 ` Jakub Jelinek
@ 2014-09-30  6:57                 ` Yury Gribov
  2014-09-30  7:14                   ` Yury Gribov
  2 siblings, 1 reply; 73+ messages in thread
From: Yury Gribov @ 2014-09-30  6:57 UTC (permalink / raw)
  To: Konstantin Serebryany, Alexey Samsonov
  Cc: Jakub Jelinek, GCC Patches, Dmitry Vyukov, Andrey Ryabinin,
	Konstantin Khlebnikov

On 09/30/2014 04:24 AM, Konstantin Serebryany wrote:
> On Mon, Sep 29, 2014 at 4:26 PM, Alexey Samsonov <samsonov@google.com> wrote:
>> I don't think we ever going to support recovery for regular ASan
>> (Kostya, correct me if I'm wrong).
>
> I hope so too.
> Another point is that with asan-instrumentation-with-call-threshold=0
> (instrumentation with callbacks)
> we can and probably will allow to recover from errors (glibc demands that),
> but that does not require any compile-time flag.

I don't know details but are you absolutely sure that you won't want to 
do inline instrumentation of glibc in the future? This would then 
require -fasan-recover.

-Y

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-09-30  5:40                 ` Jakub Jelinek
@ 2014-09-30  7:07                   ` Yury Gribov
  2014-09-30 17:26                     ` Alexey Samsonov
  0 siblings, 1 reply; 73+ messages in thread
From: Yury Gribov @ 2014-09-30  7:07 UTC (permalink / raw)
  To: Jakub Jelinek, Konstantin Serebryany
  Cc: Alexey Samsonov, GCC Patches, Dmitry Vyukov, Andrey Ryabinin,
	Konstantin Khlebnikov

On 09/30/2014 09:40 AM, Jakub Jelinek wrote:
> On Mon, Sep 29, 2014 at 05:24:02PM -0700, Konstantin Serebryany wrote:
>>> I don't think we ever going to support recovery for regular ASan
>>> (Kostya, correct me if I'm wrong).
>>
>> I hope so too.
>> Another point is that with asan-instrumentation-with-call-threshold=0
>> (instrumentation with callbacks)
>
> The normal (non-recovery) callbacks are __attribute__((noreturn)) for
> performance reasons, and you do need different callbacks and different
> generated code if you want to recover (after the callback you need jump
> back to a basic block after the conditional jump).
> So, in that case you would need -fsanitize-recover=address.
>
>>> I see no problem in enabling -fsanitize-recover by default for
>>> -fsanitize=undefined and
>>
>> This becomes more interesting when we use asan and ubsan together.
>
> That is fairly common case.

I think we can summarize:
* the current option -fsanitize-recover is misleading; it's really 
-fubsan-recover
* we need a way to selectively enable/disable recovery for different 
sanitizers

The most promininet solution seems to be
* allow -fsanitize-recover=tgt1,tgt2 syntax
* -fsanitize-recover wo options would still mean UBSan recovery

The question is what to do with -fno-sanitize-recover then.

-Y

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-09-30  6:57                 ` [PATCHv3][PING] Enable -fsanitize-recover for KASan Yury Gribov
@ 2014-09-30  7:14                   ` Yury Gribov
  0 siblings, 0 replies; 73+ messages in thread
From: Yury Gribov @ 2014-09-30  7:14 UTC (permalink / raw)
  To: Konstantin Serebryany, Alexey Samsonov
  Cc: Jakub Jelinek, GCC Patches, Dmitry Vyukov, Andrey Ryabinin,
	Konstantin Khlebnikov

On 09/30/2014 10:56 AM, Yury Gribov wrote:
> On 09/30/2014 04:24 AM, Konstantin Serebryany wrote:
>> On Mon, Sep 29, 2014 at 4:26 PM, Alexey Samsonov <samsonov@google.com>
>> wrote:
>>> I don't think we ever going to support recovery for regular ASan
>>> (Kostya, correct me if I'm wrong).
>>
>> I hope so too.
>> Another point is that with asan-instrumentation-with-call-threshold=0
>> (instrumentation with callbacks)
>> we can and probably will allow to recover from errors (glibc demands
>> that),
>> but that does not require any compile-time flag.
>
> I don't know details but are you absolutely sure that you won't want to
> do inline instrumentation of glibc in the future? This would then
> require -fasan-recover.

FYI in kernel we had exactly this situation: outline instrumentation 
allowed us to hide recovery inside callbacks but then turned out to be 
too slow so we are now switching back to inline instrumentation (which 
requires -fasan-recovery).

-Y

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-09-30  7:07                   ` Yury Gribov
@ 2014-09-30 17:26                     ` Alexey Samsonov
  2014-09-30 17:33                       ` Jakub Jelinek
  0 siblings, 1 reply; 73+ messages in thread
From: Alexey Samsonov @ 2014-09-30 17:26 UTC (permalink / raw)
  To: Yury Gribov
  Cc: Jakub Jelinek, Konstantin Serebryany, GCC Patches, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On Tue, Sep 30, 2014 at 12:07 AM, Yury Gribov <y.gribov@samsung.com> wrote:
> On 09/30/2014 09:40 AM, Jakub Jelinek wrote:
>>
>> On Mon, Sep 29, 2014 at 05:24:02PM -0700, Konstantin Serebryany wrote:
>>>>
>>>> I don't think we ever going to support recovery for regular ASan
>>>> (Kostya, correct me if I'm wrong).
>>>
>>>
>>> I hope so too.
>>> Another point is that with asan-instrumentation-with-call-threshold=0
>>> (instrumentation with callbacks)
>>
>>
>> The normal (non-recovery) callbacks are __attribute__((noreturn)) for
>> performance reasons, and you do need different callbacks and different
>> generated code if you want to recover (after the callback you need jump
>> back to a basic block after the conditional jump).
>> So, in that case you would need -fsanitize-recover=address.
>>
>>>> I see no problem in enabling -fsanitize-recover by default for
>>>> -fsanitize=undefined and
>>>
>>>
>>> This becomes more interesting when we use asan and ubsan together.
>>
>>
>> That is fairly common case.
>
>
> I think we can summarize:
> * the current option -fsanitize-recover is misleading; it's really
> -fubsan-recover
> * we need a way to selectively enable/disable recovery for different
> sanitizers
>
> The most promininet solution seems to be
> * allow -fsanitize-recover=tgt1,tgt2 syntax
> * -fsanitize-recover wo options would still mean UBSan recovery
>
> The question is what to do with -fno-sanitize-recover then.

We can make -f(no-)?sanitize-recover= flags accept the same values as
-f(no-)?sanitize= flags. In this case,

"-fsanitize-recover" will be a deprecated alias of
"-fsanitize-recover=undefined", and
"-fno-sanitize-recover" will be a deprecated alias of
"-fno-sanitize-recover=undefined".
If a user provides "-fsanitize-recover=address", we can instruct the
instrumentation pass to
use recoverable instrumentation.

>
> -Y
>



-- 
Alexey Samsonov, Mountain View, CA

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-09-30 17:26                     ` Alexey Samsonov
@ 2014-09-30 17:33                       ` Jakub Jelinek
  2014-09-30 17:36                         ` Alexey Samsonov
  0 siblings, 1 reply; 73+ messages in thread
From: Jakub Jelinek @ 2014-09-30 17:33 UTC (permalink / raw)
  To: Alexey Samsonov
  Cc: Yury Gribov, Konstantin Serebryany, GCC Patches, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On Tue, Sep 30, 2014 at 10:26:39AM -0700, Alexey Samsonov wrote:
> > I think we can summarize:
> > * the current option -fsanitize-recover is misleading; it's really
> > -fubsan-recover
> > * we need a way to selectively enable/disable recovery for different
> > sanitizers
> >
> > The most promininet solution seems to be
> > * allow -fsanitize-recover=tgt1,tgt2 syntax
> > * -fsanitize-recover wo options would still mean UBSan recovery
> >
> > The question is what to do with -fno-sanitize-recover then.
> 
> We can make -f(no-)?sanitize-recover= flags accept the same values as
> -f(no-)?sanitize= flags. In this case,
> 
> "-fsanitize-recover" will be a deprecated alias of
> "-fsanitize-recover=undefined", and
> "-fno-sanitize-recover" will be a deprecated alias of
> "-fno-sanitize-recover=undefined".
> If a user provides "-fsanitize-recover=address", we can instruct the
> instrumentation pass to
> use recoverable instrumentation.

Would we accept -fsanitize-recover=undefined -fno-sanitize-recover=signed-integer-overflow
as recovering everything but signed integer overflows, i.e. the decision
whether to recover a particular call would check similar bitmask as
is checked whether to sanitize something at all?

	Jakub

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-09-30 17:33                       ` Jakub Jelinek
@ 2014-09-30 17:36                         ` Alexey Samsonov
  2014-09-30 17:39                           ` Jakub Jelinek
  0 siblings, 1 reply; 73+ messages in thread
From: Alexey Samsonov @ 2014-09-30 17:36 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Yury Gribov, Konstantin Serebryany, GCC Patches, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On Tue, Sep 30, 2014 at 10:33 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Tue, Sep 30, 2014 at 10:26:39AM -0700, Alexey Samsonov wrote:
>> > I think we can summarize:
>> > * the current option -fsanitize-recover is misleading; it's really
>> > -fubsan-recover
>> > * we need a way to selectively enable/disable recovery for different
>> > sanitizers
>> >
>> > The most promininet solution seems to be
>> > * allow -fsanitize-recover=tgt1,tgt2 syntax
>> > * -fsanitize-recover wo options would still mean UBSan recovery
>> >
>> > The question is what to do with -fno-sanitize-recover then.
>>
>> We can make -f(no-)?sanitize-recover= flags accept the same values as
>> -f(no-)?sanitize= flags. In this case,
>>
>> "-fsanitize-recover" will be a deprecated alias of
>> "-fsanitize-recover=undefined", and
>> "-fno-sanitize-recover" will be a deprecated alias of
>> "-fno-sanitize-recover=undefined".
>> If a user provides "-fsanitize-recover=address", we can instruct the
>> instrumentation pass to
>> use recoverable instrumentation.
>
> Would we accept -fsanitize-recover=undefined -fno-sanitize-recover=signed-integer-overflow
> as recovering everything but signed integer overflows, i.e. the decision
> whether to recover a particular call would check similar bitmask as
> is checked whether to sanitize something at all?

Yes, the logic for creating a set of recoverable sanitizers should be
the same as the logic for creating a set of enabled sanitizers.

-- 
Alexey Samsonov, Mountain View, CA

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-09-30 17:36                         ` Alexey Samsonov
@ 2014-09-30 17:39                           ` Jakub Jelinek
  2014-10-01 23:21                             ` Alexey Samsonov
       [not found]                             ` <543BADAB.4090000@samsung.com>
  0 siblings, 2 replies; 73+ messages in thread
From: Jakub Jelinek @ 2014-09-30 17:39 UTC (permalink / raw)
  To: Alexey Samsonov
  Cc: Yury Gribov, Konstantin Serebryany, GCC Patches, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On Tue, Sep 30, 2014 at 10:36:34AM -0700, Alexey Samsonov wrote:
> > Would we accept -fsanitize-recover=undefined -fno-sanitize-recover=signed-integer-overflow
> > as recovering everything but signed integer overflows, i.e. the decision
> > whether to recover a particular call would check similar bitmask as
> > is checked whether to sanitize something at all?
> 
> Yes, the logic for creating a set of recoverable sanitizers should be
> the same as the logic for creating a set of enabled sanitizers.

LGTM, will hack it up soon in GCC then.

	Jakub

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-09-30 17:39                           ` Jakub Jelinek
@ 2014-10-01 23:21                             ` Alexey Samsonov
  2014-10-02  5:58                               ` Jakub Jelinek
       [not found]                             ` <543BADAB.4090000@samsung.com>
  1 sibling, 1 reply; 73+ messages in thread
From: Alexey Samsonov @ 2014-10-01 23:21 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Yury Gribov, Konstantin Serebryany, GCC Patches, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

Speaking of plain -f(no-)sanitize-recover - it would probably be
better to change the semantics of this flag,
so that "-f(no-)?sanitize-recover" means "enable(disable) recovery for
all sanitizers enabled at this point".
That is, it would be pretty much like -Werror flag.

For example,
"-fsanitize=undefined -fsanitize=address -fno-sanitize-recover"
would mean "run UBSan and ASan and don't recover from errors".

On Tue, Sep 30, 2014 at 10:39 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Tue, Sep 30, 2014 at 10:36:34AM -0700, Alexey Samsonov wrote:
>> > Would we accept -fsanitize-recover=undefined -fno-sanitize-recover=signed-integer-overflow
>> > as recovering everything but signed integer overflows, i.e. the decision
>> > whether to recover a particular call would check similar bitmask as
>> > is checked whether to sanitize something at all?
>>
>> Yes, the logic for creating a set of recoverable sanitizers should be
>> the same as the logic for creating a set of enabled sanitizers.
>
> LGTM, will hack it up soon in GCC then.
>
>         Jakub



-- 
Alexey Samsonov, Mountain View, CA

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-10-01 23:21                             ` Alexey Samsonov
@ 2014-10-02  5:58                               ` Jakub Jelinek
  2014-10-03 18:54                                 ` Alexey Samsonov
  0 siblings, 1 reply; 73+ messages in thread
From: Jakub Jelinek @ 2014-10-02  5:58 UTC (permalink / raw)
  To: Alexey Samsonov
  Cc: Yury Gribov, Konstantin Serebryany, GCC Patches, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On Wed, Oct 01, 2014 at 04:21:29PM -0700, Alexey Samsonov wrote:
> Speaking of plain -f(no-)sanitize-recover - it would probably be
> better to change the semantics of this flag,
> so that "-f(no-)?sanitize-recover" means "enable(disable) recovery for
> all sanitizers enabled at this point".
> That is, it would be pretty much like -Werror flag.
> 
> For example,
> "-fsanitize=undefined -fsanitize=address -fno-sanitize-recover"
> would mean "run UBSan and ASan and don't recover from errors".

That would change behavior, e.g. for
-fsanitize=undefined,address -fsanitize-recover
would suddenly enable recovery from asan errors while previously
they wouldn't be recovering.

GCC has not shipped with the -fsanitize-recover flag yet (we have just
vendor backport of it), so if you don't mind changing behavior for clang
users, I can live with that.  Would the default still be
-fsanitize-recover=undefined,kernel-address -fno-sanitize-recover=address ?

	Jakub

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

* Re: [PATCHv3][PING] Enable -fsanitize-recover for KASan
  2014-10-02  5:58                               ` Jakub Jelinek
@ 2014-10-03 18:54                                 ` Alexey Samsonov
  0 siblings, 0 replies; 73+ messages in thread
From: Alexey Samsonov @ 2014-10-03 18:54 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Yury Gribov, Konstantin Serebryany, GCC Patches, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On Wed, Oct 1, 2014 at 10:58 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Wed, Oct 01, 2014 at 04:21:29PM -0700, Alexey Samsonov wrote:
>> Speaking of plain -f(no-)sanitize-recover - it would probably be
>> better to change the semantics of this flag,
>> so that "-f(no-)?sanitize-recover" means "enable(disable) recovery for
>> all sanitizers enabled at this point".
>> That is, it would be pretty much like -Werror flag.
>>
>> For example,
>> "-fsanitize=undefined -fsanitize=address -fno-sanitize-recover"
>> would mean "run UBSan and ASan and don't recover from errors".
>
> That would change behavior, e.g. for
> -fsanitize=undefined,address -fsanitize-recover
> would suddenly enable recovery from asan errors while previously
> they wouldn't be recovering.
>
> GCC has not shipped with the -fsanitize-recover flag yet (we have just
> vendor backport of it), so if you don't mind changing behavior for clang
> users, I can live with that.

Yes, I think so. -fsanitize-recover was not documented in Clang user manual.

>  Would the default still be
> -fsanitize-recover=undefined,kernel-address -fno-sanitize-recover=address ?

Yes.

-- 
Alexey Samsonov, Mountain View, CA

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

* [PATCH] -fsanitize-recover=list
       [not found]                             ` <543BADAB.4090000@samsung.com>
@ 2014-10-17 16:16                               ` Jakub Jelinek
  2014-10-20 10:44                                 ` Yury Gribov
                                                   ` (2 more replies)
  0 siblings, 3 replies; 73+ messages in thread
From: Jakub Jelinek @ 2014-10-17 16:16 UTC (permalink / raw)
  To: Yury Gribov, Marek Polacek
  Cc: gcc-patches, Alexey Samsonov, Dmitry Vyukov, Konstantin Serebryany

On Mon, Oct 13, 2014 at 02:47:07PM +0400, Yury Gribov wrote:
> On 09/30/2014 09:39 PM, Jakub Jelinek wrote:
> >LGTM, will hack it up soon in GCC then.
> 
> Do you plan to work on this in near future?

Here is only very lightly tested patch, didn't get to updating
documentation though, plus there is no testsuite coverage for it.
Supposedly, most of the tests that use -fno-sanitize-recover
or -fsanitize-recover in dg-options should be changed to use
-fno-sanitize-recover= or -fsanitize-recover (in some cases for
the kind that is enabled with -fsanitize= only, in other cases
perhaps for something covering that and some other options),
plus perhaps some new smallish tests that test that if you e.g.
do -fsanitize=undefined -fno-sanitize-recover=divide , that
you can recover from several say out of bound shifts, but that
the first divide will terminate, etc. 
Yuri or Marek, would you have spare time for that?

There is one not so nice thing, if one requests e.g.
-fsanitize=null,alignment -fno-sanitize-recover=null -fsanitize-recover=alignment
(or vice versa), as a single call is used for both alignment and null
checks, if both are tested, it needs to pick something, the patch
right now picks recovery rather than abort if the two bits
in flag_sanitize_recover disagree.  In theory, we could in that case
just use two separate calls rather than sharing one call, doing the
check and conditional branch to *_abort () first and if that wasn't true,
do the other check.

Also, the patch enables -fsanitize-recover by default for
-fsanitize-recover=undefined,float-divide-by-zero,float-cast-overflow
but not for kernel-address and doesn't check
(flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) in asan.c, you'd
need to add that afterwards.

2014-10-17  Jakub Jelinek  <jakub@redhat.com>

	* common.opt (flag_sanitize_recover): New variable.
	(fsanitize-recover): Remove Var/Init, deprecate.
	(fsanitize-recover=): New option.
	* opts.c (finish_options): Use opts->x_flag_sanitize
	instead of flag_sanitize.  Formatting.
	(common_handle_option): Handle OPT_fsanitize_recover_
	and OPT_fsanitize_recover.  Use opts->x_flag_sanitize
	instead of flag_sanitize.
	* asan.c (pass_sanopt::execute): Fix up formatting.
	* ubsan.c (ubsan_expand_bounds_ifn, ubsan_expand_null_ifn,
	ubsan_expand_objsize_ifn, ubsan_build_overflow_builtin,
	instrument_bool_enum_load, ubsan_instrument_float_cast,
	instrument_nonnull_arg, instrument_nonnull_return): Check
	bits in flag_sanitize_recover bitmask instead of
	flag_sanitize_recover as bool flag.
c-family/
	* c-ubsan.c (ubsan_instrument_division, ubsan_instrument_shift,
	ubsan_instrument_vla): Check bits in flag_sanitize_recover bitmask
	instead of flag_sanitize_recover as bool flag.

--- gcc/common.opt.jj	2014-10-17 08:47:21.000000000 +0200
+++ gcc/common.opt	2014-10-17 17:45:41.816337133 +0200
@@ -211,6 +211,10 @@ bool flag_opts_finished
 Variable
 unsigned int flag_sanitize
 
+; What sanitizers should recover from errors
+Variable
+unsigned int flag_sanitize_recover = SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT
+
 ; Flag whether a prefix has been added to dump_base_name
 Variable
 bool dump_base_name_prefixed = false
@@ -879,10 +883,14 @@ fsanitize=
 Common Driver Report Joined
 Select what to sanitize
 
-fsanitize-recover
-Common Report Var(flag_sanitize_recover) Init(1)
+fsanitize-recover=
+Common Report Joined
 After diagnosing undefined behavior attempt to continue execution
 
+fsanitize-recover
+Common Report
+This switch is deprecated; use -fsanitize-recover= instead
+
 fsanitize-undefined-trap-on-error
 Common Report Var(flag_sanitize_undefined_trap_on_error) Init(0)
 Use trap instead of a library function for undefined behavior sanitization
--- gcc/opts.c.jj	2014-10-17 12:01:19.000000000 +0200
+++ gcc/opts.c	2014-10-17 17:17:38.620375035 +0200
@@ -879,17 +879,17 @@ finish_options (struct gcc_options *opts
 
   /* Userspace and kernel ASan conflict with each other and with TSan.  */
 
-  if ((flag_sanitize & SANITIZE_USER_ADDRESS)
-      && (flag_sanitize & SANITIZE_KERNEL_ADDRESS))
+  if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS)
+      && (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS))
     error_at (loc,
-              "-fsanitize=address is incompatible with "
-              "-fsanitize=kernel-address");
+	      "-fsanitize=address is incompatible with "
+	      "-fsanitize=kernel-address");
 
-  if ((flag_sanitize & SANITIZE_ADDRESS)
-      && (flag_sanitize & SANITIZE_THREAD))
+  if ((opts->x_flag_sanitize & SANITIZE_ADDRESS)
+      && (opts->x_flag_sanitize & SANITIZE_THREAD))
     error_at (loc,
-              "-fsanitize=address and -fsanitize=kernel-address "
-              "are incompatible with -fsanitize=thread");
+	      "-fsanitize=address and -fsanitize=kernel-address "
+	      "are incompatible with -fsanitize=thread");
 }
 
 #define LEFT_COLUMN	27
@@ -1473,6 +1473,7 @@ common_handle_option (struct gcc_options
       break;
 
     case OPT_fsanitize_:
+    case OPT_fsanitize_recover_:
       {
 	const char *p = arg;
 	while (*p != 0)
@@ -1539,33 +1540,48 @@ common_handle_option (struct gcc_options
 		  && memcmp (p, spec[i].name, len) == 0)
 		{
 		  /* Handle both -fsanitize and -fno-sanitize cases.  */
-		  if (value)
-		    flag_sanitize |= spec[i].flag;
+		  if (code == OPT_fsanitize_)
+		    {
+		      if (value)
+			opts->x_flag_sanitize |= spec[i].flag;
+		      else
+			opts->x_flag_sanitize &= ~spec[i].flag;
+		    }
 		  else
-		    flag_sanitize &= ~spec[i].flag;
+		    {
+		      if (value)
+			opts->x_flag_sanitize_recover |= spec[i].flag;
+		      else
+			opts->x_flag_sanitize_recover &= ~spec[i].flag;
+		    }
 		  found = true;
 		  break;
 		}
 
 	    if (! found)
 	      error_at (loc,
-			"unrecognized argument to -fsanitize= option: %q.*s",
-			(int) len, p);
+			code == OPT_fsanitize_
+			? "unrecognized argument to -fsanitize= option: %q.*s"
+			: "unrecognized argument to -fsanitize-recover= "
+			  "option: %q.*s", (int) len, p);
 
 	    if (comma == NULL)
 	      break;
 	    p = comma + 1;
 	  }
 
+	if (code != OPT_fsanitize_)
+	  break;
+
 	/* When instrumenting the pointers, we don't want to remove
 	   the null pointer checks.  */
-	if (flag_sanitize & (SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
-			     | SANITIZE_RETURNS_NONNULL_ATTRIBUTE))
+	if (opts->x_flag_sanitize & (SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
+				     | SANITIZE_RETURNS_NONNULL_ATTRIBUTE))
 	  opts->x_flag_delete_null_pointer_checks = 0;
 
 	/* Kernel ASan implies normal ASan but does not yet support
 	   all features.  */
-	if (flag_sanitize & SANITIZE_KERNEL_ADDRESS)
+	if (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS)
 	  {
 	    maybe_set_param_value (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD, 0,
 				   opts->x_param_values,
@@ -1584,6 +1600,15 @@ common_handle_option (struct gcc_options
 	break;
       }
 
+    case OPT_fsanitize_recover:
+      if (value)
+	opts->x_flag_sanitize_recover
+	  |= SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT;
+      else
+	opts->x_flag_sanitize_recover
+	  &= ~(SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT);
+      break;
+
     case OPT_O:
     case OPT_Os:
     case OPT_Ofast:
--- gcc/asan.c.jj	2014-10-13 17:54:34.000000000 +0200
+++ gcc/asan.c	2014-10-17 17:46:20.952620580 +0200
@@ -2884,10 +2884,8 @@ pass_sanopt::execute (function *fun)
 		  no_next = ubsan_expand_objsize_ifn (&gsi);
 		  break;
 		case IFN_ASAN_CHECK:
-		  {
-		    no_next = asan_expand_check_ifn (&gsi, use_calls);
-		    break;
-		  }
+		  no_next = asan_expand_check_ifn (&gsi, use_calls);
+		  break;
 		default:
 		  break;
 		}
--- gcc/ubsan.c.jj	2014-10-10 19:42:22.000000000 +0200
+++ gcc/ubsan.c	2014-10-17 17:05:57.609330882 +0200
@@ -638,7 +638,7 @@ ubsan_expand_bounds_ifn (gimple_stmt_ite
 			     NULL_TREE, NULL_TREE);
       data = build_fold_addr_expr_loc (loc, data);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= (flag_sanitize_recover & SANITIZE_BOUNDS)
 	  ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
 	  : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
       tree fn = builtin_decl_explicit (bcode);
@@ -741,7 +741,8 @@ ubsan_expand_null_ifn (gimple_stmt_itera
   else
     {
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= (flag_sanitize_recover & ((check_align ? SANITIZE_ALIGNMENT : 0)
+				    | (check_null ? SANITIZE_NULL : 0)))
 	  ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
 	  : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
       tree fn = builtin_decl_implicit (bcode);
@@ -879,7 +880,7 @@ ubsan_expand_objsize_ifn (gimple_stmt_it
 				 NULL_TREE);
 	  data = build_fold_addr_expr_loc (loc, data);
 	  enum built_in_function bcode
-	    = flag_sanitize_recover
+	    = (flag_sanitize_recover & SANITIZE_OBJECT_SIZE)
 	      ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
 	      : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
 	  tree p = make_ssa_name (pointer_sized_int_node, NULL);
@@ -964,22 +965,22 @@ ubsan_build_overflow_builtin (tree_code
   switch (code)
     {
     case PLUS_EXPR:
-      fn_code = flag_sanitize_recover
+      fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
 		? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
 		: BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
       break;
     case MINUS_EXPR:
-      fn_code = flag_sanitize_recover
+      fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
 		? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
 		: BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
       break;
     case MULT_EXPR:
-      fn_code = flag_sanitize_recover
+      fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
 		? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
 		: BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
       break;
     case NEGATE_EXPR:
-      fn_code = flag_sanitize_recover
+      fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
 		? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
 		: BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
       break;
@@ -1156,7 +1157,8 @@ instrument_bool_enum_load (gimple_stmt_i
 				     NULL_TREE);
       data = build_fold_addr_expr_loc (loc, data);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= (flag_sanitize_recover & (TREE_CODE (type) == BOOLEAN_TYPE
+				    ? SANITIZE_BOOL : SANITIZE_ENUM))
 	  ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
 	  : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
       tree fn = builtin_decl_explicit (bcode);
@@ -1278,7 +1280,7 @@ ubsan_instrument_float_cast (location_t
 				     ubsan_type_descriptor (type), NULL_TREE,
 				     NULL_TREE);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= (flag_sanitize_recover & SANITIZE_FLOAT_CAST)
 	  ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
 	  : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
       fn = builtin_decl_explicit (bcode);
@@ -1344,7 +1346,7 @@ instrument_nonnull_arg (gimple_stmt_iter
 					     NULL_TREE);
 	      data = build_fold_addr_expr_loc (loc[0], data);
 	      enum built_in_function bcode
-		= flag_sanitize_recover
+		= (flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
 		  ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
 		  : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
 	      tree fn = builtin_decl_explicit (bcode);
@@ -1396,7 +1398,7 @@ instrument_nonnull_return (gimple_stmt_i
 					 2, loc, NULL_TREE, NULL_TREE);
 	  data = build_fold_addr_expr_loc (loc[0], data);
 	  enum built_in_function bcode
-	    = flag_sanitize_recover
+	    = (flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
 	      ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
 	      : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT;
 	  tree fn = builtin_decl_explicit (bcode);
--- gcc/c-family/c-ubsan.c.jj	2014-09-10 11:20:49.000000000 +0200
+++ gcc/c-family/c-ubsan.c	2014-10-17 17:13:14.393241619 +0200
@@ -104,7 +104,7 @@ ubsan_instrument_division (location_t lo
 				     NULL_TREE);
       data = build_fold_addr_expr_loc (loc, data);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= (flag_sanitize_recover & SANITIZE_DIVIDE)
 	  ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
 	  : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT;
       tt = builtin_decl_explicit (bcode);
@@ -199,7 +199,7 @@ ubsan_instrument_shift (location_t loc,
       data = build_fold_addr_expr_loc (loc, data);
 
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= (flag_sanitize_recover & SANITIZE_SHIFT)
 	  ? BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS
 	  : BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS_ABORT;
       tt = builtin_decl_explicit (bcode);
@@ -229,7 +229,7 @@ ubsan_instrument_vla (location_t loc, tr
 				     NULL_TREE);
       data = build_fold_addr_expr_loc (loc, data);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= (flag_sanitize_recover & SANITIZE_VLA)
 	  ? BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE
 	  : BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE_ABORT;
       tt = builtin_decl_explicit (bcode);


	Jakub

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

* Re: [PATCH] -fsanitize-recover=list
  2014-10-17 16:16                               ` [PATCH] -fsanitize-recover=list Jakub Jelinek
@ 2014-10-20 10:44                                 ` Yury Gribov
  2014-10-22  8:05                                 ` Yury Gribov
  2014-11-18  2:50                                 ` Alexey Samsonov
  2 siblings, 0 replies; 73+ messages in thread
From: Yury Gribov @ 2014-10-20 10:44 UTC (permalink / raw)
  To: Jakub Jelinek, Marek Polacek
  Cc: gcc-patches, Alexey Samsonov, Dmitry Vyukov, Konstantin Serebryany

On 10/17/2014 08:13 PM, Jakub Jelinek wrote:
> On Mon, Oct 13, 2014 at 02:47:07PM +0400, Yury Gribov wrote:
>> On 09/30/2014 09:39 PM, Jakub Jelinek wrote:
>>> LGTM, will hack it up soon in GCC then.
>>
>> Do you plan to work on this in near future?
>
> Here is only very lightly tested patch, didn't get to updating
> documentation though, plus there is no testsuite coverage for it.
> Supposedly, most of the tests that use -fno-sanitize-recover
> or -fsanitize-recover in dg-options should be changed to use
> -fno-sanitize-recover= or -fsanitize-recover (in some cases for
> the kind that is enabled with -fsanitize= only, in other cases
> perhaps for something covering that and some other options),
> plus perhaps some new smallish tests that test that if you e.g.
> do -fsanitize=undefined -fno-sanitize-recover=divide , that
> you can recover from several say out of bound shifts, but that
> the first divide will terminate, etc.
> Yuri or Marek, would you have spare time for that?

I'll take on this!

-Y

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

* Re: [PATCH] -fsanitize-recover=list
  2014-10-17 16:16                               ` [PATCH] -fsanitize-recover=list Jakub Jelinek
  2014-10-20 10:44                                 ` Yury Gribov
@ 2014-10-22  8:05                                 ` Yury Gribov
  2014-10-22 10:02                                   ` Jakub Jelinek
  2014-11-18  2:50                                 ` Alexey Samsonov
  2 siblings, 1 reply; 73+ messages in thread
From: Yury Gribov @ 2014-10-22  8:05 UTC (permalink / raw)
  To: Jakub Jelinek, Marek Polacek
  Cc: gcc-patches, Alexey Samsonov, Dmitry Vyukov, Konstantin Serebryany

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

On 10/17/2014 08:13 PM, Jakub Jelinek wrote:
> On Mon, Oct 13, 2014 at 02:47:07PM +0400, Yury Gribov wrote:
>> On 09/30/2014 09:39 PM, Jakub Jelinek wrote:
>>> LGTM, will hack it up soon in GCC then.
>>
>> Do you plan to work on this in near future?
>
> Here is only very lightly tested patch, didn't get to updating
> documentation though, plus there is no testsuite coverage for it.
> Supposedly, most of the tests that use -fno-sanitize-recover
> or -fsanitize-recover in dg-options should be changed to use
> -fno-sanitize-recover= or -fsanitize-recover

Here is an updated patch. I've slightly changed opts.c chunk, added docs 
and updated tests.

> (in some cases for
> the kind that is enabled with -fsanitize= only, in other cases
> perhaps for something covering that and some other options),

Depending on what? I've just passed contents of -fsanitize= to 
-fsanitize-recover=, seems to work fine.

> plus perhaps some new smallish tests that test that if you e.g.
> do -fsanitize=undefined -fno-sanitize-recover=divide , that
> you can recover from several say out of bound shifts, but that
> the first divide will terminate, etc.

Did couple of those.

> There is one not so nice thing, if one requests e.g.
> -fsanitize=null,alignment -fno-sanitize-recover=null -fsanitize-recover=alignment
> (or vice versa), as a single call is used for both alignment and null
> checks, if both are tested, it needs to pick something, the patch
> right now picks recovery rather than abort if the two bits
> in flag_sanitize_recover disagree.  In theory, we could in that case
> just use two separate calls rather than sharing one call, doing the
> check and conditional branch to *_abort () first and if that wasn't true,
> do the other check.

Either that or just issue warning for now.

-Y

[-- Attachment #2: 0001-New-syntax-for-fsanitize-recover.patch --]
[-- Type: text/x-patch, Size: 37891 bytes --]

From 956b59533590fdda49af3afb33063047b0415567 Mon Sep 17 00:00:00 2001
From: Yury Gribov <y.gribov@samsung.com>
Date: Tue, 21 Oct 2014 17:09:37 +0400
Subject: [PATCH] New syntax for -fsanitize-recover.

2014-10-22  Jakub Jelinek  <jakub@redhat.com>
	    Yury Gribov  <y.gribov@samsung.com>

gcc/
	* common.opt (flag_sanitize_recover): New variable.
	(fsanitize-recover): Remove Var/Init, deprecate.
	(fsanitize-recover=): New option.
	* doc/invoke.texi (fsanitize-recover): Update docs.
	* opts.c (finish_options): Use opts->x_flag_sanitize
	instead of flag_sanitize.  Prohibit -fsanitize-recover
	for anything besides UBSan.  Formatting.
	(common_handle_option): Handle OPT_fsanitize_recover_
	and OPT_fsanitize_recover.  Use opts->x_flag_sanitize
	instead of flag_sanitize.
	* asan.c (pass_sanopt::execute): Fix up formatting.
	* ubsan.c (ubsan_expand_bounds_ifn, ubsan_expand_null_ifn,
	ubsan_expand_objsize_ifn, ubsan_build_overflow_builtin,
	instrument_bool_enum_load, ubsan_instrument_float_cast,
	instrument_nonnull_arg, instrument_nonnull_return): Check
	bits in flag_sanitize_recover bitmask instead of
	flag_sanitize_recover as bool flag.

gcc/c-family/
	* c-ubsan.c (ubsan_instrument_division, ubsan_instrument_shift,
	ubsan_instrument_vla): Check bits in flag_sanitize_recover bitmask
	instead of flag_sanitize_recover as bool flag.

gcc/testsuite/
	* c-c++-common/ubsan/align-1.c: Updated cmdline options.
	* c-c++-common/ubsan/align-3.c: Likewise.
	* c-c++-common/ubsan/bounds-1.c: Likewise.
	* c-c++-common/ubsan/div-by-zero-7.c: Likewise.
	* c-c++-common/ubsan/float-cast-overflow-10.c: Likewise.
	* c-c++-common/ubsan/float-cast-overflow-7.c: Likewise.
	* c-c++-common/ubsan/float-cast-overflow-8.c: Likewise.
	* c-c++-common/ubsan/float-cast-overflow-9.c: Likewise.
	* c-c++-common/ubsan/nonnull-2.c: Likewise.
	* c-c++-common/ubsan/nonnull-3.c: Likewise.
	* c-c++-common/ubsan/object-size-3.c: Likewise.
	* c-c++-common/ubsan/overflow-1.c: Likewise.
	* c-c++-common/ubsan/overflow-add-1.c: Likewise.
	* c-c++-common/ubsan/overflow-add-3.c: Likewise.
	* c-c++-common/ubsan/overflow-mul-1.c: Likewise.
	* c-c++-common/ubsan/overflow-mul-3.c: Likewise.
	* c-c++-common/ubsan/overflow-negate-2.c: Likewise.
	* c-c++-common/ubsan/overflow-sub-1.c: Likewise.
	* c-c++-common/ubsan/pr59503.c: Likewise.
	* c-c++-common/ubsan/pr60613-1.c: Likewise.
	* c-c++-common/ubsan/save-expr-1.c: Likewise.
	* c-c++-common/ubsan/shift-3.c: Likewise.
	* c-c++-common/ubsan/shift-6.c: Likewise.
	* c-c++-common/ubsan/undefined-1.c: Likewise.
	* c-c++-common/ubsan/vla-2.c: Likewise.
	* c-c++-common/ubsan/vla-3.c: Likewise.
	* c-c++-common/ubsan/vla-4.c: Likewise.
	* g++.dg/ubsan/cxx11-shift-1.C: Likewise.
	* g++.dg/ubsan/return-2.C: Likewise.
	* c-c++-common/ubsan/recovery-1.c: New test.
	* c-c++-common/ubsan/recovery-2.c: New test.
	* c-c++-common/ubsan/recovery-3.c: New test.
	* c-c++-common/ubsan/recovery-common.inc: New file.
---
 gcc/asan.c                                         |    6 +--
 gcc/c-family/c-ubsan.c                             |    6 +--
 gcc/common.opt                                     |   12 ++++-
 gcc/doc/invoke.texi                                |   31 +++++++----
 gcc/opts.c                                         |   57 ++++++++++++++------
 gcc/testsuite/c-c++-common/ubsan/align-1.c         |    2 +-
 gcc/testsuite/c-c++-common/ubsan/align-3.c         |    2 +-
 gcc/testsuite/c-c++-common/ubsan/bounds-1.c        |    2 +-
 gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c   |    2 +-
 .../c-c++-common/ubsan/float-cast-overflow-10.c    |    2 +-
 .../c-c++-common/ubsan/float-cast-overflow-7.c     |    2 +-
 .../c-c++-common/ubsan/float-cast-overflow-8.c     |    2 +-
 .../c-c++-common/ubsan/float-cast-overflow-9.c     |    2 +-
 gcc/testsuite/c-c++-common/ubsan/nonnull-2.c       |    2 +-
 gcc/testsuite/c-c++-common/ubsan/nonnull-3.c       |    2 +-
 gcc/testsuite/c-c++-common/ubsan/object-size-3.c   |    2 +-
 gcc/testsuite/c-c++-common/ubsan/overflow-1.c      |    2 +-
 gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c  |    2 +-
 gcc/testsuite/c-c++-common/ubsan/overflow-add-3.c  |    2 +-
 gcc/testsuite/c-c++-common/ubsan/overflow-mul-1.c  |    2 +-
 gcc/testsuite/c-c++-common/ubsan/overflow-mul-3.c  |    2 +-
 .../c-c++-common/ubsan/overflow-negate-2.c         |    2 +-
 gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c  |    2 +-
 gcc/testsuite/c-c++-common/ubsan/pr59503.c         |    2 +-
 gcc/testsuite/c-c++-common/ubsan/pr60613-1.c       |    2 +-
 gcc/testsuite/c-c++-common/ubsan/recovery-1.c      |    9 ++++
 gcc/testsuite/c-c++-common/ubsan/recovery-2.c      |   10 ++++
 gcc/testsuite/c-c++-common/ubsan/recovery-3.c      |    9 ++++
 .../c-c++-common/ubsan/recovery-common.inc         |   19 +++++++
 gcc/testsuite/c-c++-common/ubsan/save-expr-1.c     |    2 +-
 gcc/testsuite/c-c++-common/ubsan/shift-3.c         |    2 +-
 gcc/testsuite/c-c++-common/ubsan/shift-6.c         |    2 +-
 gcc/testsuite/c-c++-common/ubsan/undefined-1.c     |    2 +-
 gcc/testsuite/c-c++-common/ubsan/vla-2.c           |    2 +-
 gcc/testsuite/c-c++-common/ubsan/vla-3.c           |    2 +-
 gcc/testsuite/c-c++-common/ubsan/vla-4.c           |    2 +-
 gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C         |    2 +-
 gcc/testsuite/g++.dg/ubsan/return-2.C              |    2 +-
 gcc/ubsan.c                                        |   24 +++++----
 39 files changed, 167 insertions(+), 74 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/recovery-1.c
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/recovery-2.c
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/recovery-3.c
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/recovery-common.inc

diff --git a/gcc/asan.c b/gcc/asan.c
index 2a61a82..97f0b4c 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -2884,10 +2884,8 @@ pass_sanopt::execute (function *fun)
 		  no_next = ubsan_expand_objsize_ifn (&gsi);
 		  break;
 		case IFN_ASAN_CHECK:
-		  {
-		    no_next = asan_expand_check_ifn (&gsi, use_calls);
-		    break;
-		  }
+		  no_next = asan_expand_check_ifn (&gsi, use_calls);
+		  break;
 		default:
 		  break;
 		}
diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c
index 3539c68..5a42303 100644
--- a/gcc/c-family/c-ubsan.c
+++ b/gcc/c-family/c-ubsan.c
@@ -104,7 +104,7 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
 				     NULL_TREE);
       data = build_fold_addr_expr_loc (loc, data);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= (flag_sanitize_recover & SANITIZE_DIVIDE)
 	  ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
 	  : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT;
       tt = builtin_decl_explicit (bcode);
@@ -199,7 +199,7 @@ ubsan_instrument_shift (location_t loc, enum tree_code code,
       data = build_fold_addr_expr_loc (loc, data);
 
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= (flag_sanitize_recover & SANITIZE_SHIFT)
 	  ? BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS
 	  : BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS_ABORT;
       tt = builtin_decl_explicit (bcode);
@@ -229,7 +229,7 @@ ubsan_instrument_vla (location_t loc, tree size)
 				     NULL_TREE);
       data = build_fold_addr_expr_loc (loc, data);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= (flag_sanitize_recover & SANITIZE_VLA)
 	  ? BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE
 	  : BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE_ABORT;
       tt = builtin_decl_explicit (bcode);
diff --git a/gcc/common.opt b/gcc/common.opt
index 5db5e1e..3ea5958 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -211,6 +211,10 @@ bool flag_opts_finished
 Variable
 unsigned int flag_sanitize
 
+; What sanitizers should recover from errors
+Variable
+unsigned int flag_sanitize_recover = SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT
+
 ; Flag whether a prefix has been added to dump_base_name
 Variable
 bool dump_base_name_prefixed = false
@@ -879,10 +883,14 @@ fsanitize=
 Common Driver Report Joined
 Select what to sanitize
 
-fsanitize-recover
-Common Report Var(flag_sanitize_recover) Init(1)
+fsanitize-recover=
+Common Report Joined
 After diagnosing undefined behavior attempt to continue execution
 
+fsanitize-recover
+Common Report
+This switch is deprecated; use -fsanitize-recover= instead
+
 fsanitize-undefined-trap-on-error
 Common Report Var(flag_sanitize_undefined_trap_on_error) Init(0)
 Use trap instead of a library function for undefined behavior sanitization
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 23f272f..349957d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -296,7 +296,7 @@ Objective-C and Objective-C++ Dialects}.
 @item Debugging Options
 @xref{Debugging Options,,Options for Debugging Your Program or GCC}.
 @gccoptlist{-d@var{letters}  -dumpspecs  -dumpmachine  -dumpversion @gol
--fsanitize=@var{style} -fsanitize-recover @gol
+-fsanitize=@var{style} -fsanitize-recover -fsanitize-recover=@var{style} @gol
 -fsanitize-undefined-trap-on-error @gol
 -fdbg-cnt-list -fdbg-cnt=@var{counter-value-list} @gol
 -fdisable-ipa-@var{pass_name} @gol
@@ -5637,18 +5637,29 @@ While @option{-ftrapv} causes traps for signed overflows to be emitted,
 @option{-fsanitize=undefined} gives a diagnostic message.
 This currently works only for the C family of languages.
 
-@item -fsanitize-recover
+@item -fsanitize-recover@r{[}=@var{opts}@r{]}
 @opindex fsanitize-recover
-By default @option{-fsanitize=undefined} sanitization (and its suboptions
-except for @option{-fsanitize=unreachable} and @option{-fsanitize=return})
-after reporting undefined behavior attempts to continue running the
-program as if no undefined behavior happened.  This means multiple undefined
-behavior runtime errors can be reported in a single program run, and the exit
-code of the program may indicate success even when undefined behavior
-has been reported.  The @option{-fno-sanitize-recover} can be used to alter
-this behavior, only the first detected undefined behavior will be reported
+@opindex fno-sanitize-recover
+@option{-fsanitize-recover=} controls error recovery mode for sanitizers
+mentioned in comma-separated list of @var{opts}.  Enabling this option
+for a sanitizer component would cause it to attempt to continue
+running the program as if no error happened.  This means multiple
+runtime errors can be reported in a single program run, and the exit
+code of the program may indicate success even when errors
+have been reported.  The @option{-fno-sanitize-recover=} can be used to alter
+this behavior, only the first detected error will be reported
 and program will exit after that with non-zero exit code.
 
+Currently this feature only works for @option{-fsanitize=undefined} (and its suboptions
+except for @option{-fsanitize=unreachable} and @option{-fsanitize=return}),
+@option{-fsanitize=float-cast-overflow} and @option{-fsanitize=float-divide-by-zero}.
+For these sanitizers error recovery is turned on by default.
+
+Syntax without explicit @var{opts} parameter is deprecated.  It is equivalent to
+@option{-fsanitize-recover=undefined,float-cast-overflow,float-divide-by-zero}.
+Similarly @option{-fno-sanitize-recover} is equivalent to
+@option{-fno-sanitize-recover=undefined,float-cast-overflow,float-divide-by-zero}.
+
 @item -fsanitize-undefined-trap-on-error
 @opindex fsanitize-undefined-trap-on-error
 The @option{-fsanitize-undefined-trap-on-error} instructs the compiler to
diff --git a/gcc/opts.c b/gcc/opts.c
index 3054196..48ada43 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -879,17 +879,28 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
 
   /* Userspace and kernel ASan conflict with each other and with TSan.  */
 
-  if ((flag_sanitize & SANITIZE_USER_ADDRESS)
-      && (flag_sanitize & SANITIZE_KERNEL_ADDRESS))
+  if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS)
+      && (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS))
     error_at (loc,
-              "-fsanitize=address is incompatible with "
-              "-fsanitize=kernel-address");
+	      "-fsanitize=address is incompatible with "
+	      "-fsanitize=kernel-address");
 
-  if ((flag_sanitize & SANITIZE_ADDRESS)
-      && (flag_sanitize & SANITIZE_THREAD))
+  if ((opts->x_flag_sanitize & SANITIZE_ADDRESS)
+      && (opts->x_flag_sanitize & SANITIZE_THREAD))
     error_at (loc,
-              "-fsanitize=address and -fsanitize=kernel-address "
-              "are incompatible with -fsanitize=thread");
+	      "-fsanitize=address and -fsanitize=kernel-address "
+	      "are incompatible with -fsanitize=thread");
+
+  /* Error recovery is not allowed for ASan and TSan.  */
+
+  if (opts->x_flag_sanitize_recover & SANITIZE_USER_ADDRESS)
+    error_at (loc, "-fsanitize-recover=address is not supported");
+
+  if (opts->x_flag_sanitize_recover & SANITIZE_THREAD)
+    error_at (loc, "-fsanitize-recover=thread is not supported");
+
+  if (opts->x_flag_sanitize_recover & SANITIZE_LEAK)
+    error_at (loc, "-fsanitize-recover=leak is not supported");
 }
 
 #define LEFT_COLUMN	27
@@ -1473,8 +1484,12 @@ common_handle_option (struct gcc_options *opts,
       break;
 
     case OPT_fsanitize_:
+    case OPT_fsanitize_recover_:
       {
 	const char *p = arg;
+	unsigned int *flag
+	  = code == OPT_fsanitize_ ? &opts->x_flag_sanitize
+	  : &opts->x_flag_sanitize_recover;
 	while (*p != 0)
 	  {
 	    static const struct
@@ -1540,32 +1555,35 @@ common_handle_option (struct gcc_options *opts,
 		{
 		  /* Handle both -fsanitize and -fno-sanitize cases.  */
 		  if (value)
-		    flag_sanitize |= spec[i].flag;
+		    *flag |= spec[i].flag;
 		  else
-		    flag_sanitize &= ~spec[i].flag;
+		    *flag &= ~spec[i].flag;
 		  found = true;
 		  break;
 		}
 
 	    if (! found)
 	      error_at (loc,
-			"unrecognized argument to -fsanitize= option: %q.*s",
-			(int) len, p);
+			"unrecognized argument to -fsanitize%s= option: %q.*s",
+			code == OPT_fsanitize_ ? "" : "-recover", (int) len, p);
 
 	    if (comma == NULL)
 	      break;
 	    p = comma + 1;
 	  }
 
+	if (code != OPT_fsanitize_)
+	  break;
+
 	/* When instrumenting the pointers, we don't want to remove
 	   the null pointer checks.  */
-	if (flag_sanitize & (SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
-			     | SANITIZE_RETURNS_NONNULL_ATTRIBUTE))
+	if (opts->x_flag_sanitize & (SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
+				     | SANITIZE_RETURNS_NONNULL_ATTRIBUTE))
 	  opts->x_flag_delete_null_pointer_checks = 0;
 
 	/* Kernel ASan implies normal ASan but does not yet support
 	   all features.  */
-	if (flag_sanitize & SANITIZE_KERNEL_ADDRESS)
+	if (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS)
 	  {
 	    maybe_set_param_value (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD, 0,
 				   opts->x_param_values,
@@ -1584,6 +1602,15 @@ common_handle_option (struct gcc_options *opts,
 	break;
       }
 
+    case OPT_fsanitize_recover:
+      if (value)
+	opts->x_flag_sanitize_recover
+	  |= SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT;
+      else
+	opts->x_flag_sanitize_recover
+	  &= ~(SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT);
+      break;
+
     case OPT_O:
     case OPT_Os:
     case OPT_Ofast:
diff --git a/gcc/testsuite/c-c++-common/ubsan/align-1.c b/gcc/testsuite/c-c++-common/ubsan/align-1.c
index 2e40e83..b2ccb30 100644
--- a/gcc/testsuite/c-c++-common/ubsan/align-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/align-1.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover=undefined" } */
 
 struct S { int a; char b; long long c; short d[10]; };
 struct T { char a; long long b; };
diff --git a/gcc/testsuite/c-c++-common/ubsan/align-3.c b/gcc/testsuite/c-c++-common/ubsan/align-3.c
index a509fa9..bbacc42 100644
--- a/gcc/testsuite/c-c++-common/ubsan/align-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/align-3.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover=undefined" } */
 
 int c;
 
diff --git a/gcc/testsuite/c-c++-common/ubsan/bounds-1.c b/gcc/testsuite/c-c++-common/ubsan/bounds-1.c
index aa192d3..20e390f 100644
--- a/gcc/testsuite/c-c++-common/ubsan/bounds-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/bounds-1.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=bounds -fno-sanitize-recover -Wall" } */
+/* { dg-options "-fsanitize=bounds -fno-sanitize-recover=bounds -Wall" } */
 
 /* Don't fail on valid uses.  */
 
diff --git a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c
index b65a0bc..5f53bef 100644
--- a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c
+++ b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-div-by-zero -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-div-by-zero -fno-sanitize-recover=integer-divide-by-zero" } */
 /* { dg-shouldfail "ubsan" } */
 
 #include <stdio.h>
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c
index e95f194..269a0ed 100644
--- a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c
@@ -1,6 +1,6 @@
 /* { dg-do run { target dfp } } */
 /* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
-/* { dg-options "-fsanitize=float-cast-overflow -fsanitize-recover" } */
+/* { dg-options "-fsanitize=float-cast-overflow -fsanitize-recover=float-cast-overflow" } */
 /* { dg-additional-options "-DUSE_INT128" { target int128 } } */
 /* FIXME: When _DecimalXX <-> {signed, unsigned} __int128 conversions are
    supported, -DBROKEN_DECIMAL_INT128 can be removed.  */
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c
index 3223d5e..69d4628 100644
--- a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c
@@ -1,6 +1,6 @@
 /* { dg-do run } */
 /* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
-/* { dg-options "-fsanitize=float-cast-overflow -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=float-cast-overflow -fno-sanitize-recover=float-cast-overflow" } */
 /* FIXME: When _DecimalXX <-> {signed, unsigned} __int128 conversions are
    supported, -DBROKEN_DECIMAL_INT128 can be removed.  */
 /* { dg-additional-options "-DUSE_DFP -DBROKEN_DECIMAL_INT128" { target dfp } } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c
index 5414a0b..5b1837d 100644
--- a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c
@@ -1,6 +1,6 @@
 /* { dg-do run } */
 /* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
-/* { dg-options "-fsanitize=float-cast-overflow -fsanitize-recover -DUSE_FLT_DBL_LDBL" } */
+/* { dg-options "-fsanitize=float-cast-overflow -DUSE_FLT_DBL_LDBL" } */
 /* { dg-additional-options "-DUSE_INT128" { target int128 } } */
 
 #include "float-cast-overflow-7.h"
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c
index cadef31..05399e7 100644
--- a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c
@@ -1,6 +1,6 @@
 /* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */
 /* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
-/* { dg-options "-fsanitize=float-cast-overflow -fsanitize-recover -DUSE_FLOAT80 -DUSE_FLOAT128" } */
+/* { dg-options "-fsanitize=float-cast-overflow -fsanitize-recover=float-cast-overflow -DUSE_FLOAT80 -DUSE_FLOAT128" } */
 /* { dg-additional-options "-DUSE_INT128" { target int128 } } */
 
 #include "float-cast-overflow-8.c"
diff --git a/gcc/testsuite/c-c++-common/ubsan/nonnull-2.c b/gcc/testsuite/c-c++-common/ubsan/nonnull-2.c
index 49a5cf2..3eb6ae7 100644
--- a/gcc/testsuite/c-c++-common/ubsan/nonnull-2.c
+++ b/gcc/testsuite/c-c++-common/ubsan/nonnull-2.c
@@ -1,6 +1,6 @@
 /* { dg-do run } */
 /* { dg-shouldfail "ubsan" } */
-/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover=undefined" } */
 
 int q, r;
 void *a, *b, *c = (void *) &q, *d, *e, *f = (void *) &q, *g, *h;
diff --git a/gcc/testsuite/c-c++-common/ubsan/nonnull-3.c b/gcc/testsuite/c-c++-common/ubsan/nonnull-3.c
index 80018c2..67fd6dd 100644
--- a/gcc/testsuite/c-c++-common/ubsan/nonnull-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/nonnull-3.c
@@ -1,6 +1,6 @@
 /* { dg-do run } */
 /* { dg-shouldfail "ubsan" } */
-/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover=undefined" } */
 
 int q, r;
 void *a, *b, *c = (void *) &q, *d, *e, *f = (void *) &q, *g, *h;
diff --git a/gcc/testsuite/c-c++-common/ubsan/object-size-3.c b/gcc/testsuite/c-c++-common/ubsan/object-size-3.c
index 62dc76f..a88081c 100644
--- a/gcc/testsuite/c-c++-common/ubsan/object-size-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/object-size-3.c
@@ -1,6 +1,6 @@
 /* { dg-do run } */
 /* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
-/* { dg-options "-fsanitize=object-size -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=object-size -fno-sanitize-recover=object-size" } */
 
 /* Test valid uses.  */
 
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-1.c b/gcc/testsuite/c-c++-common/ubsan/overflow-1.c
index b0ef259..22bacb3 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-1.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover=signed-integer-overflow" } */
 
 #ifndef ASM1
 # define ASM1(a) /* Nothing */
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c b/gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c
index b009f5b..960f1b0 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover=signed-integer-overflow" } */
 
 #define SCHAR_MAX __SCHAR_MAX__
 #define SHRT_MAX __SHRT_MAX__
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-add-3.c b/gcc/testsuite/c-c++-common/ubsan/overflow-add-3.c
index 6475d10..f406276 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-add-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-add-3.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover=signed-integer-overflow" } */
 /* { dg-shouldfail "ubsan" } */
 
 #define INT_MAX __INT_MAX__
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-mul-1.c b/gcc/testsuite/c-c++-common/ubsan/overflow-mul-1.c
index 22ea639..04a9ec7 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-mul-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-mul-1.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover=signed-integer-overflow" } */
 
 #define SCHAR_MAX __SCHAR_MAX__
 #define SHRT_MAX __SHRT_MAX__
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-mul-3.c b/gcc/testsuite/c-c++-common/ubsan/overflow-mul-3.c
index 896c0bc..9bca1f8 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-mul-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-mul-3.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover=signed-integer-overflow" } */
 
 __attribute__((noinline, noclone)) long long
 mul (long long x, long long y)
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-negate-2.c b/gcc/testsuite/c-c++-common/ubsan/overflow-negate-2.c
index 8b5ffa5..db54b27 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-negate-2.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-negate-2.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover=signed-integer-overflow" } */
 
 #define SCHAR_MIN (-__SCHAR_MAX__ - 1)
 #define SHRT_MIN (-__SHRT_MAX__ - 1)
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c b/gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c
index 2b10f9e..e92aaf4 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover=signed-integer-overflow" } */
 
 #define SCHAR_MAX __SCHAR_MAX__
 #define SCHAR_MIN (-__SCHAR_MAX__ - 1)
diff --git a/gcc/testsuite/c-c++-common/ubsan/pr59503.c b/gcc/testsuite/c-c++-common/ubsan/pr59503.c
index 81447d7..36356d5 100644
--- a/gcc/testsuite/c-c++-common/ubsan/pr59503.c
+++ b/gcc/testsuite/c-c++-common/ubsan/pr59503.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover=signed-integer-overflow" } */
 
 int
 main (void)
diff --git a/gcc/testsuite/c-c++-common/ubsan/pr60613-1.c b/gcc/testsuite/c-c++-common/ubsan/pr60613-1.c
index 4c0810b..f358e19 100644
--- a/gcc/testsuite/c-c++-common/ubsan/pr60613-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/pr60613-1.c
@@ -1,6 +1,6 @@
 /* PR sanitizer/60613 */
 /* { dg-do run } */
-/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover=undefined" } */
 
 long long y;
 
diff --git a/gcc/testsuite/c-c++-common/ubsan/recovery-1.c b/gcc/testsuite/c-c++-common/ubsan/recovery-1.c
new file mode 100644
index 0000000..8043a5c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/recovery-1.c
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=undefined -fsanitize-recover=signed-integer-overflow -w" } */
+
+#include "recovery-common.inc"
+
+/* { dg-output "shift exponent 152 is too large for \[^\n\r]*-bit type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*shift exponent 153 is too large for \[^\n\r]*-bit type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*signed integer overflow: 2147483647 \\+ 1 cannot be represented in type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*signed integer overflow: 2147483647 \\+ 2 cannot be represented in type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/recovery-2.c b/gcc/testsuite/c-c++-common/ubsan/recovery-2.c
new file mode 100644
index 0000000..ad5e410
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/recovery-2.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover=signed-integer-overflow -w" } */
+/* { dg-shouldfail "ubsan" } */
+
+#include "recovery-common.inc"
+
+/* { dg-output "shift exponent 152 is too large for \[^\n\r]*-bit type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*shift exponent 153 is too large for \[^\n\r]*-bit type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*signed integer overflow: 2147483647 \\+ 1 cannot be represented in type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*(?!.*signed integer overflow)" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/recovery-3.c b/gcc/testsuite/c-c++-common/ubsan/recovery-3.c
new file mode 100644
index 0000000..02f2272
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/recovery-3.c
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=undefined -w" } */
+
+#include "recovery-common.inc"
+
+/* { dg-output "shift exponent 152 is too large for \[^\n\r]*-bit type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*shift exponent 153 is too large for \[^\n\r]*-bit type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*signed integer overflow: 2147483647 \\+ 1 cannot be represented in type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*signed integer overflow: 2147483647 \\+ 2 cannot be represented in type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/recovery-common.inc b/gcc/testsuite/c-c++-common/ubsan/recovery-common.inc
new file mode 100644
index 0000000..1e0667a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/recovery-common.inc
@@ -0,0 +1,19 @@
+typedef const unsigned long long int CULLI;
+typedef volatile int VI;
+struct s { signed long int a; };
+
+int
+main (void)
+{
+  volatile int shiftcount = 153;
+  volatile int a = __INT_MAX__;
+  volatile int b = __INT_MAX__;
+
+  a << 152;
+  b << shiftcount;
+  a += 1;
+  b += 2;
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/c-c++-common/ubsan/save-expr-1.c b/gcc/testsuite/c-c++-common/ubsan/save-expr-1.c
index 89ac58c..ff6c5cf 100644
--- a/gcc/testsuite/c-c++-common/ubsan/save-expr-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/save-expr-1.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-fsanitize=shift -Wall -Werror -O -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=shift -Wall -Werror -O -fno-sanitize-recover=shift" } */
 
 static int x;
 int
diff --git a/gcc/testsuite/c-c++-common/ubsan/shift-3.c b/gcc/testsuite/c-c++-common/ubsan/shift-3.c
index 67f1b69..d57d73e 100644
--- a/gcc/testsuite/c-c++-common/ubsan/shift-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/shift-3.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=shift -w -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=shift -w -fno-sanitize-recover=shift" } */
 
 int
 main (void)
diff --git a/gcc/testsuite/c-c++-common/ubsan/shift-6.c b/gcc/testsuite/c-c++-common/ubsan/shift-6.c
index e26e684..d596459 100644
--- a/gcc/testsuite/c-c++-common/ubsan/shift-6.c
+++ b/gcc/testsuite/c-c++-common/ubsan/shift-6.c
@@ -1,6 +1,6 @@
 /* PR sanitizer/58413 */
 /* { dg-do run { target int32plus } } */
-/* { dg-options "-fsanitize=shift -w -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=shift -w -fno-sanitize-recover=shift" } */
 
 int x = 7;
 int
diff --git a/gcc/testsuite/c-c++-common/ubsan/undefined-1.c b/gcc/testsuite/c-c++-common/ubsan/undefined-1.c
index 201818d..b67b013 100644
--- a/gcc/testsuite/c-c++-common/ubsan/undefined-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/undefined-1.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover=undefined" } */
 
 int
 foo (int x, int y)
diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-2.c b/gcc/testsuite/c-c++-common/ubsan/vla-2.c
index c767042..9cd4ddf 100644
--- a/gcc/testsuite/c-c++-common/ubsan/vla-2.c
+++ b/gcc/testsuite/c-c++-common/ubsan/vla-2.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=vla-bound -Wall -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=vla-bound -Wall -Wno-unused-variable -fno-sanitize-recover=vla-bound" } */
 
 int
 main (void)
diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-3.c b/gcc/testsuite/c-c++-common/ubsan/vla-3.c
index 06c6939..6003fdd 100644
--- a/gcc/testsuite/c-c++-common/ubsan/vla-3.c
+++ b/gcc/testsuite/c-c++-common/ubsan/vla-3.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=vla-bound -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=vla-bound -fno-sanitize-recover=vla-bound" } */
 
 /* Don't instrument the arrays here.  */
 int
diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-4.c b/gcc/testsuite/c-c++-common/ubsan/vla-4.c
index d47f26b..c9060177 100644
--- a/gcc/testsuite/c-c++-common/ubsan/vla-4.c
+++ b/gcc/testsuite/c-c++-common/ubsan/vla-4.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=vla-bound -fno-sanitize-recover" } */
+/* { dg-options "-fsanitize=vla-bound -fno-sanitize-recover=vla-bound" } */
 
 int
 main (void)
diff --git a/gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C b/gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C
index 23a7b15..431eab1 100644
--- a/gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C
+++ b/gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=shift -w -fno-sanitize-recover -std=c++11" } */
+/* { dg-options "-fsanitize=shift -w -fno-sanitize-recover=shift -std=c++11" } */
 
 int
 main (void)
diff --git a/gcc/testsuite/g++.dg/ubsan/return-2.C b/gcc/testsuite/g++.dg/ubsan/return-2.C
index a182999..90c48b5 100644
--- a/gcc/testsuite/g++.dg/ubsan/return-2.C
+++ b/gcc/testsuite/g++.dg/ubsan/return-2.C
@@ -1,5 +1,5 @@
 // { dg-do run }
-// { dg-options "-fsanitize=return -fno-sanitize-recover" }
+// { dg-options "-fsanitize=return -fno-sanitize-recover=return" }
 
 struct S { S (); ~S (); };
 
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index dde0418..f143fce 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -638,7 +638,7 @@ ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
 			     NULL_TREE, NULL_TREE);
       data = build_fold_addr_expr_loc (loc, data);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= (flag_sanitize_recover & SANITIZE_BOUNDS)
 	  ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
 	  : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
       tree fn = builtin_decl_explicit (bcode);
@@ -741,7 +741,8 @@ ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
   else
     {
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= (flag_sanitize_recover & ((check_align ? SANITIZE_ALIGNMENT : 0)
+				    | (check_null ? SANITIZE_NULL : 0)))
 	  ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
 	  : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
       tree fn = builtin_decl_implicit (bcode);
@@ -879,7 +880,7 @@ ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
 				 NULL_TREE);
 	  data = build_fold_addr_expr_loc (loc, data);
 	  enum built_in_function bcode
-	    = flag_sanitize_recover
+	    = (flag_sanitize_recover & SANITIZE_OBJECT_SIZE)
 	      ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
 	      : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
 	  tree p = make_ssa_name (pointer_sized_int_node, NULL);
@@ -964,22 +965,22 @@ ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
   switch (code)
     {
     case PLUS_EXPR:
-      fn_code = flag_sanitize_recover
+      fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
 		? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
 		: BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
       break;
     case MINUS_EXPR:
-      fn_code = flag_sanitize_recover
+      fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
 		? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
 		: BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
       break;
     case MULT_EXPR:
-      fn_code = flag_sanitize_recover
+      fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
 		? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
 		: BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
       break;
     case NEGATE_EXPR:
-      fn_code = flag_sanitize_recover
+      fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
 		? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
 		: BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
       break;
@@ -1156,7 +1157,8 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi)
 				     NULL_TREE);
       data = build_fold_addr_expr_loc (loc, data);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= (flag_sanitize_recover & (TREE_CODE (type) == BOOLEAN_TYPE
+				    ? SANITIZE_BOOL : SANITIZE_ENUM))
 	  ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
 	  : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
       tree fn = builtin_decl_explicit (bcode);
@@ -1278,7 +1280,7 @@ ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
 				     ubsan_type_descriptor (type), NULL_TREE,
 				     NULL_TREE);
       enum built_in_function bcode
-	= flag_sanitize_recover
+	= (flag_sanitize_recover & SANITIZE_FLOAT_CAST)
 	  ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
 	  : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
       fn = builtin_decl_explicit (bcode);
@@ -1344,7 +1346,7 @@ instrument_nonnull_arg (gimple_stmt_iterator *gsi)
 					     NULL_TREE);
 	      data = build_fold_addr_expr_loc (loc[0], data);
 	      enum built_in_function bcode
-		= flag_sanitize_recover
+		= (flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
 		  ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
 		  : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
 	      tree fn = builtin_decl_explicit (bcode);
@@ -1396,7 +1398,7 @@ instrument_nonnull_return (gimple_stmt_iterator *gsi)
 					 2, loc, NULL_TREE, NULL_TREE);
 	  data = build_fold_addr_expr_loc (loc[0], data);
 	  enum built_in_function bcode
-	    = flag_sanitize_recover
+	    = (flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
 	      ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
 	      : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT;
 	  tree fn = builtin_decl_explicit (bcode);
-- 
1.7.9.5


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

* Re: [PATCH] -fsanitize-recover=list
  2014-10-22  8:05                                 ` Yury Gribov
@ 2014-10-22 10:02                                   ` Jakub Jelinek
  0 siblings, 0 replies; 73+ messages in thread
From: Jakub Jelinek @ 2014-10-22 10:02 UTC (permalink / raw)
  To: Yury Gribov
  Cc: Marek Polacek, gcc-patches, Alexey Samsonov, Dmitry Vyukov,
	Konstantin Serebryany

On Wed, Oct 22, 2014 at 11:59:06AM +0400, Yury Gribov wrote:
> >(in some cases for
> >the kind that is enabled with -fsanitize= only, in other cases
> >perhaps for something covering that and some other options),
> 
> Depending on what? I've just passed contents of -fsanitize= to
> -fsanitize-recover=, seems to work fine.

I meant pick randomly a few testcases where you -fno-sanitize-recover=
a superset of what is specified in -fsanitize= , but it is not a big deal.

> 2014-10-22  Jakub Jelinek  <jakub@redhat.com>
> 	    Yury Gribov  <y.gribov@samsung.com>
> 
> gcc/
> 	* common.opt (flag_sanitize_recover): New variable.
> 	(fsanitize-recover): Remove Var/Init, deprecate.
> 	(fsanitize-recover=): New option.
> 	* doc/invoke.texi (fsanitize-recover): Update docs.
> 	* opts.c (finish_options): Use opts->x_flag_sanitize
> 	instead of flag_sanitize.  Prohibit -fsanitize-recover
> 	for anything besides UBSan.  Formatting.
> 	(common_handle_option): Handle OPT_fsanitize_recover_
> 	and OPT_fsanitize_recover.  Use opts->x_flag_sanitize
> 	instead of flag_sanitize.
> 	* asan.c (pass_sanopt::execute): Fix up formatting.
> 	* ubsan.c (ubsan_expand_bounds_ifn, ubsan_expand_null_ifn,
> 	ubsan_expand_objsize_ifn, ubsan_build_overflow_builtin,
> 	instrument_bool_enum_load, ubsan_instrument_float_cast,
> 	instrument_nonnull_arg, instrument_nonnull_return): Check
> 	bits in flag_sanitize_recover bitmask instead of
> 	flag_sanitize_recover as bool flag.
> 
> gcc/c-family/
> 	* c-ubsan.c (ubsan_instrument_division, ubsan_instrument_shift,
> 	ubsan_instrument_vla): Check bits in flag_sanitize_recover bitmask
> 	instead of flag_sanitize_recover as bool flag.
> 
> gcc/testsuite/
> 	* c-c++-common/ubsan/align-1.c: Updated cmdline options.
> 	* c-c++-common/ubsan/align-3.c: Likewise.
> 	* c-c++-common/ubsan/bounds-1.c: Likewise.
> 	* c-c++-common/ubsan/div-by-zero-7.c: Likewise.
> 	* c-c++-common/ubsan/float-cast-overflow-10.c: Likewise.
> 	* c-c++-common/ubsan/float-cast-overflow-7.c: Likewise.
> 	* c-c++-common/ubsan/float-cast-overflow-8.c: Likewise.
> 	* c-c++-common/ubsan/float-cast-overflow-9.c: Likewise.
> 	* c-c++-common/ubsan/nonnull-2.c: Likewise.
> 	* c-c++-common/ubsan/nonnull-3.c: Likewise.
> 	* c-c++-common/ubsan/object-size-3.c: Likewise.
> 	* c-c++-common/ubsan/overflow-1.c: Likewise.
> 	* c-c++-common/ubsan/overflow-add-1.c: Likewise.
> 	* c-c++-common/ubsan/overflow-add-3.c: Likewise.
> 	* c-c++-common/ubsan/overflow-mul-1.c: Likewise.
> 	* c-c++-common/ubsan/overflow-mul-3.c: Likewise.
> 	* c-c++-common/ubsan/overflow-negate-2.c: Likewise.
> 	* c-c++-common/ubsan/overflow-sub-1.c: Likewise.
> 	* c-c++-common/ubsan/pr59503.c: Likewise.
> 	* c-c++-common/ubsan/pr60613-1.c: Likewise.
> 	* c-c++-common/ubsan/save-expr-1.c: Likewise.
> 	* c-c++-common/ubsan/shift-3.c: Likewise.
> 	* c-c++-common/ubsan/shift-6.c: Likewise.
> 	* c-c++-common/ubsan/undefined-1.c: Likewise.
> 	* c-c++-common/ubsan/vla-2.c: Likewise.
> 	* c-c++-common/ubsan/vla-3.c: Likewise.
> 	* c-c++-common/ubsan/vla-4.c: Likewise.
> 	* g++.dg/ubsan/cxx11-shift-1.C: Likewise.
> 	* g++.dg/ubsan/return-2.C: Likewise.
> 	* c-c++-common/ubsan/recovery-1.c: New test.
> 	* c-c++-common/ubsan/recovery-2.c: New test.
> 	* c-c++-common/ubsan/recovery-3.c: New test.
> 	* c-c++-common/ubsan/recovery-common.inc: New file.

Ok, thanks.

	Jakub

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

* [PATCHv4] Enable -fsanitize-recover for KASan
  2014-09-29 17:21   ` [PATCHv3][PING] " Yury Gribov
  2014-09-29 17:44     ` Jakub Jelinek
@ 2014-10-23  7:15     ` Yury Gribov
  2014-10-23  7:20       ` Jakub Jelinek
  2014-10-28  8:46       ` [PATCH v5] " Yury Gribov
  1 sibling, 2 replies; 73+ messages in thread
From: Yury Gribov @ 2014-10-23  7:15 UTC (permalink / raw)
  To: GCC Patches
  Cc: Jakub Jelinek, Konstantin Serebryany, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

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

Hi all,

On 09/29/2014 09:21 PM, Yury Gribov wrote:
>>> This patch enables -fsanitize-recover for KASan by default. This causes
>>> KASan to continue execution after error in case of inline
>>> instrumentation. This feature is needed because
>>> - reports during early bootstrap won't even be printed
>>> - needed to run all tests w/o rebooting machine for every test
>>> - needed for interactive work on desktop
>
> This is the third version of patch which renames -fsanitize-recover to
> -fubsan-recover and introduces -fasan-recover (enabled by default for
> KASan). It also moves flag handling to finish_options per Jakub's request.

A new version of patch based upon Jakub's recent changes to 
-fsanitize-recover=.  I've renamed __asan_report_recover_load* to 
__asan_report_load*_noabort to match UBSan's style.

Note that currently -fsanitize=kernel-address 
-fno-sanitize-recover=kernel-address won't work as expected because we 
miss __asan_load*_abort family of functions in libasan.

Bootstrapped and regtested on x64.

-Y

[-- Attachment #2: 0001-Enable-fsanitize-recover-for-KASan.patch --]
[-- Type: text/x-patch, Size: 11046 bytes --]

From 75586eb21f1272a4fcf7c626d9b740eed7150c2c Mon Sep 17 00:00:00 2001
From: Yury Gribov <y.gribov@samsung.com>
Date: Wed, 22 Oct 2014 17:24:55 +0400
Subject: [PATCH] Enable -fsanitize-recover for KASan.

2014-10-22  Yury Gribov  <y.gribov@samsung.com>

gcc/
	* asan.c (report_error_func): Add noabort path.
	(check_func): Formatting.
	(asan_expand_check_ifn): Handle noabort path.
	* common.opt (flag_sanitize_recover): Add SANITIZE_KERNEL_ADDRESS
	to default value.
	* doc/invoke.texi (-fsanitize-recover=): Mention KASan.
	* opts.c (finish_options): Reword comment.
	* sanitizer.def: Add noabort ASan builtins.

gcc/testsuite/
	* c-c++-common/asan/kasan-recover-1.c: New test.
---
 gcc/asan.c                                        |   52 ++++++++++++++-------
 gcc/common.opt                                    |    2 +-
 gcc/doc/invoke.texi                               |    8 ++--
 gcc/opts.c                                        |    4 +-
 gcc/sanitizer.def                                 |   38 +++++++++++++++
 gcc/testsuite/c-c++-common/asan/kasan-recover-1.c |   12 +++++
 6 files changed, 93 insertions(+), 23 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/asan/kasan-recover-1.c

diff --git a/gcc/asan.c b/gcc/asan.c
index 97f0b4c..6b04591 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -1344,22 +1344,36 @@ 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, int *nargs)
-{
-  static enum built_in_function report[2][6]
-    = { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
-	  BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
-	  BUILT_IN_ASAN_REPORT_LOAD16, BUILT_IN_ASAN_REPORT_LOAD_N },
-	{ BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2,
-	  BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
-	  BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } };
+report_error_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
+		   int *nargs)
+{
+  static enum built_in_function report[2][2][6]
+    = { { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
+	    BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
+	    BUILT_IN_ASAN_REPORT_LOAD16, BUILT_IN_ASAN_REPORT_LOAD_N },
+	  { BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2,
+	    BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
+	    BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } },
+	{ { BUILT_IN_ASAN_REPORT_LOAD1_NOABORT,
+	    BUILT_IN_ASAN_REPORT_LOAD2_NOABORT,
+	    BUILT_IN_ASAN_REPORT_LOAD4_NOABORT,
+	    BUILT_IN_ASAN_REPORT_LOAD8_NOABORT,
+	    BUILT_IN_ASAN_REPORT_LOAD16_NOABORT,
+	    BUILT_IN_ASAN_REPORT_LOAD_N_NOABORT },
+	  { BUILT_IN_ASAN_REPORT_STORE1_NOABORT,
+	    BUILT_IN_ASAN_REPORT_STORE2_NOABORT,
+	    BUILT_IN_ASAN_REPORT_STORE4_NOABORT,
+	    BUILT_IN_ASAN_REPORT_STORE8_NOABORT,
+	    BUILT_IN_ASAN_REPORT_STORE16_NOABORT,
+	    BUILT_IN_ASAN_REPORT_STORE_N_NOABORT } } };
   if (size_in_bytes == -1)
     {
       *nargs = 2;
-      return builtin_decl_implicit (report[is_store][5]);
+      return builtin_decl_implicit (report[recover_p][is_store][5]);
     }
   *nargs = 1;
-  return builtin_decl_implicit (report[is_store][exact_log2 (size_in_bytes)]);
+  int size_log2 = exact_log2 (size_in_bytes);
+  return builtin_decl_implicit (report[recover_p][is_store][size_log2]);
 }
 
 /* Construct a function tree for __asan_{load,store}{1,2,4,8,16,_n}.
@@ -1370,11 +1384,11 @@ check_func (bool is_store, int size_in_bytes, int *nargs)
 {
   static enum built_in_function check[2][6]
     = { { BUILT_IN_ASAN_LOAD1, BUILT_IN_ASAN_LOAD2,
-      BUILT_IN_ASAN_LOAD4, BUILT_IN_ASAN_LOAD8,
-      BUILT_IN_ASAN_LOAD16, BUILT_IN_ASAN_LOADN },
+	  BUILT_IN_ASAN_LOAD4, BUILT_IN_ASAN_LOAD8,
+	  BUILT_IN_ASAN_LOAD16, BUILT_IN_ASAN_LOADN },
 	{ BUILT_IN_ASAN_STORE1, BUILT_IN_ASAN_STORE2,
-      BUILT_IN_ASAN_STORE4, BUILT_IN_ASAN_STORE8,
-      BUILT_IN_ASAN_STORE16, BUILT_IN_ASAN_STOREN } };
+	  BUILT_IN_ASAN_STORE4, BUILT_IN_ASAN_STORE8,
+	  BUILT_IN_ASAN_STORE16, BUILT_IN_ASAN_STOREN } };
   if (size_in_bytes == -1)
     {
       *nargs = 2;
@@ -2589,9 +2603,11 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
   /* Get an iterator on the point where we can add the condition
      statement for the instrumentation.  */
   basic_block then_bb, else_bb;
+  bool create_then_fallthru_edge
+    = (flag_sanitize & flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) != 0;
   gsi = create_cond_insert_point (&gsi, /*before_p*/false,
 				  /*then_more_likely_p=*/false,
-				  /*create_then_fallthru_edge=*/false,
+				  create_then_fallthru_edge,
 				  &then_bb,
 				  &else_bb);
 
@@ -2700,7 +2716,9 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
   /* Generate call to the run-time library (e.g. __asan_report_load8).  */
   gsi = gsi_start_bb (then_bb);
   int nargs;
-  tree fun = report_error_func (is_store, size_in_bytes, &nargs);
+  bool recover_p
+    = (flag_sanitize & flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) != 0;
+  tree fun = report_error_func (is_store, recover_p, size_in_bytes, &nargs);
   g = gimple_build_call (fun, nargs, base_addr, len);
   gimple_set_location (g, loc);
   gsi_insert_after (&gsi, g, GSI_NEW_STMT);
diff --git a/gcc/common.opt b/gcc/common.opt
index da5250b..e385615 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -213,7 +213,7 @@ unsigned int flag_sanitize
 
 ; What sanitizers should recover from errors
 Variable
-unsigned int flag_sanitize_recover = SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT
+unsigned int flag_sanitize_recover = SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT | SANITIZE_KERNEL_ADDRESS
 
 ; Flag whether a prefix has been added to dump_base_name
 Variable
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index c9ca404..6a425c0 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -5657,13 +5657,13 @@ and program will exit after that with non-zero exit code.
 
 Currently this feature only works for @option{-fsanitize=undefined} (and its suboptions
 except for @option{-fsanitize=unreachable} and @option{-fsanitize=return}),
-@option{-fsanitize=float-cast-overflow} and @option{-fsanitize=float-divide-by-zero}.
-For these sanitizers error recovery is turned on by default.
+@option{-fsanitize=float-cast-overflow}, @option{-fsanitize=float-divide-by-zero} and
+@option{-fsanitize=kernel-address}.  For these sanitizers error recovery is turned on by default.
 
 Syntax without explicit @var{opts} parameter is deprecated.  It is equivalent to
-@option{-fsanitize-recover=undefined,float-cast-overflow,float-divide-by-zero}.
+@option{-fsanitize-recover=undefined,float-cast-overflow,float-divide-by-zero,kernel-address}.
 Similarly @option{-fno-sanitize-recover} is equivalent to
-@option{-fno-sanitize-recover=undefined,float-cast-overflow,float-divide-by-zero}.
+@option{-fno-sanitize-recover=undefined,float-cast-overflow,float-divide-by-zero,kernel-address}.
 
 @item -fsanitize-undefined-trap-on-error
 @opindex fsanitize-undefined-trap-on-error
diff --git a/gcc/opts.c b/gcc/opts.c
index 25f5235..7157865 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -877,7 +877,7 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
   if (opts->x_dwarf_split_debug_info)
     opts->x_debug_generate_pub_sections = 2;
 
-  /* Userspace and kernel ASan conflict with each other and with TSan.  */
+  /* Userspace and kernel ASan conflict with each other.  */
 
   if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS)
       && (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS))
@@ -885,6 +885,8 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
 	      "-fsanitize=address is incompatible with "
 	      "-fsanitize=kernel-address");
 
+  /* And with TSan.  */
+
   if ((opts->x_flag_sanitize & SANITIZE_ADDRESS)
       && (opts->x_flag_sanitize & SANITIZE_THREAD))
     error_at (loc,
diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def
index 722311a..63c6e6d 100644
--- a/gcc/sanitizer.def
+++ b/gcc/sanitizer.def
@@ -57,6 +57,44 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE16, "__asan_report_store16",
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE_N, "__asan_report_store_n",
 		      BT_FN_VOID_PTR_PTRMODE,
 		      ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD1_NOABORT,
+		      "__asan_report_load1_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD2_NOABORT,
+		      "__asan_report_load2_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD4_NOABORT,
+		      "__asan_report_load4_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD8_NOABORT,
+		      "__asan_report_load8_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD16_NOABORT,
+		      "__asan_report_load16_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD_N_NOABORT,
+		      "__asan_report_load_n_noabort",
+		      BT_FN_VOID_PTR_PTRMODE,
+		      ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE1_NOABORT,
+		      "__asan_report_store1_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE2_NOABORT,
+		      "__asan_report_store2_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE4_NOABORT,
+		      "__asan_report_store4_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE8_NOABORT,
+		      "__asan_report_store8_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE16_NOABORT,
+		      "__asan_report_store16_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE_N_NOABORT,
+		      "__asan_report_store_n_noabort",
+		      BT_FN_VOID_PTR_PTRMODE,
+		      ATTR_TMPURE_NOTHROW_LEAF_LIST)
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD1, "__asan_load1",
 		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD2, "__asan_load2",
diff --git a/gcc/testsuite/c-c++-common/asan/kasan-recover-1.c b/gcc/testsuite/c-c++-common/asan/kasan-recover-1.c
new file mode 100644
index 0000000..6e04e5d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/kasan-recover-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-sanitize=address -fsanitize=kernel-address --param asan-instrumentation-with-call-threshold=100 -save-temps" } */
+
+void
+foo (int *p)
+{
+  *p = 0;
+}
+
+/* { dg-final { scan-assembler "__asan_report_store4_noabort" } } */
+/* { dg-final { cleanup-saved-temps } } */
+
-- 
1.7.9.5


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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-23  7:15     ` [PATCHv4] " Yury Gribov
@ 2014-10-23  7:20       ` Jakub Jelinek
  2014-10-23  7:30         ` Yury Gribov
  2014-10-28  8:46       ` [PATCH v5] " Yury Gribov
  1 sibling, 1 reply; 73+ messages in thread
From: Jakub Jelinek @ 2014-10-23  7:20 UTC (permalink / raw)
  To: Yury Gribov
  Cc: GCC Patches, Konstantin Serebryany, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On Thu, Oct 23, 2014 at 11:11:29AM +0400, Yury Gribov wrote:
> Hi all,
> 
> On 09/29/2014 09:21 PM, Yury Gribov wrote:
> >>>This patch enables -fsanitize-recover for KASan by default. This causes
> >>>KASan to continue execution after error in case of inline
> >>>instrumentation. This feature is needed because
> >>>- reports during early bootstrap won't even be printed
> >>>- needed to run all tests w/o rebooting machine for every test
> >>>- needed for interactive work on desktop
> >
> >This is the third version of patch which renames -fsanitize-recover to
> >-fubsan-recover and introduces -fasan-recover (enabled by default for
> >KASan). It also moves flag handling to finish_options per Jakub's request.
> 
> A new version of patch based upon Jakub's recent changes to
> -fsanitize-recover=.  I've renamed __asan_report_recover_load* to
> __asan_report_load*_noabort to match UBSan's style.
> 
> Note that currently -fsanitize=kernel-address
> -fno-sanitize-recover=kernel-address won't work as expected because we miss
> __asan_load*_abort family of functions in libasan.

I thought __asan_* functions are provided by the kernel, not libasan, for
-fsanitize=kernel-address.  Or is kernel linked with real libasan.a or
some stripped down version thereof?

	Jakub

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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-23  7:20       ` Jakub Jelinek
@ 2014-10-23  7:30         ` Yury Gribov
  2014-10-23  9:55           ` Andrey Ryabinin
  0 siblings, 1 reply; 73+ messages in thread
From: Yury Gribov @ 2014-10-23  7:30 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: GCC Patches, Konstantin Serebryany, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On 10/23/2014 11:13 AM, Jakub Jelinek wrote:
> On Thu, Oct 23, 2014 at 11:11:29AM +0400, Yury Gribov wrote:
>> Hi all,
>>
>> On 09/29/2014 09:21 PM, Yury Gribov wrote:
>>>>> This patch enables -fsanitize-recover for KASan by default. This causes
>>>>> KASan to continue execution after error in case of inline
>>>>> instrumentation. This feature is needed because
>>>>> - reports during early bootstrap won't even be printed
>>>>> - needed to run all tests w/o rebooting machine for every test
>>>>> - needed for interactive work on desktop
>>>
>>> This is the third version of patch which renames -fsanitize-recover to
>>> -fubsan-recover and introduces -fasan-recover (enabled by default for
>>> KASan). It also moves flag handling to finish_options per Jakub's request.
>>
>> A new version of patch based upon Jakub's recent changes to
>> -fsanitize-recover=.  I've renamed __asan_report_recover_load* to
>> __asan_report_load*_noabort to match UBSan's style.
>>
>> Note that currently -fsanitize=kernel-address
>> -fno-sanitize-recover=kernel-address won't work as expected because we miss
>> __asan_load*_abort family of functions in libasan.
>
> I thought __asan_* functions are provided by the kernel, not libasan, for
> -fsanitize=kernel-address.  Or is kernel linked with real libasan.a or
> some stripped down version thereof?

Hm, right, libasan is not linked to kernel so it indeed does not need 
any changes.  But now I see that for -fsanitize=kernel-address we need 
both __asan_load* and __asan_load*_noabort (the latter being default) 
depending on -fsanitize-recover setting.  Let me update the patch for this.

-Y

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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-23  7:30         ` Yury Gribov
@ 2014-10-23  9:55           ` Andrey Ryabinin
  2014-10-23 10:00             ` Jakub Jelinek
  0 siblings, 1 reply; 73+ messages in thread
From: Andrey Ryabinin @ 2014-10-23  9:55 UTC (permalink / raw)
  To: Yury Gribov, Jakub Jelinek
  Cc: GCC Patches, Konstantin Serebryany, Dmitry Vyukov, Konstantin Khlebnikov

On 10/23/2014 11:28 AM, Yury Gribov wrote:
> On 10/23/2014 11:13 AM, Jakub Jelinek wrote:
>> On Thu, Oct 23, 2014 at 11:11:29AM +0400, Yury Gribov wrote:
>>> Hi all,
>>>
>>> On 09/29/2014 09:21 PM, Yury Gribov wrote:
>>>>>> This patch enables -fsanitize-recover for KASan by default. This causes
>>>>>> KASan to continue execution after error in case of inline
>>>>>> instrumentation. This feature is needed because
>>>>>> - reports during early bootstrap won't even be printed
>>>>>> - needed to run all tests w/o rebooting machine for every test
>>>>>> - needed for interactive work on desktop
>>>>
>>>> This is the third version of patch which renames -fsanitize-recover to
>>>> -fubsan-recover and introduces -fasan-recover (enabled by default for
>>>> KASan). It also moves flag handling to finish_options per Jakub's request.
>>>
>>> A new version of patch based upon Jakub's recent changes to
>>> -fsanitize-recover=.  I've renamed __asan_report_recover_load* to
>>> __asan_report_load*_noabort to match UBSan's style.
>>>
>>> Note that currently -fsanitize=kernel-address
>>> -fno-sanitize-recover=kernel-address won't work as expected because we miss
>>> __asan_load*_abort family of functions in libasan.
>>
>> I thought __asan_* functions are provided by the kernel, not libasan, for
>> -fsanitize=kernel-address.  Or is kernel linked with real libasan.a or
>> some stripped down version thereof?
> 
> Hm, right, libasan is not linked to kernel so it indeed does not need any changes.  But now I see that for -fsanitize=kernel-address we need both __asan_load* and __asan_load*_noabort (the latter
> being default) depending on -fsanitize-recover setting.  Let me update the patch for this.
> 

IMO we don't need different versions of __asan_load* and __asan_load*_noabort, because
-fno-sanitize-recover=kernel-address will never work with the linux kernel.

I already said this before, and repeat this once again:
There is few places in kernel where we validly touch poisoned memory,
so we need to disable error reporting in runtime for such memory accesses.
I use per-thread flag which is raised before the valid access to poisoned memory.
This flag checked in __asan_report*() function. If it raised then we shouldn't print any error message,
just silently exit from report.
-fno-sanitize-recover=kernel-address will just cause early kernel crash on boot, so we will never use it.


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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-23  9:55           ` Andrey Ryabinin
@ 2014-10-23 10:00             ` Jakub Jelinek
  2014-10-23 10:07               ` Jakub Jelinek
  2014-10-23 10:11               ` Andrey Ryabinin
  0 siblings, 2 replies; 73+ messages in thread
From: Jakub Jelinek @ 2014-10-23 10:00 UTC (permalink / raw)
  To: Andrey Ryabinin
  Cc: Yury Gribov, GCC Patches, Konstantin Serebryany, Dmitry Vyukov,
	Konstantin Khlebnikov

On Thu, Oct 23, 2014 at 01:51:12PM +0400, Andrey Ryabinin wrote:
> IMO we don't need different versions of __asan_load* and __asan_load*_noabort, because
> -fno-sanitize-recover=kernel-address will never work with the linux kernel.
> 
> I already said this before, and repeat this once again:
> There is few places in kernel where we validly touch poisoned memory,
> so we need to disable error reporting in runtime for such memory accesses.
> I use per-thread flag which is raised before the valid access to poisoned memory.
> This flag checked in __asan_report*() function. If it raised then we shouldn't print any error message,
> just silently exit from report.

Can't you just use __attribute__((no_sanitize_address)) on the functions
that have such a code?  Or you could use special macros for those accesses
(which could e.g. call function to read memory or write memory, implemented
in assembly or in __attribute__((no_sanitize_address)) function), or
temporarily unpoison and poison again.

	Jakub

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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-23 10:00             ` Jakub Jelinek
@ 2014-10-23 10:07               ` Jakub Jelinek
  2014-10-23 10:24                 ` Andrey Ryabinin
  2014-10-23 10:11               ` Andrey Ryabinin
  1 sibling, 1 reply; 73+ messages in thread
From: Jakub Jelinek @ 2014-10-23 10:07 UTC (permalink / raw)
  To: Andrey Ryabinin
  Cc: Yury Gribov, GCC Patches, Konstantin Serebryany, Dmitry Vyukov,
	Konstantin Khlebnikov

On Thu, Oct 23, 2014 at 11:55:32AM +0200, Jakub Jelinek wrote:
> On Thu, Oct 23, 2014 at 01:51:12PM +0400, Andrey Ryabinin wrote:
> > IMO we don't need different versions of __asan_load* and __asan_load*_noabort, because
> > -fno-sanitize-recover=kernel-address will never work with the linux kernel.
> > 
> > I already said this before, and repeat this once again:
> > There is few places in kernel where we validly touch poisoned memory,
> > so we need to disable error reporting in runtime for such memory accesses.
> > I use per-thread flag which is raised before the valid access to poisoned memory.
> > This flag checked in __asan_report*() function. If it raised then we shouldn't print any error message,
> > just silently exit from report.
> 
> Can't you just use __attribute__((no_sanitize_address)) on the functions
> that have such a code?  Or you could use special macros for those accesses
> (which could e.g. call function to read memory or write memory, implemented
> in assembly or in __attribute__((no_sanitize_address)) function), or
> temporarily unpoison and poison again.

Also, if you always rely on recovery for kernel-address, wonder why all the
effort to make it optional (when it could be decided based on
flag_sanitize & SANITIZE_KERNEL_ADDRESS), and whether I should wait
with 4.9.2-rc1 for that (given that 4.9 branch now has kasan support
backported, but not -fsanitize-recover (neither old style, nor new style)).
I'd really like to release 4.9.2 soon...

	Jakub

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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-23 10:00             ` Jakub Jelinek
  2014-10-23 10:07               ` Jakub Jelinek
@ 2014-10-23 10:11               ` Andrey Ryabinin
  2014-10-23 10:17                 ` Jakub Jelinek
  1 sibling, 1 reply; 73+ messages in thread
From: Andrey Ryabinin @ 2014-10-23 10:11 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Yury Gribov, GCC Patches, Konstantin Serebryany, Dmitry Vyukov,
	Konstantin Khlebnikov

On 10/23/2014 01:55 PM, Jakub Jelinek wrote:
> On Thu, Oct 23, 2014 at 01:51:12PM +0400, Andrey Ryabinin wrote:
>> IMO we don't need different versions of __asan_load* and __asan_load*_noabort, because
>> -fno-sanitize-recover=kernel-address will never work with the linux kernel.
>>
>> I already said this before, and repeat this once again:
>> There is few places in kernel where we validly touch poisoned memory,
>> so we need to disable error reporting in runtime for such memory accesses.
>> I use per-thread flag which is raised before the valid access to poisoned memory.
>> This flag checked in __asan_report*() function. If it raised then we shouldn't print any error message,
>> just silently exit from report.
> 
> Can't you just use __attribute__((no_sanitize_address)) on the functions
> that have such a code?  Or you could use special macros for those accesses
> (which could e.g. call function to read memory or write memory, implemented
> in assembly or in __attribute__((no_sanitize_address)) function), or

Those are quite generic functions used from a lot of places. So we want to instrument
them in general, but there are few call sites which use those functions for poisoned memory.


> temporarily unpoison and poison again.
> 

That's a bit tricky. State of shadow memory is unknown, so we would need to store shadow
somewhere before unpoisoning to restore it later.

> 	Jakub
> 

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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-23 10:11               ` Andrey Ryabinin
@ 2014-10-23 10:17                 ` Jakub Jelinek
  2014-10-23 10:38                   ` Yury Gribov
  0 siblings, 1 reply; 73+ messages in thread
From: Jakub Jelinek @ 2014-10-23 10:17 UTC (permalink / raw)
  To: Andrey Ryabinin
  Cc: Yury Gribov, GCC Patches, Konstantin Serebryany, Dmitry Vyukov,
	Konstantin Khlebnikov

On Thu, Oct 23, 2014 at 02:09:47PM +0400, Andrey Ryabinin wrote:
> On 10/23/2014 01:55 PM, Jakub Jelinek wrote:
> > On Thu, Oct 23, 2014 at 01:51:12PM +0400, Andrey Ryabinin wrote:
> >> IMO we don't need different versions of __asan_load* and __asan_load*_noabort, because
> >> -fno-sanitize-recover=kernel-address will never work with the linux kernel.
> >>
> >> I already said this before, and repeat this once again:
> >> There is few places in kernel where we validly touch poisoned memory,
> >> so we need to disable error reporting in runtime for such memory accesses.
> >> I use per-thread flag which is raised before the valid access to poisoned memory.
> >> This flag checked in __asan_report*() function. If it raised then we shouldn't print any error message,
> >> just silently exit from report.
> > 
> > Can't you just use __attribute__((no_sanitize_address)) on the functions
> > that have such a code?  Or you could use special macros for those accesses
> > (which could e.g. call function to read memory or write memory, implemented
> > in assembly or in __attribute__((no_sanitize_address)) function), or
> 
> Those are quite generic functions used from a lot of places. So we want to instrument
> them in general, but there are few call sites which use those functions for poisoned memory.

Actually, -fsanitize=kernel-address forcibly uses function calls (i.e.
__asan_load* etc. rather than __asan_report_load* only if inline shadow
memory test suggested there is a problem).
So, at that point you can include your ugly hacks in __asan_load* logic in
the kernel, the difference between __asan_load4 and __asan_load4_noabort
will be just that the latter will always return, while the former will not
if some error has been reported.
All the __asan_load* and __asan_store* entrypoints, regardless of
-f{,no-}sanitize-recover=kernel-address are by definition not noreturn, they
in the common case (if the code is not buggy) return.

	Jakub

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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-23 10:07               ` Jakub Jelinek
@ 2014-10-23 10:24                 ` Andrey Ryabinin
  2014-10-23 10:27                   ` Yury Gribov
  0 siblings, 1 reply; 73+ messages in thread
From: Andrey Ryabinin @ 2014-10-23 10:24 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Yury Gribov, GCC Patches, Konstantin Serebryany, Dmitry Vyukov,
	Konstantin Khlebnikov

On 10/23/2014 02:00 PM, Jakub Jelinek wrote:
> On Thu, Oct 23, 2014 at 11:55:32AM +0200, Jakub Jelinek wrote:
>> On Thu, Oct 23, 2014 at 01:51:12PM +0400, Andrey Ryabinin wrote:
>>> IMO we don't need different versions of __asan_load* and __asan_load*_noabort, because
>>> -fno-sanitize-recover=kernel-address will never work with the linux kernel.
>>>
>>> I already said this before, and repeat this once again:
>>> There is few places in kernel where we validly touch poisoned memory,
>>> so we need to disable error reporting in runtime for such memory accesses.
>>> I use per-thread flag which is raised before the valid access to poisoned memory.
>>> This flag checked in __asan_report*() function. If it raised then we shouldn't print any error message,
>>> just silently exit from report.
>>
>> Can't you just use __attribute__((no_sanitize_address)) on the functions
>> that have such a code?  Or you could use special macros for those accesses
>> (which could e.g. call function to read memory or write memory, implemented
>> in assembly or in __attribute__((no_sanitize_address)) function), or
>> temporarily unpoison and poison again.
> 
> Also, if you always rely on recovery for kernel-address, wonder why all the
> effort to make it optional (when it could be decided based on
> flag_sanitize & SANITIZE_KERNEL_ADDRESS), and whether I should wait
> with 4.9.2-rc1 for that (given that 4.9 branch now has kasan support
> backported, but not -fsanitize-recover (neither old style, nor new style)).
> I'd really like to release 4.9.2 soon...
> 

-fsanitize-recover needed only for inline instrumentation, and 4.9 don't support
inline instrumentation for kernel-address. There is no reason to delay release
unless you want to see inline support  in 4.9.



> 	Jakub
> 

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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-23 10:24                 ` Andrey Ryabinin
@ 2014-10-23 10:27                   ` Yury Gribov
  0 siblings, 0 replies; 73+ messages in thread
From: Yury Gribov @ 2014-10-23 10:27 UTC (permalink / raw)
  To: Andrey Ryabinin, Jakub Jelinek
  Cc: GCC Patches, Konstantin Serebryany, Dmitry Vyukov, Konstantin Khlebnikov

On 10/23/2014 02:20 PM, Andrey Ryabinin wrote:
> On 10/23/2014 02:00 PM, Jakub Jelinek wrote:
>> On Thu, Oct 23, 2014 at 11:55:32AM +0200, Jakub Jelinek wrote:
>>> On Thu, Oct 23, 2014 at 01:51:12PM +0400, Andrey Ryabinin wrote:
>>>> IMO we don't need different versions of __asan_load* and __asan_load*_noabort, because
>>>> -fno-sanitize-recover=kernel-address will never work with the linux kernel.
>>>>
>>>> I already said this before, and repeat this once again:
>>>> There is few places in kernel where we validly touch poisoned memory,
>>>> so we need to disable error reporting in runtime for such memory accesses.
>>>> I use per-thread flag which is raised before the valid access to poisoned memory.
>>>> This flag checked in __asan_report*() function. If it raised then we shouldn't print any error message,
>>>> just silently exit from report.
>>>
>>> Can't you just use __attribute__((no_sanitize_address)) on the functions
>>> that have such a code?  Or you could use special macros for those accesses
>>> (which could e.g. call function to read memory or write memory, implemented
>>> in assembly or in __attribute__((no_sanitize_address)) function), or
>>> temporarily unpoison and poison again.
>>
>> Also, if you always rely on recovery for kernel-address, wonder why all the
>> effort to make it optional (when it could be decided based on
>> flag_sanitize & SANITIZE_KERNEL_ADDRESS), and whether I should wait
>> with 4.9.2-rc1 for that (given that 4.9 branch now has kasan support
>> backported, but not -fsanitize-recover (neither old style, nor new style)).
>> I'd really like to release 4.9.2 soon...
>>
>
> -fsanitize-recover needed only for inline instrumentation, and 4.9 don't support
> inline instrumentation for kernel-address. There is no reason to delay release
> unless you want to see inline support  in 4.9.

+1

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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-23 10:17                 ` Jakub Jelinek
@ 2014-10-23 10:38                   ` Yury Gribov
  2014-10-23 10:39                     ` Jakub Jelinek
  0 siblings, 1 reply; 73+ messages in thread
From: Yury Gribov @ 2014-10-23 10:38 UTC (permalink / raw)
  To: Jakub Jelinek, Andrey Ryabinin
  Cc: GCC Patches, Konstantin Serebryany, Dmitry Vyukov, Konstantin Khlebnikov

On 10/23/2014 02:16 PM, Jakub Jelinek wrote:
> On Thu, Oct 23, 2014 at 02:09:47PM +0400, Andrey Ryabinin wrote:
>> On 10/23/2014 01:55 PM, Jakub Jelinek wrote:
>>> On Thu, Oct 23, 2014 at 01:51:12PM +0400, Andrey Ryabinin wrote:
>>>> IMO we don't need different versions of __asan_load* and __asan_load*_noabort, because
>>>> -fno-sanitize-recover=kernel-address will never work with the linux kernel.
>>>>
>>>> I already said this before, and repeat this once again:
>>>> There is few places in kernel where we validly touch poisoned memory,
>>>> so we need to disable error reporting in runtime for such memory accesses.
>>>> I use per-thread flag which is raised before the valid access to poisoned memory.
>>>> This flag checked in __asan_report*() function. If it raised then we shouldn't print any error message,
>>>> just silently exit from report.
>>>
>>> Can't you just use __attribute__((no_sanitize_address)) on the functions
>>> that have such a code?  Or you could use special macros for those accesses
>>> (which could e.g. call function to read memory or write memory, implemented
>>> in assembly or in __attribute__((no_sanitize_address)) function), or
>>
>> Those are quite generic functions used from a lot of places. So we want to instrument
>> them in general, but there are few call sites which use those functions for poisoned memory.
>
> Actually, -fsanitize=kernel-address forcibly uses function calls (i.e.
> __asan_load* etc. rather than __asan_report_load* only if inline shadow
> memory test suggested there is a problem).

Actually this is a historical artifact.  If inlining proves to be 
significantly faster, they may want to switch.

> So, at that point you can include your ugly hacks in __asan_load* logic in
> the kernel, the difference between __asan_load4 and __asan_load4_noabort
> will be just that the latter will always return, while the former will not
> if some error has been reported.
> All the __asan_load* and __asan_store* entrypoints, regardless of
> -f{,no-}sanitize-recover=kernel-address are by definition not noreturn, they
> in the common case (if the code is not buggy) return.

Perhaps we should just keep __asan_load* as is and leave the decision 
whether to abort or continue for the runtime?  This would make semantics 
of -fsanitize-recover cumbersome though (because it wouldn't work if 
user selects outline instrumentation).

-Y

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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-23 10:38                   ` Yury Gribov
@ 2014-10-23 10:39                     ` Jakub Jelinek
  2014-10-23 11:12                       ` Andrey Ryabinin
  0 siblings, 1 reply; 73+ messages in thread
From: Jakub Jelinek @ 2014-10-23 10:39 UTC (permalink / raw)
  To: Yury Gribov
  Cc: Andrey Ryabinin, GCC Patches, Konstantin Serebryany,
	Dmitry Vyukov, Konstantin Khlebnikov

On Thu, Oct 23, 2014 at 02:33:42PM +0400, Yury Gribov wrote:
> Actually this is a historical artifact.  If inlining proves to be
> significantly faster, they may want to switch.

Ok.

> >So, at that point you can include your ugly hacks in __asan_load* logic in
> >the kernel, the difference between __asan_load4 and __asan_load4_noabort
> >will be just that the latter will always return, while the former will not
> >if some error has been reported.
> >All the __asan_load* and __asan_store* entrypoints, regardless of
> >-f{,no-}sanitize-recover=kernel-address are by definition not noreturn, they
> >in the common case (if the code is not buggy) return.
> 
> Perhaps we should just keep __asan_load* as is and leave the decision
> whether to abort or continue for the runtime?  This would make semantics of
> -fsanitize-recover cumbersome though (because it wouldn't work if user
> selects outline instrumentation).

Well, the "don't ever report anything while some per-CPU flag is set" thing
can be considered as part of the "is this memory access ok" test, it is
pretending everything is accessible.

But, otherwise, if it is supposed to be developer's decision at compile
time, __asan_load*_noabort should better always continue, even if it
reported issues, and __asan_load* should better not return after reporting
errors.

	Jakub

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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-23 10:39                     ` Jakub Jelinek
@ 2014-10-23 11:12                       ` Andrey Ryabinin
  2014-10-24  8:37                         ` Yury Gribov
  0 siblings, 1 reply; 73+ messages in thread
From: Andrey Ryabinin @ 2014-10-23 11:12 UTC (permalink / raw)
  To: Jakub Jelinek, Yury Gribov
  Cc: GCC Patches, Konstantin Serebryany, Dmitry Vyukov, Konstantin Khlebnikov

On 10/23/2014 02:38 PM, Jakub Jelinek wrote:
> On Thu, Oct 23, 2014 at 02:33:42PM +0400, Yury Gribov wrote:
>> Actually this is a historical artifact.  If inlining proves to be
>> significantly faster, they may want to switch.
> 
> Ok.
> 
>>> So, at that point you can include your ugly hacks in __asan_load* logic in
>>> the kernel, the difference between __asan_load4 and __asan_load4_noabort
>>> will be just that the latter will always return, while the former will not
>>> if some error has been reported.
>>> All the __asan_load* and __asan_store* entrypoints, regardless of
>>> -f{,no-}sanitize-recover=kernel-address are by definition not noreturn, they
>>> in the common case (if the code is not buggy) return.
>>
>> Perhaps we should just keep __asan_load* as is and leave the decision
>> whether to abort or continue for the runtime?  This would make semantics of
>> -fsanitize-recover cumbersome though (because it wouldn't work if user
>> selects outline instrumentation).
> 
> Well, the "don't ever report anything while some per-CPU flag is set" thing
> can be considered as part of the "is this memory access ok" test, it is
> pretending everything is accessible.
> 
> But, otherwise, if it is supposed to be developer's decision at compile
> time, __asan_load*_noabort should better always continue, even if it
> reported issues, and __asan_load* should better not return after reporting
> errors.
> 

True, but why we need new functions for that.
__asan_load could also abort or not depending on what user/developer wants.
Why we have to rebuild the entire kernel if someone wants to switch from abort to noabort?

I'm not against __asan_load_noabort, I'm just saying that this is no point to have separate
__asan_load/__asan_load_noabort functions in kernel.

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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-23 11:12                       ` Andrey Ryabinin
@ 2014-10-24  8:37                         ` Yury Gribov
  2014-10-24  9:46                           ` Dmitry Vyukov
  0 siblings, 1 reply; 73+ messages in thread
From: Yury Gribov @ 2014-10-24  8:37 UTC (permalink / raw)
  To: Andrey Ryabinin, Jakub Jelinek
  Cc: GCC Patches, Konstantin Serebryany, Dmitry Vyukov, Konstantin Khlebnikov

On 10/23/2014 03:10 PM, Andrey Ryabinin wrote:
> On 10/23/2014 02:38 PM, Jakub Jelinek wrote:
>> On Thu, Oct 23, 2014 at 02:33:42PM +0400, Yury Gribov wrote:
>>> Actually this is a historical artifact.  If inlining proves to be
>>> significantly faster, they may want to switch.
>>
>> Ok.
>>
>>>> So, at that point you can include your ugly hacks in __asan_load* logic in
>>>> the kernel, the difference between __asan_load4 and __asan_load4_noabort
>>>> will be just that the latter will always return, while the former will not
>>>> if some error has been reported.
>>>> All the __asan_load* and __asan_store* entrypoints, regardless of
>>>> -f{,no-}sanitize-recover=kernel-address are by definition not noreturn, they
>>>> in the common case (if the code is not buggy) return.
>>>
>>> Perhaps we should just keep __asan_load* as is and leave the decision
>>> whether to abort or continue for the runtime?  This would make semantics of
>>> -fsanitize-recover cumbersome though (because it wouldn't work if user
>>> selects outline instrumentation).
>>
>> Well, the "don't ever report anything while some per-CPU flag is set" thing
>> can be considered as part of the "is this memory access ok" test, it is
>> pretending everything is accessible.
>>
>> But, otherwise, if it is supposed to be developer's decision at compile
>> time, __asan_load*_noabort should better always continue, even if it
>> reported issues, and __asan_load* should better not return after reporting
>> errors.
>>
>
> True, but why we need new functions for that.
> __asan_load could also abort or not depending on what user/developer wants.
> Why we have to rebuild the entire kernel if someone wants to switch from abort to noabort?
>
> I'm not against __asan_load_noabort, I'm just saying that this is no point to have separate
> __asan_load/__asan_load_noabort functions in kernel.

I'd still suggest to emit __asan_load_noabort so that we match userspace 
(where __asan_load strictly matches __asan_report in terminating the 
program).  Behavior of __asan_load_noabort can further be restricted by 
user via various environment settings (kernel parameters, /proc, etc.).

@Dmitry: what's your opinion on this?

-Y

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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-24  8:37                         ` Yury Gribov
@ 2014-10-24  9:46                           ` Dmitry Vyukov
  2014-10-24  9:52                             ` Jakub Jelinek
  2014-10-24 10:01                             ` Yury Gribov
  0 siblings, 2 replies; 73+ messages in thread
From: Dmitry Vyukov @ 2014-10-24  9:46 UTC (permalink / raw)
  To: Yury Gribov
  Cc: Andrey Ryabinin, Jakub Jelinek, GCC Patches,
	Konstantin Serebryany, Konstantin Khlebnikov

On Fri, Oct 24, 2014 at 12:28 PM, Yury Gribov <y.gribov@samsung.com> wrote:
> On 10/23/2014 03:10 PM, Andrey Ryabinin wrote:
>>
>> On 10/23/2014 02:38 PM, Jakub Jelinek wrote:
>>>
>>> On Thu, Oct 23, 2014 at 02:33:42PM +0400, Yury Gribov wrote:
>>>>
>>>> Actually this is a historical artifact.  If inlining proves to be
>>>> significantly faster, they may want to switch.
>>>
>>>
>>> Ok.
>>>
>>>>> So, at that point you can include your ugly hacks in __asan_load* logic
>>>>> in
>>>>> the kernel, the difference between __asan_load4 and
>>>>> __asan_load4_noabort
>>>>> will be just that the latter will always return, while the former will
>>>>> not
>>>>> if some error has been reported.
>>>>> All the __asan_load* and __asan_store* entrypoints, regardless of
>>>>> -f{,no-}sanitize-recover=kernel-address are by definition not noreturn,
>>>>> they
>>>>> in the common case (if the code is not buggy) return.
>>>>
>>>>
>>>> Perhaps we should just keep __asan_load* as is and leave the decision
>>>> whether to abort or continue for the runtime?  This would make semantics
>>>> of
>>>> -fsanitize-recover cumbersome though (because it wouldn't work if user
>>>> selects outline instrumentation).
>>>
>>>
>>> Well, the "don't ever report anything while some per-CPU flag is set"
>>> thing
>>> can be considered as part of the "is this memory access ok" test, it is
>>> pretending everything is accessible.
>>>
>>> But, otherwise, if it is supposed to be developer's decision at compile
>>> time, __asan_load*_noabort should better always continue, even if it
>>> reported issues, and __asan_load* should better not return after
>>> reporting
>>> errors.
>>>
>>
>> True, but why we need new functions for that.
>> __asan_load could also abort or not depending on what user/developer
>> wants.
>> Why we have to rebuild the entire kernel if someone wants to switch from
>> abort to noabort?
>>
>> I'm not against __asan_load_noabort, I'm just saying that this is no point
>> to have separate
>> __asan_load/__asan_load_noabort functions in kernel.
>
>
> I'd still suggest to emit __asan_load_noabort so that we match userspace
> (where __asan_load strictly matches __asan_report in terminating the
> program).  Behavior of __asan_load_noabort can further be restricted by user
> via various environment settings (kernel parameters, /proc, etc.).
>
> @Dmitry: what's your opinion on this?


I am somewhat lost in this thread and probably missing something.
But why do we need __asan_load (which is not noabort) at all? Outline
instrumentation is non a default mode for both user-space asan and
kasan (at least in the envisioned future). I would expect that these
non-typical cases that use outline instrumentation can also bear the
overhead of non-noreturn functions. Can we use just one version of
__asan_load and let runtime decide on abort?

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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-24  9:46                           ` Dmitry Vyukov
@ 2014-10-24  9:52                             ` Jakub Jelinek
  2014-10-24  9:56                               ` Dmitry Vyukov
  2014-10-24  9:59                               ` Jakub Jelinek
  2014-10-24 10:01                             ` Yury Gribov
  1 sibling, 2 replies; 73+ messages in thread
From: Jakub Jelinek @ 2014-10-24  9:52 UTC (permalink / raw)
  To: Dmitry Vyukov
  Cc: Yury Gribov, Andrey Ryabinin, GCC Patches, Konstantin Serebryany,
	Konstantin Khlebnikov

On Fri, Oct 24, 2014 at 01:44:27PM +0400, Dmitry Vyukov wrote:
> I am somewhat lost in this thread and probably missing something.
> But why do we need __asan_load (which is not noabort) at all? Outline
> instrumentation is non a default mode for both user-space asan and
> kasan (at least in the envisioned future). I would expect that these
> non-typical cases that use outline instrumentation can also bear the
> overhead of non-noreturn functions. Can we use just one version of
> __asan_load and let runtime decide on abort?

__asan_load actually must never be noreturn, because in the common
case where the load is valid it of course returns.

	Jakub

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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-24  9:52                             ` Jakub Jelinek
@ 2014-10-24  9:56                               ` Dmitry Vyukov
  2014-10-24  9:59                               ` Jakub Jelinek
  1 sibling, 0 replies; 73+ messages in thread
From: Dmitry Vyukov @ 2014-10-24  9:56 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Yury Gribov, Andrey Ryabinin, GCC Patches, Konstantin Serebryany,
	Konstantin Khlebnikov

On Fri, Oct 24, 2014 at 1:50 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Fri, Oct 24, 2014 at 01:44:27PM +0400, Dmitry Vyukov wrote:
>> I am somewhat lost in this thread and probably missing something.
>> But why do we need __asan_load (which is not noabort) at all? Outline
>> instrumentation is non a default mode for both user-space asan and
>> kasan (at least in the envisioned future). I would expect that these
>> non-typical cases that use outline instrumentation can also bear the
>> overhead of non-noreturn functions. Can we use just one version of
>> __asan_load and let runtime decide on abort?
>
> __asan_load actually must never be noreturn, because in the common
> case where the load is valid it of course returns.


Right!

Then I am puzzled by that message by Yury:

"I'd still suggest to emit __asan_load_noabort so that we match
userspace (where __asan_load strictly matches __asan_report in
terminating the program)"

Why are we discussing __asan_load_noabort?

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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-24  9:52                             ` Jakub Jelinek
  2014-10-24  9:56                               ` Dmitry Vyukov
@ 2014-10-24  9:59                               ` Jakub Jelinek
  1 sibling, 0 replies; 73+ messages in thread
From: Jakub Jelinek @ 2014-10-24  9:59 UTC (permalink / raw)
  To: Dmitry Vyukov
  Cc: Yury Gribov, Andrey Ryabinin, GCC Patches, Konstantin Serebryany,
	Konstantin Khlebnikov

On Fri, Oct 24, 2014 at 11:50:58AM +0200, Jakub Jelinek wrote:
> On Fri, Oct 24, 2014 at 01:44:27PM +0400, Dmitry Vyukov wrote:
> > I am somewhat lost in this thread and probably missing something.
> > But why do we need __asan_load (which is not noabort) at all? Outline
> > instrumentation is non a default mode for both user-space asan and
> > kasan (at least in the envisioned future). I would expect that these
> > non-typical cases that use outline instrumentation can also bear the
> > overhead of non-noreturn functions. Can we use just one version of
> > __asan_load and let runtime decide on abort?
> 
> __asan_load actually must never be noreturn, because in the common
> case where the load is valid it of course returns.

The point of __asan_load*_noabort (vs. __asan_load*) and
__asan_report*_noabort (vs. __asan_report*) is to allow the choice
what is fatal and what is not fatal to be done at compile time,
per compilation unit.  For __asan_report* that is a must, as __asan_report*
without noabort is noreturn, for __asan_load* which is not noreturn
the implementation can of course choose not to make something fatal when it
wishes.  Without -fsanitize-recover={address,kernel-address} support,
the choice could be done only per program or kernel globally, without a way
for programmer to differentiate.

	Jakub

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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-24  9:46                           ` Dmitry Vyukov
  2014-10-24  9:52                             ` Jakub Jelinek
@ 2014-10-24 10:01                             ` Yury Gribov
  2014-10-24 10:21                               ` Dmitry Vyukov
  1 sibling, 1 reply; 73+ messages in thread
From: Yury Gribov @ 2014-10-24 10:01 UTC (permalink / raw)
  To: Dmitry Vyukov
  Cc: Andrey Ryabinin, Jakub Jelinek, GCC Patches,
	Konstantin Serebryany, Konstantin Khlebnikov

On 10/24/2014 01:44 PM, Dmitry Vyukov wrote:
> On Fri, Oct 24, 2014 at 12:28 PM, Yury Gribov <y.gribov@samsung.com> wrote:
>> On 10/23/2014 03:10 PM, Andrey Ryabinin wrote:
>>>
>>> On 10/23/2014 02:38 PM, Jakub Jelinek wrote:
>>>>
>>>> On Thu, Oct 23, 2014 at 02:33:42PM +0400, Yury Gribov wrote:
>>>>>
>>>>> Actually this is a historical artifact.  If inlining proves to be
>>>>> significantly faster, they may want to switch.
>>>>
>>>>
>>>> Ok.
>>>>
>>>>>> So, at that point you can include your ugly hacks in __asan_load* logic
>>>>>> in
>>>>>> the kernel, the difference between __asan_load4 and
>>>>>> __asan_load4_noabort
>>>>>> will be just that the latter will always return, while the former will
>>>>>> not
>>>>>> if some error has been reported.
>>>>>> All the __asan_load* and __asan_store* entrypoints, regardless of
>>>>>> -f{,no-}sanitize-recover=kernel-address are by definition not noreturn,
>>>>>> they
>>>>>> in the common case (if the code is not buggy) return.
>>>>>
>>>>>
>>>>> Perhaps we should just keep __asan_load* as is and leave the decision
>>>>> whether to abort or continue for the runtime?  This would make semantics
>>>>> of
>>>>> -fsanitize-recover cumbersome though (because it wouldn't work if user
>>>>> selects outline instrumentation).
>>>>
>>>>
>>>> Well, the "don't ever report anything while some per-CPU flag is set"
>>>> thing
>>>> can be considered as part of the "is this memory access ok" test, it is
>>>> pretending everything is accessible.
>>>>
>>>> But, otherwise, if it is supposed to be developer's decision at compile
>>>> time, __asan_load*_noabort should better always continue, even if it
>>>> reported issues, and __asan_load* should better not return after
>>>> reporting
>>>> errors.
>>>>
>>>
>>> True, but why we need new functions for that.
>>> __asan_load could also abort or not depending on what user/developer
>>> wants.
>>> Why we have to rebuild the entire kernel if someone wants to switch from
>>> abort to noabort?
>>>
>>> I'm not against __asan_load_noabort, I'm just saying that this is no point
>>> to have separate
>>> __asan_load/__asan_load_noabort functions in kernel.
>>
>>
>> I'd still suggest to emit __asan_load_noabort so that we match userspace
>> (where __asan_load strictly matches __asan_report in terminating the
>> program).  Behavior of __asan_load_noabort can further be restricted by user
>> via various environment settings (kernel parameters, /proc, etc.).
>>
>> @Dmitry: what's your opinion on this?
>
> I am somewhat lost in this thread and probably missing something.
> But why do we need __asan_load (which is not noabort) at all? Outline
> instrumentation is non a default mode for both user-space asan and
> kasan (at least in the envisioned future).

Well, it's still enabled automatically if number of memory accesses is 
getting large enough (I think it was 7000?) so it is default in a way.

> I would expect that these
> non-typical cases that use outline instrumentation can also bear the
> overhead of non-noreturn functions.

As Jakub mentioned both __asan_load and __asan_load_noabort will _not_ 
be NORETURN.  Two different versions are necessary so that compiler can 
insert outline instrumentation that matches the -fsanitize-recover setting.

 > Can we use just one version of
> __asan_load and let runtime decide on abort?

In this case semantics of inline and outline instrumentation will differ 
(the former depending on -fsanitize-recover compile-time setting and the 
latter depending on runtime options) which may be undesirable given that 
compiler may automatically choose to switch from inline to outline 
depending on function size.

-Y

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

* Re: [PATCHv4] Enable -fsanitize-recover for KASan
  2014-10-24 10:01                             ` Yury Gribov
@ 2014-10-24 10:21                               ` Dmitry Vyukov
  0 siblings, 0 replies; 73+ messages in thread
From: Dmitry Vyukov @ 2014-10-24 10:21 UTC (permalink / raw)
  To: Yury Gribov
  Cc: Andrey Ryabinin, Jakub Jelinek, GCC Patches,
	Konstantin Serebryany, Konstantin Khlebnikov

On Fri, Oct 24, 2014 at 1:59 PM, Yury Gribov <y.gribov@samsung.com> wrote:
> On 10/24/2014 01:44 PM, Dmitry Vyukov wrote:
>>
>> On Fri, Oct 24, 2014 at 12:28 PM, Yury Gribov <y.gribov@samsung.com>
>> wrote:
>>>
>>> On 10/23/2014 03:10 PM, Andrey Ryabinin wrote:
>>>>
>>>>
>>>> On 10/23/2014 02:38 PM, Jakub Jelinek wrote:
>>>>>
>>>>>
>>>>> On Thu, Oct 23, 2014 at 02:33:42PM +0400, Yury Gribov wrote:
>>>>>>
>>>>>>
>>>>>> Actually this is a historical artifact.  If inlining proves to be
>>>>>> significantly faster, they may want to switch.
>>>>>
>>>>>
>>>>>
>>>>> Ok.
>>>>>
>>>>>>> So, at that point you can include your ugly hacks in __asan_load*
>>>>>>> logic
>>>>>>> in
>>>>>>> the kernel, the difference between __asan_load4 and
>>>>>>> __asan_load4_noabort
>>>>>>> will be just that the latter will always return, while the former
>>>>>>> will
>>>>>>> not
>>>>>>> if some error has been reported.
>>>>>>> All the __asan_load* and __asan_store* entrypoints, regardless of
>>>>>>> -f{,no-}sanitize-recover=kernel-address are by definition not
>>>>>>> noreturn,
>>>>>>> they
>>>>>>> in the common case (if the code is not buggy) return.
>>>>>>
>>>>>>
>>>>>>
>>>>>> Perhaps we should just keep __asan_load* as is and leave the decision
>>>>>> whether to abort or continue for the runtime?  This would make
>>>>>> semantics
>>>>>> of
>>>>>> -fsanitize-recover cumbersome though (because it wouldn't work if user
>>>>>> selects outline instrumentation).
>>>>>
>>>>>
>>>>>
>>>>> Well, the "don't ever report anything while some per-CPU flag is set"
>>>>> thing
>>>>> can be considered as part of the "is this memory access ok" test, it is
>>>>> pretending everything is accessible.
>>>>>
>>>>> But, otherwise, if it is supposed to be developer's decision at compile
>>>>> time, __asan_load*_noabort should better always continue, even if it
>>>>> reported issues, and __asan_load* should better not return after
>>>>> reporting
>>>>> errors.
>>>>>
>>>>
>>>> True, but why we need new functions for that.
>>>> __asan_load could also abort or not depending on what user/developer
>>>> wants.
>>>> Why we have to rebuild the entire kernel if someone wants to switch from
>>>> abort to noabort?
>>>>
>>>> I'm not against __asan_load_noabort, I'm just saying that this is no
>>>> point
>>>> to have separate
>>>> __asan_load/__asan_load_noabort functions in kernel.
>>>
>>>
>>>
>>> I'd still suggest to emit __asan_load_noabort so that we match userspace
>>> (where __asan_load strictly matches __asan_report in terminating the
>>> program).  Behavior of __asan_load_noabort can further be restricted by
>>> user
>>> via various environment settings (kernel parameters, /proc, etc.).
>>>
>>> @Dmitry: what's your opinion on this?
>>
>>
>> I am somewhat lost in this thread and probably missing something.
>> But why do we need __asan_load (which is not noabort) at all? Outline
>> instrumentation is non a default mode for both user-space asan and
>> kasan (at least in the envisioned future).
>
>
> Well, it's still enabled automatically if number of memory accesses is
> getting large enough (I think it was 7000?) so it is default in a way.
>
>> I would expect that these
>> non-typical cases that use outline instrumentation can also bear the
>> overhead of non-noreturn functions.
>
>
> As Jakub mentioned both __asan_load and __asan_load_noabort will _not_ be
> NORETURN.  Two different versions are necessary so that compiler can insert
> outline instrumentation that matches the -fsanitize-recover setting.
>
>> Can we use just one version of
>>
>> __asan_load and let runtime decide on abort?
>
>
> In this case semantics of inline and outline instrumentation will differ
> (the former depending on -fsanitize-recover compile-time setting and the
> latter depending on runtime options) which may be undesirable given that
> compiler may automatically choose to switch from inline to outline depending
> on function size.


Ok, thank you, now I am on the same page.

Yury, I would expect that the inline instrumentation will become the
default in the kernel as well (it's 2 times faster, or maybe even more
if happens to affect loop registration). Do you agree?
If we consider inline as default, then the user won't be able to
simply switch between abort/noabort with a runtime flag w/o rebuilding
the kernel, because for __asan_report* we have to have 2 versions.
I would also consider that abort/noabort is pretty persistent in a
particular testing environment -- you either use one or another and do
not switch frequently between them.

Taking that into account and the fact that __asan_load* can be emitted
due to call threshold, I am mildly in favor of Jakub's position of
making it all consistent between user/kernel and load/report and
explicit. To make it clear, I mean the runtime interface:
__asan_load* -- not-noreturn, always aborts in runtime on failure
__asan_load*_noabort - not-noreturn, never aborts in runtime on failure

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

* [PATCH v5] Enable -fsanitize-recover for KASan
  2014-10-23  7:15     ` [PATCHv4] " Yury Gribov
  2014-10-23  7:20       ` Jakub Jelinek
@ 2014-10-28  8:46       ` Yury Gribov
  2014-10-28  9:31         ` Jakub Jelinek
  1 sibling, 1 reply; 73+ messages in thread
From: Yury Gribov @ 2014-10-28  8:46 UTC (permalink / raw)
  To: GCC Patches
  Cc: Jakub Jelinek, Konstantin Serebryany, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

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

Hi all,

On 10/23/2014 11:11 AM, Yury Gribov wrote:
>>>> This patch enables -fsanitize-recover for KASan by default. This causes
>>>> KASan to continue execution after error in case of inline
>>>> instrumentation. This feature is needed because
>>>> - reports during early bootstrap won't even be printed
>>>> - needed to run all tests w/o rebooting machine for every test
>>>> - needed for interactive work on desktop
>>
>> This is the third version of patch which renames -fsanitize-recover to
>> -fubsan-recover and introduces -fasan-recover (enabled by default for
>> KASan). It also moves flag handling to finish_options per Jakub's
>> request.
>
> A new version of patch based upon Jakub's recent changes to
> -fsanitize-recover=.  I've renamed __asan_report_recover_load* to
> __asan_report_load*_noabort to match UBSan's style.
>
> Note that currently -fsanitize=kernel-address
> -fno-sanitize-recover=kernel-address won't work as expected because we
> miss __asan_load*_abort family of functions in libasan.

A new version of patch with full support for __asan_report_loadX_noabort 
and __asan_loadX_noabort based upon recent discussion with KASan folks.

Bootstrapped and regtested on x64.

-Y


[-- Attachment #2: 0001-Enable-fsanitize-recover-for-KASan-v5.patch --]
[-- Type: text/x-patch, Size: 15435 bytes --]

From ee93b44c0b87da5346476c2554697168d07c6600 Mon Sep 17 00:00:00 2001
From: Yury Gribov <y.gribov@samsung.com>
Date: Wed, 22 Oct 2014 17:24:55 +0400
Subject: [PATCH] Enable -fsanitize-recover for KASan.

2014-10-23  Yury Gribov  <y.gribov@samsung.com>

gcc/
	* asan.c (report_error_func): Add noabort path.
	(check_func): Ditto.  Formatting.
	(asan_expand_check_ifn): Handle noabort path.
	* common.opt (flag_sanitize_recover): Add SANITIZE_KERNEL_ADDRESS
	to default value.
	* doc/invoke.texi (-fsanitize-recover=): Mention KASan.
	* opts.c (finish_options): Reword comment.
	* sanitizer.def: Add noabort ASan builtins.

gcc/testsuite/
	* c-c++-common/asan/kasan-recover-1.c: New test.
	* c-c++-common/asan/kasan-recover-2.c: New test.
---
 gcc/asan.c                                        |   81 ++++++++++++++-------
 gcc/common.opt                                    |    2 +-
 gcc/doc/invoke.texi                               |    8 +-
 gcc/opts.c                                        |    4 +-
 gcc/sanitizer.def                                 |   62 ++++++++++++++++
 gcc/testsuite/c-c++-common/asan/kasan-recover-1.c |   12 +++
 gcc/testsuite/c-c++-common/asan/kasan-recover-2.c |   12 +++
 7 files changed, 150 insertions(+), 31 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/asan/kasan-recover-1.c
 create mode 100644 gcc/testsuite/c-c++-common/asan/kasan-recover-2.c

diff --git a/gcc/asan.c b/gcc/asan.c
index 97f0b4c..93536ad 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -1344,44 +1344,72 @@ 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, int *nargs)
-{
-  static enum built_in_function report[2][6]
-    = { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
-	  BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
-	  BUILT_IN_ASAN_REPORT_LOAD16, BUILT_IN_ASAN_REPORT_LOAD_N },
-	{ BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2,
-	  BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
-	  BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } };
+report_error_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
+		   int *nargs)
+{
+  static enum built_in_function report[2][2][6]
+    = { { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
+	    BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
+	    BUILT_IN_ASAN_REPORT_LOAD16, BUILT_IN_ASAN_REPORT_LOAD_N },
+	  { BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2,
+	    BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
+	    BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } },
+	{ { BUILT_IN_ASAN_REPORT_LOAD1_NOABORT,
+	    BUILT_IN_ASAN_REPORT_LOAD2_NOABORT,
+	    BUILT_IN_ASAN_REPORT_LOAD4_NOABORT,
+	    BUILT_IN_ASAN_REPORT_LOAD8_NOABORT,
+	    BUILT_IN_ASAN_REPORT_LOAD16_NOABORT,
+	    BUILT_IN_ASAN_REPORT_LOAD_N_NOABORT },
+	  { BUILT_IN_ASAN_REPORT_STORE1_NOABORT,
+	    BUILT_IN_ASAN_REPORT_STORE2_NOABORT,
+	    BUILT_IN_ASAN_REPORT_STORE4_NOABORT,
+	    BUILT_IN_ASAN_REPORT_STORE8_NOABORT,
+	    BUILT_IN_ASAN_REPORT_STORE16_NOABORT,
+	    BUILT_IN_ASAN_REPORT_STORE_N_NOABORT } } };
   if (size_in_bytes == -1)
     {
       *nargs = 2;
-      return builtin_decl_implicit (report[is_store][5]);
+      return builtin_decl_implicit (report[recover_p][is_store][5]);
     }
   *nargs = 1;
-  return builtin_decl_implicit (report[is_store][exact_log2 (size_in_bytes)]);
+  int size_log2 = exact_log2 (size_in_bytes);
+  return builtin_decl_implicit (report[recover_p][is_store][size_log2]);
 }
 
 /* Construct a function tree for __asan_{load,store}{1,2,4,8,16,_n}.
    IS_STORE is either 1 (for a store) or 0 (for a load).  */
 
 static tree
-check_func (bool is_store, int size_in_bytes, int *nargs)
-{
-  static enum built_in_function check[2][6]
-    = { { BUILT_IN_ASAN_LOAD1, BUILT_IN_ASAN_LOAD2,
-      BUILT_IN_ASAN_LOAD4, BUILT_IN_ASAN_LOAD8,
-      BUILT_IN_ASAN_LOAD16, BUILT_IN_ASAN_LOADN },
-	{ BUILT_IN_ASAN_STORE1, BUILT_IN_ASAN_STORE2,
-      BUILT_IN_ASAN_STORE4, BUILT_IN_ASAN_STORE8,
-      BUILT_IN_ASAN_STORE16, BUILT_IN_ASAN_STOREN } };
+check_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
+	    int *nargs)
+{
+  static enum built_in_function check[2][2][6]
+    = { { { BUILT_IN_ASAN_LOAD1, BUILT_IN_ASAN_LOAD2,
+	    BUILT_IN_ASAN_LOAD4, BUILT_IN_ASAN_LOAD8,
+	    BUILT_IN_ASAN_LOAD16, BUILT_IN_ASAN_LOADN },
+	  { BUILT_IN_ASAN_STORE1, BUILT_IN_ASAN_STORE2,
+	    BUILT_IN_ASAN_STORE4, BUILT_IN_ASAN_STORE8,
+	    BUILT_IN_ASAN_STORE16, BUILT_IN_ASAN_STOREN } },
+	{ { BUILT_IN_ASAN_LOAD1_NOABORT,
+	    BUILT_IN_ASAN_LOAD2_NOABORT,
+	    BUILT_IN_ASAN_LOAD4_NOABORT,
+	    BUILT_IN_ASAN_LOAD8_NOABORT,
+	    BUILT_IN_ASAN_LOAD16_NOABORT,
+	    BUILT_IN_ASAN_LOADN_NOABORT },
+	  { BUILT_IN_ASAN_STORE1_NOABORT,
+	    BUILT_IN_ASAN_STORE2_NOABORT,
+	    BUILT_IN_ASAN_STORE4_NOABORT,
+	    BUILT_IN_ASAN_STORE8_NOABORT,
+	    BUILT_IN_ASAN_STORE16_NOABORT,
+	    BUILT_IN_ASAN_STOREN_NOABORT } } };
   if (size_in_bytes == -1)
     {
       *nargs = 2;
-      return builtin_decl_implicit (check[is_store][5]);
+      return builtin_decl_implicit (check[recover_p][is_store][5]);
     }
   *nargs = 1;
-  return builtin_decl_implicit (check[is_store][exact_log2 (size_in_bytes)]);
+  int size_log2 = exact_log2 (size_in_bytes);
+  return builtin_decl_implicit (check[recover_p][is_store][size_log2]);
 }
 
 /* Split the current basic block and create a condition statement
@@ -2502,6 +2530,9 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
   gimple g = gsi_stmt (*iter);
   location_t loc = gimple_location (g);
 
+  bool recover_p
+    = (flag_sanitize & flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) != 0;
+
   HOST_WIDE_INT flags = tree_to_shwi (gimple_call_arg (g, 0));
   gcc_assert (flags < ASAN_CHECK_LAST);
   bool is_scalar_access = (flags & ASAN_CHECK_SCALAR_ACCESS) != 0;
@@ -2530,7 +2561,7 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
       tree base_addr = gimple_assign_lhs (g);
 
       int nargs;
-      tree fun = check_func (is_store, size_in_bytes, &nargs);
+      tree fun = check_func (is_store, recover_p, size_in_bytes, &nargs);
       if (nargs == 1)
 	g = gimple_build_call (fun, 1, base_addr);
       else
@@ -2591,7 +2622,7 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
   basic_block then_bb, else_bb;
   gsi = create_cond_insert_point (&gsi, /*before_p*/false,
 				  /*then_more_likely_p=*/false,
-				  /*create_then_fallthru_edge=*/false,
+				  /*create_then_fallthru_edge*/recover_p,
 				  &then_bb,
 				  &else_bb);
 
@@ -2700,7 +2731,7 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
   /* Generate call to the run-time library (e.g. __asan_report_load8).  */
   gsi = gsi_start_bb (then_bb);
   int nargs;
-  tree fun = report_error_func (is_store, size_in_bytes, &nargs);
+  tree fun = report_error_func (is_store, recover_p, size_in_bytes, &nargs);
   g = gimple_build_call (fun, nargs, base_addr, len);
   gimple_set_location (g, loc);
   gsi_insert_after (&gsi, g, GSI_NEW_STMT);
diff --git a/gcc/common.opt b/gcc/common.opt
index da5250b..e385615 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -213,7 +213,7 @@ unsigned int flag_sanitize
 
 ; What sanitizers should recover from errors
 Variable
-unsigned int flag_sanitize_recover = SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT
+unsigned int flag_sanitize_recover = SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT | SANITIZE_KERNEL_ADDRESS
 
 ; Flag whether a prefix has been added to dump_base_name
 Variable
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index c9ca404..6a425c0 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -5657,13 +5657,13 @@ and program will exit after that with non-zero exit code.
 
 Currently this feature only works for @option{-fsanitize=undefined} (and its suboptions
 except for @option{-fsanitize=unreachable} and @option{-fsanitize=return}),
-@option{-fsanitize=float-cast-overflow} and @option{-fsanitize=float-divide-by-zero}.
-For these sanitizers error recovery is turned on by default.
+@option{-fsanitize=float-cast-overflow}, @option{-fsanitize=float-divide-by-zero} and
+@option{-fsanitize=kernel-address}.  For these sanitizers error recovery is turned on by default.
 
 Syntax without explicit @var{opts} parameter is deprecated.  It is equivalent to
-@option{-fsanitize-recover=undefined,float-cast-overflow,float-divide-by-zero}.
+@option{-fsanitize-recover=undefined,float-cast-overflow,float-divide-by-zero,kernel-address}.
 Similarly @option{-fno-sanitize-recover} is equivalent to
-@option{-fno-sanitize-recover=undefined,float-cast-overflow,float-divide-by-zero}.
+@option{-fno-sanitize-recover=undefined,float-cast-overflow,float-divide-by-zero,kernel-address}.
 
 @item -fsanitize-undefined-trap-on-error
 @opindex fsanitize-undefined-trap-on-error
diff --git a/gcc/opts.c b/gcc/opts.c
index 25f5235..7157865 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -877,7 +877,7 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
   if (opts->x_dwarf_split_debug_info)
     opts->x_debug_generate_pub_sections = 2;
 
-  /* Userspace and kernel ASan conflict with each other and with TSan.  */
+  /* Userspace and kernel ASan conflict with each other.  */
 
   if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS)
       && (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS))
@@ -885,6 +885,8 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
 	      "-fsanitize=address is incompatible with "
 	      "-fsanitize=kernel-address");
 
+  /* And with TSan.  */
+
   if ((opts->x_flag_sanitize & SANITIZE_ADDRESS)
       && (opts->x_flag_sanitize & SANITIZE_THREAD))
     error_at (loc,
diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def
index 722311a..cddc5ea 100644
--- a/gcc/sanitizer.def
+++ b/gcc/sanitizer.def
@@ -57,6 +57,44 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE16, "__asan_report_store16",
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE_N, "__asan_report_store_n",
 		      BT_FN_VOID_PTR_PTRMODE,
 		      ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD1_NOABORT,
+		      "__asan_report_load1_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD2_NOABORT,
+		      "__asan_report_load2_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD4_NOABORT,
+		      "__asan_report_load4_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD8_NOABORT,
+		      "__asan_report_load8_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD16_NOABORT,
+		      "__asan_report_load16_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD_N_NOABORT,
+		      "__asan_report_load_n_noabort",
+		      BT_FN_VOID_PTR_PTRMODE,
+		      ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE1_NOABORT,
+		      "__asan_report_store1_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE2_NOABORT,
+		      "__asan_report_store2_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE4_NOABORT,
+		      "__asan_report_store4_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE8_NOABORT,
+		      "__asan_report_store8_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE16_NOABORT,
+		      "__asan_report_store16_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE_N_NOABORT,
+		      "__asan_report_store_n_noabort",
+		      BT_FN_VOID_PTR_PTRMODE,
+		      ATTR_TMPURE_NOTHROW_LEAF_LIST)
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD1, "__asan_load1",
 		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD2, "__asan_load2",
@@ -81,6 +119,30 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE16, "__asan_store16",
 		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STOREN, "__asan_storeN",
 		      BT_FN_VOID_PTR_PTRMODE, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD1_NOABORT, "__asan_load1_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD2_NOABORT, "__asan_load2_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD4_NOABORT, "__asan_load4_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD8_NOABORT, "__asan_load8_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD16_NOABORT, "__asan_load16_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOADN_NOABORT, "__asan_loadN_noabort",
+		      BT_FN_VOID_PTR_PTRMODE, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE1_NOABORT, "__asan_store1_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE2_NOABORT, "__asan_store2_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE4_NOABORT, "__asan_store4_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE8_NOABORT, "__asan_store8_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE16_NOABORT, "__asan_store16_noabort",
+		      BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STOREN_NOABORT, "__asan_storeN_noabort",
+		      BT_FN_VOID_PTR_PTRMODE, ATTR_TMPURE_NOTHROW_LEAF_LIST)
 DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REGISTER_GLOBALS,
 		      "__asan_register_globals",
 		      BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
diff --git a/gcc/testsuite/c-c++-common/asan/kasan-recover-1.c b/gcc/testsuite/c-c++-common/asan/kasan-recover-1.c
new file mode 100644
index 0000000..6e04e5d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/kasan-recover-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-sanitize=address -fsanitize=kernel-address --param asan-instrumentation-with-call-threshold=100 -save-temps" } */
+
+void
+foo (int *p)
+{
+  *p = 0;
+}
+
+/* { dg-final { scan-assembler "__asan_report_store4_noabort" } } */
+/* { dg-final { cleanup-saved-temps } } */
+
diff --git a/gcc/testsuite/c-c++-common/asan/kasan-recover-2.c b/gcc/testsuite/c-c++-common/asan/kasan-recover-2.c
new file mode 100644
index 0000000..1091a07
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/kasan-recover-2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-sanitize=address -fsanitize=kernel-address -save-temps" } */
+
+void
+foo (int *p)
+{
+  *p = 0;
+}
+
+/* { dg-final { scan-assembler "__asan_store4_noabort" } } */
+/* { dg-final { cleanup-saved-temps } } */
+
-- 
1.7.9.5


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

* Re: [PATCH v5] Enable -fsanitize-recover for KASan
  2014-10-28  8:46       ` [PATCH v5] " Yury Gribov
@ 2014-10-28  9:31         ` Jakub Jelinek
  2014-10-28 10:15           ` Yury Gribov
  0 siblings, 1 reply; 73+ messages in thread
From: Jakub Jelinek @ 2014-10-28  9:31 UTC (permalink / raw)
  To: Yury Gribov
  Cc: GCC Patches, Konstantin Serebryany, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On Tue, Oct 28, 2014 at 11:46:31AM +0300, Yury Gribov wrote:
> 2014-10-23  Yury Gribov  <y.gribov@samsung.com>
> 
> gcc/
> 	* asan.c (report_error_func): Add noabort path.
> 	(check_func): Ditto.  Formatting.
> 	(asan_expand_check_ifn): Handle noabort path.
> 	* common.opt (flag_sanitize_recover): Add SANITIZE_KERNEL_ADDRESS
> 	to default value.
> 	* doc/invoke.texi (-fsanitize-recover=): Mention KASan.
> 	* opts.c (finish_options): Reword comment.
> 	* sanitizer.def: Add noabort ASan builtins.
> 
> gcc/testsuite/
> 	* c-c++-common/asan/kasan-recover-1.c: New test.
> 	* c-c++-common/asan/kasan-recover-2.c: New test.

Are the __asan_{load,store,report}*_noabort entrypoints going to be added
into libasan too?

> --- a/gcc/common.opt
> +++ b/gcc/common.opt
> @@ -213,7 +213,7 @@ unsigned int flag_sanitize
>  
>  ; What sanitizers should recover from errors
>  Variable
> -unsigned int flag_sanitize_recover = SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT
> +unsigned int flag_sanitize_recover = SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT | SANITIZE_KERNEL_ADDRESS

I wonder whether we can break lines here, if e.g. \ at the end of line would
work.  If not, it is ok this way.

> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/asan/kasan-recover-1.c
> @@ -0,0 +1,12 @@
> +/* { dg-do compile } */
> +/* { dg-options "-fno-sanitize=address -fsanitize=kernel-address --param asan-instrumentation-with-call-threshold=100 -save-temps" } */

Why -save-temps and cleanup-saved-temps?  Do you for some reason want to
avoid integrated preprocessing?  I mean, this is a dg-do compile test,
so for scanning assembly you don't really need -save-temps.

> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/asan/kasan-recover-2.c
> @@ -0,0 +1,12 @@
> +/* { dg-do compile } */
> +/* { dg-options "-fno-sanitize=address -fsanitize=kernel-address -save-temps" } */

Likewise.

> +
> +void
> +foo (int *p)
> +{
> +  *p = 0;
> +}
> +
> +/* { dg-final { scan-assembler "__asan_store4_noabort" } } */
> +/* { dg-final { cleanup-saved-temps } } */
> +

Otherwise LGTM.

	Jakub

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

* Re: [PATCH v5] Enable -fsanitize-recover for KASan
  2014-10-28  9:31         ` Jakub Jelinek
@ 2014-10-28 10:15           ` Yury Gribov
  0 siblings, 0 replies; 73+ messages in thread
From: Yury Gribov @ 2014-10-28 10:15 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: GCC Patches, Konstantin Serebryany, Dmitry Vyukov,
	Andrey Ryabinin, Konstantin Khlebnikov

On 10/28/2014 12:26 PM, Jakub Jelinek wrote:
> On Tue, Oct 28, 2014 at 11:46:31AM +0300, Yury Gribov wrote:
>> 2014-10-23  Yury Gribov  <y.gribov@samsung.com>
>>
>> gcc/
>> 	* asan.c (report_error_func): Add noabort path.
>> 	(check_func): Ditto.  Formatting.
>> 	(asan_expand_check_ifn): Handle noabort path.
>> 	* common.opt (flag_sanitize_recover): Add SANITIZE_KERNEL_ADDRESS
>> 	to default value.
>> 	* doc/invoke.texi (-fsanitize-recover=): Mention KASan.
>> 	* opts.c (finish_options): Reword comment.
>> 	* sanitizer.def: Add noabort ASan builtins.
>>
>> gcc/testsuite/
>> 	* c-c++-common/asan/kasan-recover-1.c: New test.
>> 	* c-c++-common/asan/kasan-recover-2.c: New test.
>
> Are the __asan_{load,store,report}*_noabort entrypoints going to be added
> into libasan too?

Probably not, ASan team has declined recovery mode in userspace ASan 
since the beginning of days.  It's even mentioned in their FAQ at 
https://code.google.com/p/address-sanitizer/wiki/AddressSanitizer

-Y

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

* Re: [PATCH] -fsanitize-recover=list
  2014-10-17 16:16                               ` [PATCH] -fsanitize-recover=list Jakub Jelinek
  2014-10-20 10:44                                 ` Yury Gribov
  2014-10-22  8:05                                 ` Yury Gribov
@ 2014-11-18  2:50                                 ` Alexey Samsonov
  2014-11-18  7:27                                   ` Jakub Jelinek
  2014-11-18  7:39                                   ` [PATCH] -fsanitize-recover=list Yury Gribov
  2 siblings, 2 replies; 73+ messages in thread
From: Alexey Samsonov @ 2014-11-18  2:50 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Yury Gribov, Marek Polacek, GCC Patches, Dmitry Vyukov,
	Konstantin Serebryany

Hi Jakub,

I've just prepared a patch implementing -fsanitize-recover=<list> in
Clang (http://reviews.llvm.org/D6302), writing here to make sure we're
on
the same page w.r.t. flag semantics:

* -fsanitize-recover: Enable recovery for all checks enabled by
-fsanitize= which support it.
* -fno-sanitize-recover: Disable recovery for all checks.
* -fsanitize-recover=<list>: Enable recovery for all selected checks
or group of checks. It is forbidden to list unrecoverable sanitizers
here (e.g., "-fsanitize-recover=address" will produce an error).
* -fno-sanitize-recover=<list>: Disable recovery for selected checks
or group of checks.

We maintain the set of "recoverable" sanitizers. Initially it contains
all UBSan checks (except for "unreachable" and "return"). We then
update this set as we
parse flags listed above, from left to right. "-fsanitize-recover" are
"-fsanitize" flags are independent. If a sanitizer is listed as
recoverable, but is not enabled via -fsanitize=,
we just ignore corresponding -fsanitize-recover flag.

Examples:
  * $(CC) -fsanitize=undefined,thread -fsanitize-recover=thread  //
Use UBSan and TSan, both of them are recoverable (Note: in reality,
"-fsanitize-recover=thread" is not implemented in Clang, this example
just illustrates intended semantics).
  * $(CC) -fsanitize=undefined -fno-sanitize-recover
-fsanitize-recover=signed-integer-overflow // Recover only from
signed-integer-overflow check, all other UBSan checks are fatal.

Sounds good?

As for the generated code, I'm at the stage where I can implement the
following: if a single UBSan hander is used to report multiple error
kinds (__ubsan_handle_type_mismatch is used for
-fsanitize=null,alignment,object-size), and these kinds have different
recoverability, then we emit two handler calls like this:

$ (CC) -fsanitize=undefined -fno-sanitize-recover=alignment   //
"null" and "object-size" are recoverable by default.

bool IsNonNull = ...;
bool IsAligned = ...;
bool HasCorrectSize = ...;
bool OK = IsAligned && IsNonNull && HasCorrectSize;
if (UNLIKELY(!OK)) {
  // setup arguments for UBSan handler call
  if (!IsAligned) {
    __ubsan_handle_type_mismatch_abort(<args>);
    __builtin_unreachable();
  }
  __ubsan_handle_type_mismatch(<args>);
}
// user code



On Fri, Oct 17, 2014 at 9:13 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Mon, Oct 13, 2014 at 02:47:07PM +0400, Yury Gribov wrote:
>> On 09/30/2014 09:39 PM, Jakub Jelinek wrote:
>> >LGTM, will hack it up soon in GCC then.
>>
>> Do you plan to work on this in near future?
>
> Here is only very lightly tested patch, didn't get to updating
> documentation though, plus there is no testsuite coverage for it.
> Supposedly, most of the tests that use -fno-sanitize-recover
> or -fsanitize-recover in dg-options should be changed to use
> -fno-sanitize-recover= or -fsanitize-recover (in some cases for
> the kind that is enabled with -fsanitize= only, in other cases
> perhaps for something covering that and some other options),
> plus perhaps some new smallish tests that test that if you e.g.
> do -fsanitize=undefined -fno-sanitize-recover=divide , that
> you can recover from several say out of bound shifts, but that
> the first divide will terminate, etc.
> Yuri or Marek, would you have spare time for that?
>
> There is one not so nice thing, if one requests e.g.
> -fsanitize=null,alignment -fno-sanitize-recover=null -fsanitize-recover=alignment
> (or vice versa), as a single call is used for both alignment and null
> checks, if both are tested, it needs to pick something, the patch
> right now picks recovery rather than abort if the two bits
> in flag_sanitize_recover disagree.  In theory, we could in that case
> just use two separate calls rather than sharing one call, doing the
> check and conditional branch to *_abort () first and if that wasn't true,
> do the other check.
>
> Also, the patch enables -fsanitize-recover by default for
> -fsanitize-recover=undefined,float-divide-by-zero,float-cast-overflow
> but not for kernel-address and doesn't check
> (flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) in asan.c, you'd
> need to add that afterwards.
>
> 2014-10-17  Jakub Jelinek  <jakub@redhat.com>
>
>         * common.opt (flag_sanitize_recover): New variable.
>         (fsanitize-recover): Remove Var/Init, deprecate.
>         (fsanitize-recover=): New option.
>         * opts.c (finish_options): Use opts->x_flag_sanitize
>         instead of flag_sanitize.  Formatting.
>         (common_handle_option): Handle OPT_fsanitize_recover_
>         and OPT_fsanitize_recover.  Use opts->x_flag_sanitize
>         instead of flag_sanitize.
>         * asan.c (pass_sanopt::execute): Fix up formatting.
>         * ubsan.c (ubsan_expand_bounds_ifn, ubsan_expand_null_ifn,
>         ubsan_expand_objsize_ifn, ubsan_build_overflow_builtin,
>         instrument_bool_enum_load, ubsan_instrument_float_cast,
>         instrument_nonnull_arg, instrument_nonnull_return): Check
>         bits in flag_sanitize_recover bitmask instead of
>         flag_sanitize_recover as bool flag.
> c-family/
>         * c-ubsan.c (ubsan_instrument_division, ubsan_instrument_shift,
>         ubsan_instrument_vla): Check bits in flag_sanitize_recover bitmask
>         instead of flag_sanitize_recover as bool flag.
>
> --- gcc/common.opt.jj   2014-10-17 08:47:21.000000000 +0200
> +++ gcc/common.opt      2014-10-17 17:45:41.816337133 +0200
> @@ -211,6 +211,10 @@ bool flag_opts_finished
>  Variable
>  unsigned int flag_sanitize
>
> +; What sanitizers should recover from errors
> +Variable
> +unsigned int flag_sanitize_recover = SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT
> +
>  ; Flag whether a prefix has been added to dump_base_name
>  Variable
>  bool dump_base_name_prefixed = false
> @@ -879,10 +883,14 @@ fsanitize=
>  Common Driver Report Joined
>  Select what to sanitize
>
> -fsanitize-recover
> -Common Report Var(flag_sanitize_recover) Init(1)
> +fsanitize-recover=
> +Common Report Joined
>  After diagnosing undefined behavior attempt to continue execution
>
> +fsanitize-recover
> +Common Report
> +This switch is deprecated; use -fsanitize-recover= instead
> +
>  fsanitize-undefined-trap-on-error
>  Common Report Var(flag_sanitize_undefined_trap_on_error) Init(0)
>  Use trap instead of a library function for undefined behavior sanitization
> --- gcc/opts.c.jj       2014-10-17 12:01:19.000000000 +0200
> +++ gcc/opts.c  2014-10-17 17:17:38.620375035 +0200
> @@ -879,17 +879,17 @@ finish_options (struct gcc_options *opts
>
>    /* Userspace and kernel ASan conflict with each other and with TSan.  */
>
> -  if ((flag_sanitize & SANITIZE_USER_ADDRESS)
> -      && (flag_sanitize & SANITIZE_KERNEL_ADDRESS))
> +  if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS)
> +      && (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS))
>      error_at (loc,
> -              "-fsanitize=address is incompatible with "
> -              "-fsanitize=kernel-address");
> +             "-fsanitize=address is incompatible with "
> +             "-fsanitize=kernel-address");
>
> -  if ((flag_sanitize & SANITIZE_ADDRESS)
> -      && (flag_sanitize & SANITIZE_THREAD))
> +  if ((opts->x_flag_sanitize & SANITIZE_ADDRESS)
> +      && (opts->x_flag_sanitize & SANITIZE_THREAD))
>      error_at (loc,
> -              "-fsanitize=address and -fsanitize=kernel-address "
> -              "are incompatible with -fsanitize=thread");
> +             "-fsanitize=address and -fsanitize=kernel-address "
> +             "are incompatible with -fsanitize=thread");
>  }
>
>  #define LEFT_COLUMN    27
> @@ -1473,6 +1473,7 @@ common_handle_option (struct gcc_options
>        break;
>
>      case OPT_fsanitize_:
> +    case OPT_fsanitize_recover_:
>        {
>         const char *p = arg;
>         while (*p != 0)
> @@ -1539,33 +1540,48 @@ common_handle_option (struct gcc_options
>                   && memcmp (p, spec[i].name, len) == 0)
>                 {
>                   /* Handle both -fsanitize and -fno-sanitize cases.  */
> -                 if (value)
> -                   flag_sanitize |= spec[i].flag;
> +                 if (code == OPT_fsanitize_)
> +                   {
> +                     if (value)
> +                       opts->x_flag_sanitize |= spec[i].flag;
> +                     else
> +                       opts->x_flag_sanitize &= ~spec[i].flag;
> +                   }
>                   else
> -                   flag_sanitize &= ~spec[i].flag;
> +                   {
> +                     if (value)
> +                       opts->x_flag_sanitize_recover |= spec[i].flag;
> +                     else
> +                       opts->x_flag_sanitize_recover &= ~spec[i].flag;
> +                   }
>                   found = true;
>                   break;
>                 }
>
>             if (! found)
>               error_at (loc,
> -                       "unrecognized argument to -fsanitize= option: %q.*s",
> -                       (int) len, p);
> +                       code == OPT_fsanitize_
> +                       ? "unrecognized argument to -fsanitize= option: %q.*s"
> +                       : "unrecognized argument to -fsanitize-recover= "
> +                         "option: %q.*s", (int) len, p);
>
>             if (comma == NULL)
>               break;
>             p = comma + 1;
>           }
>
> +       if (code != OPT_fsanitize_)
> +         break;
> +
>         /* When instrumenting the pointers, we don't want to remove
>            the null pointer checks.  */
> -       if (flag_sanitize & (SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
> -                            | SANITIZE_RETURNS_NONNULL_ATTRIBUTE))
> +       if (opts->x_flag_sanitize & (SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
> +                                    | SANITIZE_RETURNS_NONNULL_ATTRIBUTE))
>           opts->x_flag_delete_null_pointer_checks = 0;
>
>         /* Kernel ASan implies normal ASan but does not yet support
>            all features.  */
> -       if (flag_sanitize & SANITIZE_KERNEL_ADDRESS)
> +       if (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS)
>           {
>             maybe_set_param_value (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD, 0,
>                                    opts->x_param_values,
> @@ -1584,6 +1600,15 @@ common_handle_option (struct gcc_options
>         break;
>        }
>
> +    case OPT_fsanitize_recover:
> +      if (value)
> +       opts->x_flag_sanitize_recover
> +         |= SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT;
> +      else
> +       opts->x_flag_sanitize_recover
> +         &= ~(SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT);
> +      break;
> +
>      case OPT_O:
>      case OPT_Os:
>      case OPT_Ofast:
> --- gcc/asan.c.jj       2014-10-13 17:54:34.000000000 +0200
> +++ gcc/asan.c  2014-10-17 17:46:20.952620580 +0200
> @@ -2884,10 +2884,8 @@ pass_sanopt::execute (function *fun)
>                   no_next = ubsan_expand_objsize_ifn (&gsi);
>                   break;
>                 case IFN_ASAN_CHECK:
> -                 {
> -                   no_next = asan_expand_check_ifn (&gsi, use_calls);
> -                   break;
> -                 }
> +                 no_next = asan_expand_check_ifn (&gsi, use_calls);
> +                 break;
>                 default:
>                   break;
>                 }
> --- gcc/ubsan.c.jj      2014-10-10 19:42:22.000000000 +0200
> +++ gcc/ubsan.c 2014-10-17 17:05:57.609330882 +0200
> @@ -638,7 +638,7 @@ ubsan_expand_bounds_ifn (gimple_stmt_ite
>                              NULL_TREE, NULL_TREE);
>        data = build_fold_addr_expr_loc (loc, data);
>        enum built_in_function bcode
> -       = flag_sanitize_recover
> +       = (flag_sanitize_recover & SANITIZE_BOUNDS)
>           ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
>           : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
>        tree fn = builtin_decl_explicit (bcode);
> @@ -741,7 +741,8 @@ ubsan_expand_null_ifn (gimple_stmt_itera
>    else
>      {
>        enum built_in_function bcode
> -       = flag_sanitize_recover
> +       = (flag_sanitize_recover & ((check_align ? SANITIZE_ALIGNMENT : 0)
> +                                   | (check_null ? SANITIZE_NULL : 0)))
>           ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
>           : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
>        tree fn = builtin_decl_implicit (bcode);
> @@ -879,7 +880,7 @@ ubsan_expand_objsize_ifn (gimple_stmt_it
>                                  NULL_TREE);
>           data = build_fold_addr_expr_loc (loc, data);
>           enum built_in_function bcode
> -           = flag_sanitize_recover
> +           = (flag_sanitize_recover & SANITIZE_OBJECT_SIZE)
>               ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
>               : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
>           tree p = make_ssa_name (pointer_sized_int_node, NULL);
> @@ -964,22 +965,22 @@ ubsan_build_overflow_builtin (tree_code
>    switch (code)
>      {
>      case PLUS_EXPR:
> -      fn_code = flag_sanitize_recover
> +      fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
>                 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
>                 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
>        break;
>      case MINUS_EXPR:
> -      fn_code = flag_sanitize_recover
> +      fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
>                 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
>                 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
>        break;
>      case MULT_EXPR:
> -      fn_code = flag_sanitize_recover
> +      fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
>                 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
>                 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
>        break;
>      case NEGATE_EXPR:
> -      fn_code = flag_sanitize_recover
> +      fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
>                 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
>                 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
>        break;
> @@ -1156,7 +1157,8 @@ instrument_bool_enum_load (gimple_stmt_i
>                                      NULL_TREE);
>        data = build_fold_addr_expr_loc (loc, data);
>        enum built_in_function bcode
> -       = flag_sanitize_recover
> +       = (flag_sanitize_recover & (TREE_CODE (type) == BOOLEAN_TYPE
> +                                   ? SANITIZE_BOOL : SANITIZE_ENUM))
>           ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
>           : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
>        tree fn = builtin_decl_explicit (bcode);
> @@ -1278,7 +1280,7 @@ ubsan_instrument_float_cast (location_t
>                                      ubsan_type_descriptor (type), NULL_TREE,
>                                      NULL_TREE);
>        enum built_in_function bcode
> -       = flag_sanitize_recover
> +       = (flag_sanitize_recover & SANITIZE_FLOAT_CAST)
>           ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
>           : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
>        fn = builtin_decl_explicit (bcode);
> @@ -1344,7 +1346,7 @@ instrument_nonnull_arg (gimple_stmt_iter
>                                              NULL_TREE);
>               data = build_fold_addr_expr_loc (loc[0], data);
>               enum built_in_function bcode
> -               = flag_sanitize_recover
> +               = (flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
>                   ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
>                   : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
>               tree fn = builtin_decl_explicit (bcode);
> @@ -1396,7 +1398,7 @@ instrument_nonnull_return (gimple_stmt_i
>                                          2, loc, NULL_TREE, NULL_TREE);
>           data = build_fold_addr_expr_loc (loc[0], data);
>           enum built_in_function bcode
> -           = flag_sanitize_recover
> +           = (flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
>               ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
>               : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT;
>           tree fn = builtin_decl_explicit (bcode);
> --- gcc/c-family/c-ubsan.c.jj   2014-09-10 11:20:49.000000000 +0200
> +++ gcc/c-family/c-ubsan.c      2014-10-17 17:13:14.393241619 +0200
> @@ -104,7 +104,7 @@ ubsan_instrument_division (location_t lo
>                                      NULL_TREE);
>        data = build_fold_addr_expr_loc (loc, data);
>        enum built_in_function bcode
> -       = flag_sanitize_recover
> +       = (flag_sanitize_recover & SANITIZE_DIVIDE)
>           ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
>           : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT;
>        tt = builtin_decl_explicit (bcode);
> @@ -199,7 +199,7 @@ ubsan_instrument_shift (location_t loc,
>        data = build_fold_addr_expr_loc (loc, data);
>
>        enum built_in_function bcode
> -       = flag_sanitize_recover
> +       = (flag_sanitize_recover & SANITIZE_SHIFT)
>           ? BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS
>           : BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS_ABORT;
>        tt = builtin_decl_explicit (bcode);
> @@ -229,7 +229,7 @@ ubsan_instrument_vla (location_t loc, tr
>                                      NULL_TREE);
>        data = build_fold_addr_expr_loc (loc, data);
>        enum built_in_function bcode
> -       = flag_sanitize_recover
> +       = (flag_sanitize_recover & SANITIZE_VLA)
>           ? BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE
>           : BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE_ABORT;
>        tt = builtin_decl_explicit (bcode);
>
>
>         Jakub



-- 
Alexey Samsonov, Mountain View, CA

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

* Re: [PATCH] -fsanitize-recover=list
  2014-11-18  2:50                                 ` Alexey Samsonov
@ 2014-11-18  7:27                                   ` Jakub Jelinek
  2014-11-18  8:29                                     ` Alexey Samsonov
  2014-11-18  7:39                                   ` [PATCH] -fsanitize-recover=list Yury Gribov
  1 sibling, 1 reply; 73+ messages in thread
From: Jakub Jelinek @ 2014-11-18  7:27 UTC (permalink / raw)
  To: Alexey Samsonov
  Cc: Yury Gribov, Marek Polacek, GCC Patches, Dmitry Vyukov,
	Konstantin Serebryany

On Mon, Nov 17, 2014 at 06:40:00PM -0800, Alexey Samsonov wrote:
> I've just prepared a patch implementing -fsanitize-recover=<list> in
> Clang (http://reviews.llvm.org/D6302), writing here to make sure we're
> on
> the same page w.r.t. flag semantics:
> 
> * -fsanitize-recover: Enable recovery for all checks enabled by
> -fsanitize= which support it.
> * -fno-sanitize-recover: Disable recovery for all checks.

That is not what I think we've agreed on and what is implemented in GCC.
-fsanitize-recover only enables recovery of the undefined plus
undefined-like sanitizers, in particular it doesn't enable recover from
kernel-address, because -fsanitize-recover should be a deprecated option
and kernel-address never used it before.
So, in GCC -fsanitize-recover stands for
-fsanitize-recover=undefined,float-divide-by-zero,float-cast-overflow
and -fno-sanitize-recover stands for
-fno-sanitize-recover=undefined,float-divide-by-zero,float-cast-overflow

> * -fsanitize-recover=<list>: Enable recovery for all selected checks
> or group of checks. It is forbidden to list unrecoverable sanitizers
> here (e.g., "-fsanitize-recover=address" will produce an error).

We only error on
-fsanitize-recover=address
-fsanitize-recover=thread
-fsanitize-recover=leak
but not say on
-fsanitize-recover=unreachable
which is part of undefined; unreachable isn't recoverable silently.
Likewise -fsanitize-recover=return.  Otherwise one couldn't use
-fsanitize-recover=undefined which is useful.

> * -fno-sanitize-recover=<list>: Disable recovery for selected checks
> or group of checks.

	Jakub

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

* Re: [PATCH] -fsanitize-recover=list
  2014-11-18  2:50                                 ` Alexey Samsonov
  2014-11-18  7:27                                   ` Jakub Jelinek
@ 2014-11-18  7:39                                   ` Yury Gribov
  1 sibling, 0 replies; 73+ messages in thread
From: Yury Gribov @ 2014-11-18  7:39 UTC (permalink / raw)
  To: Alexey Samsonov, Jakub Jelinek
  Cc: Marek Polacek, GCC Patches, Dmitry Vyukov, Konstantin Serebryany

> As for the generated code, I'm at the stage where I can implement the
> following: if a single UBSan hander is used to report multiple error
> kinds (__ubsan_handle_type_mismatch is used for
> -fsanitize=null,alignment,object-size), and these kinds have different
> recoverability, then we emit two handler calls like this:

Nice, I think we do not yet have this in gcc.

-Y

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

* Re: [PATCH] -fsanitize-recover=list
  2014-11-18  7:27                                   ` Jakub Jelinek
@ 2014-11-18  8:29                                     ` Alexey Samsonov
  2014-11-18  8:34                                       ` Jakub Jelinek
  0 siblings, 1 reply; 73+ messages in thread
From: Alexey Samsonov @ 2014-11-18  8:29 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Yury Gribov, Marek Polacek, GCC Patches, Dmitry Vyukov,
	Konstantin Serebryany

On Mon, Nov 17, 2014 at 10:47 PM, Jakub Jelinek <jakub@redhat.com> wrote:
>
> On Mon, Nov 17, 2014 at 06:40:00PM -0800, Alexey Samsonov wrote:
> > I've just prepared a patch implementing -fsanitize-recover=<list> in
> > Clang (http://reviews.llvm.org/D6302), writing here to make sure we're
> > on
> > the same page w.r.t. flag semantics:
> >
> > * -fsanitize-recover: Enable recovery for all checks enabled by
> > -fsanitize= which support it.
> > * -fno-sanitize-recover: Disable recovery for all checks.
>
> That is not what I think we've agreed on and what is implemented in GCC.
> -fsanitize-recover only enables recovery of the undefined plus
> undefined-like sanitizers, in particular it doesn't enable recover from
> kernel-address, because -fsanitize-recover should be a deprecated option
> and kernel-address never used it before.

Hm, indeed, I messed it up. In the older thread we agree that plain
-f(no-)sanitize-recover
should be a deprecated synonym for the current meaning of these flags,
which only specify recoverability for UBSan-related checks :-/

Has GCC already shipped with existing implementation? I'm just curious
if it's convenient to have flags that would enable/disable recovery for all
sanitizers (analogous to -Werror flags which exist in a standalone form, but
may accept specific warnings, so that one can write
  "$(CC) foo.cc -Wno-error -Werror=sign-compare"

> So, in GCC -fsanitize-recover stands for
> -fsanitize-recover=undefined,float-divide-by-zero,float-cast-overflow
> and -fno-sanitize-recover stands for
> -fno-sanitize-recover=undefined,float-divide-by-zero,float-cast-overflow
>
> > * -fsanitize-recover=<list>: Enable recovery for all selected checks
> > or group of checks. It is forbidden to list unrecoverable sanitizers
> > here (e.g., "-fsanitize-recover=address" will produce an error).
>
> We only error on
> -fsanitize-recover=address
> -fsanitize-recover=thread
> -fsanitize-recover=leak

Right, it's a good idea to error on sanitizer kinds we don't have
recovery for. I will
add the errors for TSan/MSan/LSan etc.

> but not say on
> -fsanitize-recover=unreachable
> which is part of undefined; unreachable isn't recoverable silently.
> Likewise -fsanitize-recover=return.  Otherwise one couldn't use
> -fsanitize-recover=undefined which is useful.

Can't this be fixed by checking the actual values of -fsanitize-recover= flag
before expanding the sanitizer groups (i.e. turning "undefined" into
"null,unreachable,return,....")?

We should probably be able to distinguish between -fsanitize-recover=undefined,
and -fsanitize-recover=unreachable,<another checks from undefined>.
In the first case we can enable recovery
for all parts of "undefined" that support it. In the second, we can
produce an error as user
explicitly tried to enable recovery for sanitizer that doesn't support it.

This is only a diagnostic quality issue, though.

>
> > * -fno-sanitize-recover=<list>: Disable recovery for selected checks
> > or group of checks.
>
>         Jakub

-- 
Alexey Samsonov, Mountain View, CA

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

* Re: [PATCH] -fsanitize-recover=list
  2014-11-18  8:29                                     ` Alexey Samsonov
@ 2014-11-18  8:34                                       ` Jakub Jelinek
  2014-11-18 20:25                                         ` Alexey Samsonov
  0 siblings, 1 reply; 73+ messages in thread
From: Jakub Jelinek @ 2014-11-18  8:34 UTC (permalink / raw)
  To: Alexey Samsonov
  Cc: Yury Gribov, Marek Polacek, GCC Patches, Dmitry Vyukov,
	Konstantin Serebryany

On Mon, Nov 17, 2014 at 11:39:47PM -0800, Alexey Samsonov wrote:
> > That is not what I think we've agreed on and what is implemented in GCC.
> > -fsanitize-recover only enables recovery of the undefined plus
> > undefined-like sanitizers, in particular it doesn't enable recover from
> > kernel-address, because -fsanitize-recover should be a deprecated option
> > and kernel-address never used it before.
> 
> Hm, indeed, I messed it up. In the older thread we agree that plain
> -f(no-)sanitize-recover
> should be a deprecated synonym for the current meaning of these flags,
> which only specify recoverability for UBSan-related checks :-/
> 
> Has GCC already shipped with existing implementation? I'm just curious
> if it's convenient to have flags that would enable/disable recovery for all
> sanitizers (analogous to -Werror flags which exist in a standalone form, but
> may accept specific warnings, so that one can write
>   "$(CC) foo.cc -Wno-error -Werror=sign-compare"

Well, no sanitizer is on by default, so you can just use the same
list for -fno-sanitize-recover= or -fsanitize-recover= as for -fsanitize=
if you want.

> > So, in GCC -fsanitize-recover stands for
> > -fsanitize-recover=undefined,float-divide-by-zero,float-cast-overflow
> > and -fno-sanitize-recover stands for
> > -fno-sanitize-recover=undefined,float-divide-by-zero,float-cast-overflow
> >
> > > * -fsanitize-recover=<list>: Enable recovery for all selected checks
> > > or group of checks. It is forbidden to list unrecoverable sanitizers
> > > here (e.g., "-fsanitize-recover=address" will produce an error).
> >
> > We only error on
> > -fsanitize-recover=address
> > -fsanitize-recover=thread
> > -fsanitize-recover=leak
> 
> Right, it's a good idea to error on sanitizer kinds we don't have
> recovery for. I will
> add the errors for TSan/MSan/LSan etc.
> 
> > but not say on
> > -fsanitize-recover=unreachable
> > which is part of undefined; unreachable isn't recoverable silently.
> > Likewise -fsanitize-recover=return.  Otherwise one couldn't use
> > -fsanitize-recover=undefined which is useful.
> 
> Can't this be fixed by checking the actual values of -fsanitize-recover= flag
> before expanding the sanitizer groups (i.e. turning "undefined" into
> "null,unreachable,return,....")?
> 
> We should probably be able to distinguish between -fsanitize-recover=undefined,
> and -fsanitize-recover=unreachable,<another checks from undefined>.
> In the first case we can enable recovery
> for all parts of "undefined" that support it. In the second, we can
> produce an error as user
> explicitly tried to enable recovery for sanitizer that doesn't support it.

But in that case you would need to diagnose it already when parsing the
option, or add code that would remember what bits have been set from other
option sets.
In the former case, you'd diagnose even
-fsanitize-recover=unreachable -fno-sanitize-recover=undefined
even when in that case unreachable in the end is not recoverable.
We don't error out for
-fsanitize-recover=address -fno-sanitize-recover=address
because in the end address is not recovered.

	Jakub

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

* Re: [PATCH] -fsanitize-recover=list
  2014-11-18  8:34                                       ` Jakub Jelinek
@ 2014-11-18 20:25                                         ` Alexey Samsonov
  2014-12-19  2:47                                           ` Alexey Samsonov
  0 siblings, 1 reply; 73+ messages in thread
From: Alexey Samsonov @ 2014-11-18 20:25 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Yury Gribov, Marek Polacek, GCC Patches, Dmitry Vyukov,
	Konstantin Serebryany

On Mon, Nov 17, 2014 at 11:53 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Mon, Nov 17, 2014 at 11:39:47PM -0800, Alexey Samsonov wrote:
>> > That is not what I think we've agreed on and what is implemented in GCC.
>> > -fsanitize-recover only enables recovery of the undefined plus
>> > undefined-like sanitizers, in particular it doesn't enable recover from
>> > kernel-address, because -fsanitize-recover should be a deprecated option
>> > and kernel-address never used it before.
>>
>> Hm, indeed, I messed it up. In the older thread we agree that plain
>> -f(no-)sanitize-recover
>> should be a deprecated synonym for the current meaning of these flags,
>> which only specify recoverability for UBSan-related checks :-/
>>
>> Has GCC already shipped with existing implementation? I'm just curious
>> if it's convenient to have flags that would enable/disable recovery for all
>> sanitizers (analogous to -Werror flags which exist in a standalone form, but
>> may accept specific warnings, so that one can write
>>   "$(CC) foo.cc -Wno-error -Werror=sign-compare"
>
> Well, no sanitizer is on by default, so you can just use the same
> list for -fno-sanitize-recover= or -fsanitize-recover= as for -fsanitize=
> if you want.

Yeah, but it may look somewhat redundant. Also, re-using the exact
same list may lead to diagnostic messages (if you write
-fsanitize=unreachable,null -fsanitize-recover=unreachable,null).

>> > So, in GCC -fsanitize-recover stands for
>> > -fsanitize-recover=undefined,float-divide-by-zero,float-cast-overflow
>> > and -fno-sanitize-recover stands for
>> > -fno-sanitize-recover=undefined,float-divide-by-zero,float-cast-overflow
>> >
>> > > * -fsanitize-recover=<list>: Enable recovery for all selected checks
>> > > or group of checks. It is forbidden to list unrecoverable sanitizers
>> > > here (e.g., "-fsanitize-recover=address" will produce an error).
>> >
>> > We only error on
>> > -fsanitize-recover=address
>> > -fsanitize-recover=thread
>> > -fsanitize-recover=leak
>>
>> Right, it's a good idea to error on sanitizer kinds we don't have
>> recovery for. I will
>> add the errors for TSan/MSan/LSan etc.
>>
>> > but not say on
>> > -fsanitize-recover=unreachable
>> > which is part of undefined; unreachable isn't recoverable silently.
>> > Likewise -fsanitize-recover=return.  Otherwise one couldn't use
>> > -fsanitize-recover=undefined which is useful.
>>
>> Can't this be fixed by checking the actual values of -fsanitize-recover= flag
>> before expanding the sanitizer groups (i.e. turning "undefined" into
>> "null,unreachable,return,....")?
>>
>> We should probably be able to distinguish between -fsanitize-recover=undefined,
>> and -fsanitize-recover=unreachable,<another checks from undefined>.
>> In the first case we can enable recovery
>> for all parts of "undefined" that support it. In the second, we can
>> produce an error as user
>> explicitly tried to enable recovery for sanitizer that doesn't support it.
>
> But in that case you would need to diagnose it already when parsing the
> option, or add code that would remember what bits have been set from other
> option sets.
> In the former case, you'd diagnose even
> -fsanitize-recover=unreachable -fno-sanitize-recover=undefined
> even when in that case unreachable in the end is not recoverable.
> We don't error out for
> -fsanitize-recover=address -fno-sanitize-recover=address
> because in the end address is not recovered.

OK, that's a good question: should we diagnose -fsanitize-recover=address
if it was later disabled by -fno-sanitize-recover=address? There is an argument
for doing this: "-fsanitize-recover=address" is unsupported, so this
flag shouldn't
have been provided in the first place. It makes much more sense to
delete it rather
than override it. It couldn't be passed down from some global
project-wide configuration
(like CFLAGS), because it wouldn't work anywhere.

The only case where overriding might come in handy is re-using the same list for
-fsanitize= and -fsanitize-recover= flags that you mention:
# SANITIZERS is a list of sanitizers we want to enable.
CFLAGS = "${CFLAGS} -fsanitize=${SANITIZERS} -fsanitize-recover=${SANITIZERS}"
# Oops - we produce an error if ${SANITIZERS} contains "address".

However, even if we decide to *not* diagnose unrecoverable sanitizer
kinds disabled later
in the command line, we can still implement warnings for "unreachable" properly.
You can scan "-fsanitize-recover" flags from right to left and keep
track of all sanitizers that
"would be disabled". When you see "-fsanitize=unreachable" (with
literal "unreachable" as a value),
you diagnose the error only if "unreachable" wouldn't be disabled
later by some -fno-sanitize-recover flag.

FWIW, we implement this logic in Clang for regular -fsanitize= flags.
-- 
Alexey Samsonov, Mountain View, CA

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

* Re: [PATCH] -fsanitize-recover=list
  2014-11-18 20:25                                         ` Alexey Samsonov
@ 2014-12-19  2:47                                           ` Alexey Samsonov
  2014-12-19  8:14                                             ` Jakub Jelinek
  0 siblings, 1 reply; 73+ messages in thread
From: Alexey Samsonov @ 2014-12-19  2:47 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Yury Gribov, Marek Polacek, GCC Patches, Dmitry Vyukov,
	Konstantin Serebryany

Hi Jakub,

On Tue, Nov 18, 2014 at 11:36 AM, Alexey Samsonov <samsonov@google.com> wrote:
>
> On Mon, Nov 17, 2014 at 11:53 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> > On Mon, Nov 17, 2014 at 11:39:47PM -0800, Alexey Samsonov wrote:
> >> > That is not what I think we've agreed on and what is implemented in GCC.
> >> > -fsanitize-recover only enables recovery of the undefined plus
> >> > undefined-like sanitizers, in particular it doesn't enable recover from
> >> > kernel-address, because -fsanitize-recover should be a deprecated option
> >> > and kernel-address never used it before.
> >>
> >> Hm, indeed, I messed it up. In the older thread we agree that plain
> >> -f(no-)sanitize-recover
> >> should be a deprecated synonym for the current meaning of these flags,
> >> which only specify recoverability for UBSan-related checks :-/
> >>
> >> Has GCC already shipped with existing implementation? I'm just curious
> >> if it's convenient to have flags that would enable/disable recovery for all
> >> sanitizers (analogous to -Werror flags which exist in a standalone form, but
> >> may accept specific warnings, so that one can write
> >>   "$(CC) foo.cc -Wno-error -Werror=sign-compare"
> >
> > Well, no sanitizer is on by default, so you can just use the same
> > list for -fno-sanitize-recover= or -fsanitize-recover= as for -fsanitize=
> > if you want.
>
> Yeah, but it may look somewhat redundant. Also, re-using the exact
> same list may lead to diagnostic messages (if you write
> -fsanitize=unreachable,null -fsanitize-recover=unreachable,null).

Reviving this thread.

What do you think of the following idea:
1) we keep "-fsanitize-recover" and "-fno-sanitize-recover" as
deprecated synonyms
for "-f(no-)?sanitize=<ubsan-like checks>"
2) we introduce -fsanitize-recover=<list> and
-fno-sanitize-recover=<list>, where list may contain
specific sanitizers ("address") or group of sanitizers ("undefined").
3) we introduce group of sanitizers called "all", which is, well, "all
available sanitizers". It can *not* be
used in -fsanitize=all flag, but can be used to easily disable all
previously enabled sanitizers ("-fno-sanitize=all"),
or to enable/disable recovery for all enabled sanitizers
("-fsanitize-recover=all" / "-fno-sanitize-recover=all").

This would be a handy shortcut, and will save users from copying the
same list twice for
-fsanitize= and -fsanitize-recover= flags, and from potential
diagnostic problems I mention.

>
>
> >> > So, in GCC -fsanitize-recover stands for
> >> > -fsanitize-recover=undefined,float-divide-by-zero,float-cast-overflow
> >> > and -fno-sanitize-recover stands for
> >> > -fno-sanitize-recover=undefined,float-divide-by-zero,float-cast-overflow
> >> >
> >> > > * -fsanitize-recover=<list>: Enable recovery for all selected checks
> >> > > or group of checks. It is forbidden to list unrecoverable sanitizers
> >> > > here (e.g., "-fsanitize-recover=address" will produce an error).
> >> >
> >> > We only error on
> >> > -fsanitize-recover=address
> >> > -fsanitize-recover=thread
> >> > -fsanitize-recover=leak
> >>
> >> Right, it's a good idea to error on sanitizer kinds we don't have
> >> recovery for. I will
> >> add the errors for TSan/MSan/LSan etc.
> >>
> >> > but not say on
> >> > -fsanitize-recover=unreachable
> >> > which is part of undefined; unreachable isn't recoverable silently.
> >> > Likewise -fsanitize-recover=return.  Otherwise one couldn't use
> >> > -fsanitize-recover=undefined which is useful.
> >>
> >> Can't this be fixed by checking the actual values of -fsanitize-recover= flag
> >> before expanding the sanitizer groups (i.e. turning "undefined" into
> >> "null,unreachable,return,....")?
> >>
> >> We should probably be able to distinguish between -fsanitize-recover=undefined,
> >> and -fsanitize-recover=unreachable,<another checks from undefined>.
> >> In the first case we can enable recovery
> >> for all parts of "undefined" that support it. In the second, we can
> >> produce an error as user
> >> explicitly tried to enable recovery for sanitizer that doesn't support it.
> >
> > But in that case you would need to diagnose it already when parsing the
> > option, or add code that would remember what bits have been set from other
> > option sets.
> > In the former case, you'd diagnose even
> > -fsanitize-recover=unreachable -fno-sanitize-recover=undefined
> > even when in that case unreachable in the end is not recoverable.
> > We don't error out for
> > -fsanitize-recover=address -fno-sanitize-recover=address
> > because in the end address is not recovered.
>
> OK, that's a good question: should we diagnose -fsanitize-recover=address
> if it was later disabled by -fno-sanitize-recover=address? There is an argument
> for doing this: "-fsanitize-recover=address" is unsupported, so this
> flag shouldn't
> have been provided in the first place. It makes much more sense to
> delete it rather
> than override it. It couldn't be passed down from some global
> project-wide configuration
> (like CFLAGS), because it wouldn't work anywhere.
>
> The only case where overriding might come in handy is re-using the same list for
> -fsanitize= and -fsanitize-recover= flags that you mention:
> # SANITIZERS is a list of sanitizers we want to enable.
> CFLAGS = "${CFLAGS} -fsanitize=${SANITIZERS} -fsanitize-recover=${SANITIZERS}"
> # Oops - we produce an error if ${SANITIZERS} contains "address".
>
> However, even if we decide to *not* diagnose unrecoverable sanitizer
> kinds disabled later
> in the command line, we can still implement warnings for "unreachable" properly.
> You can scan "-fsanitize-recover" flags from right to left and keep
> track of all sanitizers that
> "would be disabled". When you see "-fsanitize=unreachable" (with
> literal "unreachable" as a value),
> you diagnose the error only if "unreachable" wouldn't be disabled
> later by some -fno-sanitize-recover flag.
>
> FWIW, we implement this logic in Clang for regular -fsanitize= flags.
> --
> Alexey Samsonov, Mountain View, CA



-- 
Alexey Samsonov, Mountain View, CA

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

* Re: [PATCH] -fsanitize-recover=list
  2014-12-19  2:47                                           ` Alexey Samsonov
@ 2014-12-19  8:14                                             ` Jakub Jelinek
       [not found]                                               ` <CAGSYnCNLoU0p3FGDwb6mMAAOWFz2Te1m7wmWD94PhcADsQs9rQ@mail.gmail.com>
  0 siblings, 1 reply; 73+ messages in thread
From: Jakub Jelinek @ 2014-12-19  8:14 UTC (permalink / raw)
  To: Alexey Samsonov
  Cc: Yury Gribov, Marek Polacek, GCC Patches, Dmitry Vyukov,
	Konstantin Serebryany

On Thu, Dec 18, 2014 at 05:34:12PM -0800, Alexey Samsonov wrote:
> Reviving this thread.
> 
> What do you think of the following idea:
> 1) we keep "-fsanitize-recover" and "-fno-sanitize-recover" as
> deprecated synonyms
> for "-f(no-)?sanitize=<ubsan-like checks>"
> 2) we introduce -fsanitize-recover=<list> and
> -fno-sanitize-recover=<list>, where list may contain
> specific sanitizers ("address") or group of sanitizers ("undefined").
> 3) we introduce group of sanitizers called "all", which is, well, "all
> available sanitizers". It can *not* be
> used in -fsanitize=all flag, but can be used to easily disable all
> previously enabled sanitizers ("-fno-sanitize=all"),
> or to enable/disable recovery for all enabled sanitizers
> ("-fsanitize-recover=all" / "-fno-sanitize-recover=all").

So in esence a new group (like undefined) that is forbidden for -fsanitize=
option, but allowed for all the others?  Sounds fine to me.
Can one still mix it with others (of course, it doesn't make much sense,
but would mean fewer exceptions in the option parser and thus more easily
understandable), like
-fno-sanitize=enum,all,bool
or do you prefer to only allow it as the sole argument of those options?

	Jakub

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

* [PATCH] -f{no-sanitize,{,no-}sanitize-recover}=all support
       [not found]                                               ` <CAGSYnCNLoU0p3FGDwb6mMAAOWFz2Te1m7wmWD94PhcADsQs9rQ@mail.gmail.com>
@ 2015-01-05 17:40                                                 ` Jakub Jelinek
  2015-01-05 20:32                                                   ` Jeff Law
  0 siblings, 1 reply; 73+ messages in thread
From: Jakub Jelinek @ 2015-01-05 17:40 UTC (permalink / raw)
  To: Richard Biener, Dodji Seketeli
  Cc: Alexey Samsonov, Yury Gribov, Marek Polacek, GCC Patches,
	Dmitry Vyukov, Konstantin Serebryany

On Tue, Dec 23, 2014 at 04:47:06PM -0800, Alexey Samsonov wrote:
> Right, -fsanitize=all produces an error, while -fsanitize-recover=all
> enables recovery for all
> sanitizers, -fno-sanitize-recover=all disables recovery for everything.

Ok, here is a GCC patch for that.
-fno-sanitize=all is supported as a way to turn off all the sanitizers,
-f{,no-}sanitize-recover=all is supported too, and one can mix all
with other sanitizer names.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2015-01-05  Jakub Jelinek  <jakub@redhat.com>

	* opts.c (common_handle_option): Add support for
	-fno-sanitize=all and -f{,no-}sanitize-recover=all.

	* c-c++-common/asan/sanitize-all-1.c: New test.
	* c-c++-common/ubsan/sanitize-all-1.c: New test.
	* c-c++-common/ubsan/sanitize-all-2.c: New test.
	* c-c++-common/ubsan/sanitize-all-3.c: New test.
	* c-c++-common/ubsan/sanitize-all-4.c: New test.

--- gcc/opts.c.jj	2015-01-05 15:37:15.155023474 +0100
+++ gcc/opts.c	2015-01-05 16:05:18.659760976 +0100
@@ -1588,6 +1588,7 @@ common_handle_option (struct gcc_options
 		sizeof "returns-nonnull-attribute" - 1 },
 	      { "object-size", SANITIZE_OBJECT_SIZE,
 		sizeof "object-size" - 1 },
+	      { "all", ~0, sizeof "all" - 1 },
 	      { NULL, 0, 0 }
 	    };
 	    const char *comma;
@@ -1611,7 +1612,15 @@ common_handle_option (struct gcc_options
 		  && memcmp (p, spec[i].name, len) == 0)
 		{
 		  /* Handle both -fsanitize and -fno-sanitize cases.  */
-		  if (value)
+		  if (value && spec[i].flag == ~0U)
+		    {
+		      if (code == OPT_fsanitize_)
+			error_at (loc, "-fsanitize=all option is not valid");
+		      else
+			*flag |= ~(SANITIZE_USER_ADDRESS | SANITIZE_THREAD
+				   | SANITIZE_LEAK);
+		    }
+		  else if (value)
 		    *flag |= spec[i].flag;
 		  else
 		    *flag &= ~spec[i].flag;
--- gcc/testsuite/c-c++-common/asan/sanitize-all-1.c.jj	2015-01-05 15:41:43.515357551 +0100
+++ gcc/testsuite/c-c++-common/asan/sanitize-all-1.c	2015-01-05 15:41:43.515357551 +0100
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-sanitize=all" } */
+
+volatile int ten = 10;
+
+int main() {
+  volatile char x[10];
+  x[ten];
+  return 0;
+}
+
+/* { dg-final { scan-assembler-not "__asan_load" } } */
--- gcc/testsuite/c-c++-common/ubsan/sanitize-all-1.c.jj	2015-01-05 15:41:43.515357551 +0100
+++ gcc/testsuite/c-c++-common/ubsan/sanitize-all-1.c	2015-01-05 15:41:43.515357551 +0100
@@ -0,0 +1,8 @@
+/* Test -f*sanitize*=all */
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
+/* { dg-options "-fsanitize=all" } */
+
+int i;
+
+/* { dg-error "-fsanitize=all option is not valid" "" { target *-*-* } 0 } */
--- gcc/testsuite/c-c++-common/ubsan/sanitize-all-2.c.jj	2015-01-05 15:41:43.516357533 +0100
+++ gcc/testsuite/c-c++-common/ubsan/sanitize-all-2.c	2015-01-05 17:46:57.634523012 +0100
@@ -0,0 +1,41 @@
+/* Test -f*sanitize*=all */
+/* { dg-do run } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { *-*-* } { "-flto -fno-fat-lto-objects" } } */
+/* { dg-options "-fsanitize=undefined,float-cast-overflow,float-divide-by-zero -fno-sanitize=all -fdump-tree-optimized" } */
+
+int a[4];
+
+int
+f1 (int x, int y, int z)
+{
+  return a[x] + (1 << y) + (100 / z);
+}
+
+char *
+f2 (int x)
+{
+  char *p = (char *) __builtin_calloc (64, 1);
+  p[x] = 3;
+  return p;
+}
+
+int
+f3 (int x, int *y, double z, double w)
+{
+  int a[*y];
+  if (x)
+    __builtin_unreachable ();
+  asm volatile ("" : : "r" (&a[0]));
+  return z / w;
+}
+
+int
+main ()
+{
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "__ubsan_" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "UBSAN_CHECK_" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
--- gcc/testsuite/c-c++-common/ubsan/sanitize-all-3.c.jj	2015-01-05 15:41:43.516357533 +0100
+++ gcc/testsuite/c-c++-common/ubsan/sanitize-all-3.c	2015-01-05 17:47:03.768418951 +0100
@@ -0,0 +1,42 @@
+/* Test -f*sanitize*=all */
+/* { dg-do run } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { *-*-* } { "-flto -fno-fat-lto-objects" } } */
+/* { dg-options "-fsanitize=undefined -fsanitize-recover=all -fdump-tree-optimized" } */
+
+int a[4];
+
+int
+f1 (int x, int y, int z)
+{
+  return a[x] + (1 << y) + (100 / z);
+}
+
+char *
+f2 (int x)
+{
+  char *p = (char *) __builtin_calloc (64, 1);
+  p[x] = 3;
+  return p;
+}
+
+int
+f3 (int x, int *y, double z, double w)
+{
+  int a[*y];
+  if (x)
+    __builtin_unreachable ();
+  asm volatile ("" : : "r" (&a[0]));
+  return z / w;
+}
+
+int
+main ()
+{
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "__ubsan_" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "__ubsan_\[a-z_\]*_abort" "optimized" } } */
+/* { dg-final { scan-tree-dump "UBSAN_CHECK_" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
--- gcc/testsuite/c-c++-common/ubsan/sanitize-all-4.c.jj	2015-01-05 15:41:43.516357533 +0100
+++ gcc/testsuite/c-c++-common/ubsan/sanitize-all-4.c	2015-01-05 17:47:09.969313754 +0100
@@ -0,0 +1,42 @@
+/* Test -f*sanitize*=all */
+/* { dg-do run } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { *-*-* } { "-flto -fno-fat-lto-objects" } } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover=all -fdump-tree-optimized" } */
+
+int a[4];
+
+int
+f1 (int x, int y, int z)
+{
+  return a[x] + (1 << y) + (100 / z);
+}
+
+char *
+f2 (int x)
+{
+  char *p = (char *) __builtin_calloc (64, 1);
+  p[x] = 3;
+  return p;
+}
+
+int
+f3 (int x, int *y, double z, double w)
+{
+  int a[*y];
+  if (x)
+    __builtin_unreachable ();
+  asm volatile ("" : : "r" (&a[0]));
+  return z / w;
+}
+
+int
+main ()
+{
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "__ubsan_\[a-z_\]*_abort" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "__ubsan_\[a-z_\]*\[^et\] " "optimized" } } */
+/* { dg-final { scan-tree-dump "UBSAN_CHECK_" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */


	Jakub

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

* Re: [PATCH] -f{no-sanitize,{,no-}sanitize-recover}=all support
  2015-01-05 17:40                                                 ` [PATCH] -f{no-sanitize,{,no-}sanitize-recover}=all support Jakub Jelinek
@ 2015-01-05 20:32                                                   ` Jeff Law
  2015-01-05 21:40                                                     ` Jakub Jelinek
  0 siblings, 1 reply; 73+ messages in thread
From: Jeff Law @ 2015-01-05 20:32 UTC (permalink / raw)
  To: Jakub Jelinek, Richard Biener, Dodji Seketeli
  Cc: Alexey Samsonov, Yury Gribov, Marek Polacek, GCC Patches,
	Dmitry Vyukov, Konstantin Serebryany

On 01/05/15 09:58, Jakub Jelinek wrote:
> On Tue, Dec 23, 2014 at 04:47:06PM -0800, Alexey Samsonov wrote:
>> Right, -fsanitize=all produces an error, while -fsanitize-recover=all
>> enables recovery for all
>> sanitizers, -fno-sanitize-recover=all disables recovery for everything.
>
> Ok, here is a GCC patch for that.
> -fno-sanitize=all is supported as a way to turn off all the sanitizers,
> -f{,no-}sanitize-recover=all is supported too, and one can mix all
> with other sanitizer names.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2015-01-05  Jakub Jelinek  <jakub@redhat.com>
>
> 	* opts.c (common_handle_option): Add support for
> 	-fno-sanitize=all and -f{,no-}sanitize-recover=all.
>
> 	* c-c++-common/asan/sanitize-all-1.c: New test.
> 	* c-c++-common/ubsan/sanitize-all-1.c: New test.
> 	* c-c++-common/ubsan/sanitize-all-2.c: New test.
> 	* c-c++-common/ubsan/sanitize-all-3.c: New test.
> 	* c-c++-common/ubsan/sanitize-all-4.c: New test.
Are there any doc updates that need to happen as a result of this patch? 
  Patch itself is fine for the trunk, just want to make sure the doc 
side is good too.

jeff

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

* Re: [PATCH] -f{no-sanitize,{,no-}sanitize-recover}=all support
  2015-01-05 20:32                                                   ` Jeff Law
@ 2015-01-05 21:40                                                     ` Jakub Jelinek
  2015-01-05 22:02                                                       ` Jakub Jelinek
  0 siblings, 1 reply; 73+ messages in thread
From: Jakub Jelinek @ 2015-01-05 21:40 UTC (permalink / raw)
  To: Jeff Law
  Cc: Richard Biener, Dodji Seketeli, Alexey Samsonov, Yury Gribov,
	Marek Polacek, GCC Patches, Dmitry Vyukov, Konstantin Serebryany

On Mon, Jan 05, 2015 at 01:32:42PM -0700, Jeff Law wrote:
> On 01/05/15 09:58, Jakub Jelinek wrote:
> >On Tue, Dec 23, 2014 at 04:47:06PM -0800, Alexey Samsonov wrote:
> >>Right, -fsanitize=all produces an error, while -fsanitize-recover=all
> >>enables recovery for all
> >>sanitizers, -fno-sanitize-recover=all disables recovery for everything.
> >
> >Ok, here is a GCC patch for that.
> >-fno-sanitize=all is supported as a way to turn off all the sanitizers,
> >-f{,no-}sanitize-recover=all is supported too, and one can mix all
> >with other sanitizer names.
> >
> >Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> >
> >2015-01-05  Jakub Jelinek  <jakub@redhat.com>
> >
> >	* opts.c (common_handle_option): Add support for
> >	-fno-sanitize=all and -f{,no-}sanitize-recover=all.
> >
> >	* c-c++-common/asan/sanitize-all-1.c: New test.
> >	* c-c++-common/ubsan/sanitize-all-1.c: New test.
> >	* c-c++-common/ubsan/sanitize-all-2.c: New test.
> >	* c-c++-common/ubsan/sanitize-all-3.c: New test.
> >	* c-c++-common/ubsan/sanitize-all-4.c: New test.
> Are there any doc updates that need to happen as a result of this patch?
> Patch itself is fine for the trunk, just want to make sure the doc side is
> good too.

You're right, I'll add documentation tomorrow and repost the patch.

	Jakub

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

* Re: [PATCH] -f{no-sanitize,{,no-}sanitize-recover}=all support
  2015-01-05 21:40                                                     ` Jakub Jelinek
@ 2015-01-05 22:02                                                       ` Jakub Jelinek
  2015-01-06  9:00                                                         ` Dodji Seketeli
  0 siblings, 1 reply; 73+ messages in thread
From: Jakub Jelinek @ 2015-01-05 22:02 UTC (permalink / raw)
  To: Jeff Law
  Cc: Richard Biener, Dodji Seketeli, Alexey Samsonov, Yury Gribov,
	Marek Polacek, GCC Patches, Dmitry Vyukov, Konstantin Serebryany

On Mon, Jan 05, 2015 at 10:40:37PM +0100, Jakub Jelinek wrote:
> > Are there any doc updates that need to happen as a result of this patch?
> > Patch itself is fine for the trunk, just want to make sure the doc side is
> > good too.
> 
> You're right, I'll add documentation tomorrow and repost the patch.

Make that tonight ;), here it is.  I also found a bug in the
-fsanitize=float-cast-overflow documentation and -f{,no-}sanitize-recover
and fixed that too to much the implementation.

Ok?

2015-01-05  Jakub Jelinek  <jakub@redhat.com>

	* opts.c (common_handle_option): Add support for
	-fno-sanitize=all and -f{,no-}sanitize-recover=all.
	* doc/invoke.texi: Document -fno-sanitize=all,
	-f{,no-}sanitize-recover=all.  Document that
	-fsanitize=float-cast-overflow is not enabled
	by -fsanitize=undefined.  Fix up documentation
	of -f{,no-}sanitize-recover.

	* c-c++-common/asan/sanitize-all-1.c: New test.
	* c-c++-common/ubsan/sanitize-all-1.c: New test.
	* c-c++-common/ubsan/sanitize-all-2.c: New test.
	* c-c++-common/ubsan/sanitize-all-3.c: New test.
	* c-c++-common/ubsan/sanitize-all-4.c: New test.

--- gcc/opts.c.jj	2015-01-05 19:52:17.151813267 +0100
+++ gcc/opts.c	2015-01-05 22:48:11.738814380 +0100
@@ -1588,6 +1588,7 @@ common_handle_option (struct gcc_options
 		sizeof "returns-nonnull-attribute" - 1 },
 	      { "object-size", SANITIZE_OBJECT_SIZE,
 		sizeof "object-size" - 1 },
+	      { "all", ~0, sizeof "all" - 1 },
 	      { NULL, 0, 0 }
 	    };
 	    const char *comma;
@@ -1611,7 +1612,15 @@ common_handle_option (struct gcc_options
 		  && memcmp (p, spec[i].name, len) == 0)
 		{
 		  /* Handle both -fsanitize and -fno-sanitize cases.  */
-		  if (value)
+		  if (value && spec[i].flag == ~0U)
+		    {
+		      if (code == OPT_fsanitize_)
+			error_at (loc, "-fsanitize=all option is not valid");
+		      else
+			*flag |= ~(SANITIZE_USER_ADDRESS | SANITIZE_THREAD
+				   | SANITIZE_LEAK);
+		    }
+		  else if (value)
 		    *flag |= spec[i].flag;
 		  else
 		    *flag &= ~spec[i].flag;
--- gcc/doc/invoke.texi.jj	2015-01-05 22:44:36.000000000 +0100
+++ gcc/doc/invoke.texi	2015-01-05 22:58:23.600292158 +0100
@@ -5683,6 +5683,8 @@ be a legitimate way of obtaining infinit
 @opindex fsanitize=float-cast-overflow
 This option enables floating-point type to integer conversion checking.
 We check that the result of the conversion does not overflow.
+Unlike other similar options, @option{-fsanitize=float-cast-overflow} is
+not enabled by @option{-fsanitize=undefined}.
 This option does not work well with @code{FE_INVALID} exceptions enabled.
 
 @item -fsanitize=nonnull-attribute
@@ -5718,6 +5720,13 @@ While @option{-ftrapv} causes traps for
 @option{-fsanitize=undefined} gives a diagnostic message.
 This currently works only for the C family of languages.
 
+@item -fno-sanitize=all
+@opindex fno-sanitize=all
+
+This option disables all previously enabled sanitizers.
+@option{-fsanitize=all} is not allowed, as some sanitizers cannot be used
+together.
+
 @item -fasan-shadow-offset=@var{number}
 @opindex fasan-shadow-offset
 This option forces GCC to use custom shadow offset in AddressSanitizer checks.
@@ -5741,11 +5750,14 @@ Currently this feature only works for @o
 except for @option{-fsanitize=unreachable} and @option{-fsanitize=return}),
 @option{-fsanitize=float-cast-overflow}, @option{-fsanitize=float-divide-by-zero} and
 @option{-fsanitize=kernel-address}.  For these sanitizers error recovery is turned on by default.
+@option{-fsanitize-recover=all} and @option{-fno-sanitize-recover=all} is also
+accepted, the former enables recovery for all sanitizers that support it,
+the latter disables recovery for all sanitizers that support it.
 
 Syntax without explicit @var{opts} parameter is deprecated.  It is equivalent to
-@option{-fsanitize-recover=undefined,float-cast-overflow,float-divide-by-zero,kernel-address}.
+@option{-fsanitize-recover=undefined,float-cast-overflow,float-divide-by-zero}.
 Similarly @option{-fno-sanitize-recover} is equivalent to
-@option{-fno-sanitize-recover=undefined,float-cast-overflow,float-divide-by-zero,kernel-address}.
+@option{-fno-sanitize-recover=undefined,float-cast-overflow,float-divide-by-zero}.
 
 @item -fsanitize-undefined-trap-on-error
 @opindex fsanitize-undefined-trap-on-error
--- gcc/testsuite/c-c++-common/asan/sanitize-all-1.c.jj	2015-01-05 22:48:11.739814363 +0100
+++ gcc/testsuite/c-c++-common/asan/sanitize-all-1.c	2015-01-05 22:48:11.739814363 +0100
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-sanitize=all" } */
+
+volatile int ten = 10;
+
+int main() {
+  volatile char x[10];
+  x[ten];
+  return 0;
+}
+
+/* { dg-final { scan-assembler-not "__asan_load" } } */
--- gcc/testsuite/c-c++-common/ubsan/sanitize-all-1.c.jj	2015-01-05 22:48:11.739814363 +0100
+++ gcc/testsuite/c-c++-common/ubsan/sanitize-all-1.c	2015-01-05 22:48:11.739814363 +0100
@@ -0,0 +1,8 @@
+/* Test -f*sanitize*=all */
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
+/* { dg-options "-fsanitize=all" } */
+
+int i;
+
+/* { dg-error "-fsanitize=all option is not valid" "" { target *-*-* } 0 } */
--- gcc/testsuite/c-c++-common/ubsan/sanitize-all-2.c.jj	2015-01-05 22:48:11.739814363 +0100
+++ gcc/testsuite/c-c++-common/ubsan/sanitize-all-2.c	2015-01-05 22:48:11.739814363 +0100
@@ -0,0 +1,41 @@
+/* Test -f*sanitize*=all */
+/* { dg-do run } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { *-*-* } { "-flto -fno-fat-lto-objects" } } */
+/* { dg-options "-fsanitize=undefined,float-cast-overflow,float-divide-by-zero -fno-sanitize=all -fdump-tree-optimized" } */
+
+int a[4];
+
+int
+f1 (int x, int y, int z)
+{
+  return a[x] + (1 << y) + (100 / z);
+}
+
+char *
+f2 (int x)
+{
+  char *p = (char *) __builtin_calloc (64, 1);
+  p[x] = 3;
+  return p;
+}
+
+int
+f3 (int x, int *y, double z, double w)
+{
+  int a[*y];
+  if (x)
+    __builtin_unreachable ();
+  asm volatile ("" : : "r" (&a[0]));
+  return z / w;
+}
+
+int
+main ()
+{
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "__ubsan_" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "UBSAN_CHECK_" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
--- gcc/testsuite/c-c++-common/ubsan/sanitize-all-3.c.jj	2015-01-05 22:48:11.740814345 +0100
+++ gcc/testsuite/c-c++-common/ubsan/sanitize-all-3.c	2015-01-05 22:48:11.740814345 +0100
@@ -0,0 +1,42 @@
+/* Test -f*sanitize*=all */
+/* { dg-do run } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { *-*-* } { "-flto -fno-fat-lto-objects" } } */
+/* { dg-options "-fsanitize=undefined -fsanitize-recover=all -fdump-tree-optimized" } */
+
+int a[4];
+
+int
+f1 (int x, int y, int z)
+{
+  return a[x] + (1 << y) + (100 / z);
+}
+
+char *
+f2 (int x)
+{
+  char *p = (char *) __builtin_calloc (64, 1);
+  p[x] = 3;
+  return p;
+}
+
+int
+f3 (int x, int *y, double z, double w)
+{
+  int a[*y];
+  if (x)
+    __builtin_unreachable ();
+  asm volatile ("" : : "r" (&a[0]));
+  return z / w;
+}
+
+int
+main ()
+{
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "__ubsan_" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "__ubsan_\[a-z_\]*_abort" "optimized" } } */
+/* { dg-final { scan-tree-dump "UBSAN_CHECK_" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
--- gcc/testsuite/c-c++-common/ubsan/sanitize-all-4.c.jj	2015-01-05 22:48:11.740814345 +0100
+++ gcc/testsuite/c-c++-common/ubsan/sanitize-all-4.c	2015-01-05 22:48:11.740814345 +0100
@@ -0,0 +1,42 @@
+/* Test -f*sanitize*=all */
+/* { dg-do run } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { *-*-* } { "-flto -fno-fat-lto-objects" } } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover=all -fdump-tree-optimized" } */
+
+int a[4];
+
+int
+f1 (int x, int y, int z)
+{
+  return a[x] + (1 << y) + (100 / z);
+}
+
+char *
+f2 (int x)
+{
+  char *p = (char *) __builtin_calloc (64, 1);
+  p[x] = 3;
+  return p;
+}
+
+int
+f3 (int x, int *y, double z, double w)
+{
+  int a[*y];
+  if (x)
+    __builtin_unreachable ();
+  asm volatile ("" : : "r" (&a[0]));
+  return z / w;
+}
+
+int
+main ()
+{
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "__ubsan_\[a-z_\]*_abort" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "__ubsan_\[a-z_\]*\[^et\] " "optimized" } } */
+/* { dg-final { scan-tree-dump "UBSAN_CHECK_" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */


	Jakub

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

* Re: [PATCH] -f{no-sanitize,{,no-}sanitize-recover}=all support
  2015-01-05 22:02                                                       ` Jakub Jelinek
@ 2015-01-06  9:00                                                         ` Dodji Seketeli
  0 siblings, 0 replies; 73+ messages in thread
From: Dodji Seketeli @ 2015-01-06  9:00 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Jeff Law, Richard Biener, Dodji Seketeli, Alexey Samsonov,
	Yury Gribov, Marek Polacek, GCC Patches, Dmitry Vyukov,
	Konstantin Serebryany

Jakub Jelinek <jakub@redhat.com> writes:

> On Mon, Jan 05, 2015 at 10:40:37PM +0100, Jakub Jelinek wrote:
>> > Are there any doc updates that need to happen as a result of this patch?
>> > Patch itself is fine for the trunk, just want to make sure the doc side is
>> > good too.
>> 
>> You're right, I'll add documentation tomorrow and repost the patch.
>
> Make that tonight ;), here it is.  I also found a bug in the
> -fsanitize=float-cast-overflow documentation and -f{,no-}sanitize-recover
> and fixed that too to much the implementation.
>
> Ok?

[...]

>
> 2015-01-05  Jakub Jelinek  <jakub@redhat.com>
>
> 	* opts.c (common_handle_option): Add support for
> 	-fno-sanitize=all and -f{,no-}sanitize-recover=all.
> 	* doc/invoke.texi: Document -fno-sanitize=all,
> 	-f{,no-}sanitize-recover=all.  Document that
> 	-fsanitize=float-cast-overflow is not enabled
> 	by -fsanitize=undefined.  Fix up documentation
> 	of -f{,no-}sanitize-recover.
>
> 	* c-c++-common/asan/sanitize-all-1.c: New test.
> 	* c-c++-common/ubsan/sanitize-all-1.c: New test.
> 	* c-c++-common/ubsan/sanitize-all-2.c: New test.
> 	* c-c++-common/ubsan/sanitize-all-3.c: New test.
> 	* c-c++-common/ubsan/sanitize-all-4.c: New test.

This is OK.  Thanks!

-- 
		Dodji

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

end of thread, other threads:[~2015-01-06  9:00 UTC | newest]

Thread overview: 73+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-05  6:54 [PATCH] Enable -fsanitize-recover for KASan Yury Gribov
2014-09-05  7:32 ` Dmitry Vyukov
2014-09-05  8:12   ` Yury Gribov
2014-09-05  8:23     ` Dmitry Vyukov
2014-09-05  8:33       ` Yury Gribov
2014-09-05  9:28         ` Jakub Jelinek
2014-09-05  9:32           ` Yury Gribov
2014-09-05  9:05 ` Andrey Ryabinin
2014-09-05  9:12   ` Yury Gribov
2014-09-15  9:38 ` [PATCH][PING] " Yury Gribov
2014-09-18 10:53   ` Jakub Jelinek
2014-09-18 13:14     ` Yury Gribov
2014-09-18 23:47     ` Joseph S. Myers
2014-09-29 17:21   ` [PATCHv3][PING] " Yury Gribov
2014-09-29 17:44     ` Jakub Jelinek
2014-09-29 21:20       ` Konstantin Serebryany
2014-09-29 22:37         ` Alexey Samsonov
     [not found]         ` <CAGSYnCPwbgZ++2Jt2vE6-ytveSJwSQPZT5umLeKPVWsVjWzwPQ@mail.gmail.com>
2014-09-29 23:17           ` Jakub Jelinek
2014-09-29 23:26             ` Alexey Samsonov
2014-09-30  0:24               ` Konstantin Serebryany
2014-09-30  1:05                 ` Alexey Samsonov
2014-09-30  1:49                   ` Konstantin Serebryany
2014-09-30  5:40                 ` Jakub Jelinek
2014-09-30  7:07                   ` Yury Gribov
2014-09-30 17:26                     ` Alexey Samsonov
2014-09-30 17:33                       ` Jakub Jelinek
2014-09-30 17:36                         ` Alexey Samsonov
2014-09-30 17:39                           ` Jakub Jelinek
2014-10-01 23:21                             ` Alexey Samsonov
2014-10-02  5:58                               ` Jakub Jelinek
2014-10-03 18:54                                 ` Alexey Samsonov
     [not found]                             ` <543BADAB.4090000@samsung.com>
2014-10-17 16:16                               ` [PATCH] -fsanitize-recover=list Jakub Jelinek
2014-10-20 10:44                                 ` Yury Gribov
2014-10-22  8:05                                 ` Yury Gribov
2014-10-22 10:02                                   ` Jakub Jelinek
2014-11-18  2:50                                 ` Alexey Samsonov
2014-11-18  7:27                                   ` Jakub Jelinek
2014-11-18  8:29                                     ` Alexey Samsonov
2014-11-18  8:34                                       ` Jakub Jelinek
2014-11-18 20:25                                         ` Alexey Samsonov
2014-12-19  2:47                                           ` Alexey Samsonov
2014-12-19  8:14                                             ` Jakub Jelinek
     [not found]                                               ` <CAGSYnCNLoU0p3FGDwb6mMAAOWFz2Te1m7wmWD94PhcADsQs9rQ@mail.gmail.com>
2015-01-05 17:40                                                 ` [PATCH] -f{no-sanitize,{,no-}sanitize-recover}=all support Jakub Jelinek
2015-01-05 20:32                                                   ` Jeff Law
2015-01-05 21:40                                                     ` Jakub Jelinek
2015-01-05 22:02                                                       ` Jakub Jelinek
2015-01-06  9:00                                                         ` Dodji Seketeli
2014-11-18  7:39                                   ` [PATCH] -fsanitize-recover=list Yury Gribov
2014-09-30  6:57                 ` [PATCHv3][PING] Enable -fsanitize-recover for KASan Yury Gribov
2014-09-30  7:14                   ` Yury Gribov
2014-10-23  7:15     ` [PATCHv4] " Yury Gribov
2014-10-23  7:20       ` Jakub Jelinek
2014-10-23  7:30         ` Yury Gribov
2014-10-23  9:55           ` Andrey Ryabinin
2014-10-23 10:00             ` Jakub Jelinek
2014-10-23 10:07               ` Jakub Jelinek
2014-10-23 10:24                 ` Andrey Ryabinin
2014-10-23 10:27                   ` Yury Gribov
2014-10-23 10:11               ` Andrey Ryabinin
2014-10-23 10:17                 ` Jakub Jelinek
2014-10-23 10:38                   ` Yury Gribov
2014-10-23 10:39                     ` Jakub Jelinek
2014-10-23 11:12                       ` Andrey Ryabinin
2014-10-24  8:37                         ` Yury Gribov
2014-10-24  9:46                           ` Dmitry Vyukov
2014-10-24  9:52                             ` Jakub Jelinek
2014-10-24  9:56                               ` Dmitry Vyukov
2014-10-24  9:59                               ` Jakub Jelinek
2014-10-24 10:01                             ` Yury Gribov
2014-10-24 10:21                               ` Dmitry Vyukov
2014-10-28  8:46       ` [PATCH v5] " Yury Gribov
2014-10-28  9:31         ` Jakub Jelinek
2014-10-28 10:15           ` Yury Gribov

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