]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR sanitizer/60275 ([UBSAN] Add -f[no-]sanitize-recover/-fsanitize-undefined-trap...
authorJakub Jelinek <jakub@redhat.com>
Wed, 23 Apr 2014 08:20:12 +0000 (10:20 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 23 Apr 2014 08:20:12 +0000 (10:20 +0200)
PR sanitizer/60275
* common.opt (fsanitize-recover, fsanitize-undefined-trap-on-error):
New options.
* gcc.c (sanitize_spec_function): Don't return "" for "undefined"
if flag_sanitize_undefined_trap_on_error.
* sanitizer.def (BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT,
BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS_ABORT,
BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE_ABORT,
BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT,
BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT,
BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT,
BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT,
BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT,
BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT): New builtins.
* ubsan.c (ubsan_instrument_unreachable): Return
__builtin_trap () if flag_sanitize_undefined_trap_on_error.
(ubsan_expand_null_ifn): Emit __builtin_trap ()
if flag_sanitize_undefined_trap_on_error and
__ubsan_handle_type_mismatch_abort if !flag_sanitize_recover.
(ubsan_expand_null_ifn, ubsan_build_overflow_builtin,
instrument_bool_enum_load): Emit __builtin_trap () if
flag_sanitize_undefined_trap_on_error and
__builtin_handle_*_abort () if !flag_sanitize_recover.
* doc/invoke.texi (-fsanitize-recover,
-fsanitize-undefined-trap-on-error): Document.
c-family/
* c-ubsan.c (ubsan_instrument_return): Return __builtin_trap ()
if flag_sanitize_undefined_trap_on_error.
(ubsan_instrument_division, ubsan_instrument_shift,
ubsan_instrument_vla): Likewise.  Use __ubsan_handle_*_abort ()
if !flag_sanitize_recover.
testsuite/
* g++.dg/ubsan/return-2.C: Revert 2014-03-24 changes, add
-fno-sanitize-recover to dg-options.
* g++.dg/ubsan/cxx11-shift-1.C: Remove c++11 target restriction,
add -std=c++11 to dg-options.
* g++.dg/ubsan/cxx11-shift-2.C: Likewise.
* g++.dg/ubsan/cxx1y-vla.C: Remove c++1y target restriction,
add -std=c++1y to dg-options.
* c-c++-common/ubsan/undefined-1.c: Revert 2014-03-24 changes, add
-fno-sanitize-recover to dg-options.
* c-c++-common/ubsan/overflow-sub-1.c: Likewise.
* c-c++-common/ubsan/vla-4.c: Likewise.
* c-c++-common/ubsan/pr59503.c: Likewise.
* c-c++-common/ubsan/vla-3.c: Likewise.
* c-c++-common/ubsan/save-expr-1.c: Likewise.
* c-c++-common/ubsan/overflow-add-1.c: Likewise.
* c-c++-common/ubsan/shift-3.c: Likewise.
* c-c++-common/ubsan/overflow-1.c: Likewise.
* c-c++-common/ubsan/overflow-negate-2.c: Likewise.
* c-c++-common/ubsan/vla-2.c: Likewise.
* c-c++-common/ubsan/overflow-mul-1.c: Likewise.
* c-c++-common/ubsan/pr60613-1.c: Likewise.
* c-c++-common/ubsan/shift-6.c: Likewise.
* c-c++-common/ubsan/overflow-mul-3.c: Likewise.
* c-c++-common/ubsan/overflow-add-3.c: New test.
* c-c++-common/ubsan/overflow-add-4.c: New test.
* c-c++-common/ubsan/div-by-zero-6.c: New test.
* c-c++-common/ubsan/div-by-zero-7.c: New test.

From-SVN: r209672

32 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-ubsan.c
gcc/common.opt
gcc/doc/invoke.texi
gcc/gcc.c
gcc/sanitizer.def
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/ubsan/div-by-zero-6.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/ubsan/overflow-1.c
gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c
gcc/testsuite/c-c++-common/ubsan/overflow-add-3.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/ubsan/overflow-add-4.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/ubsan/overflow-mul-1.c
gcc/testsuite/c-c++-common/ubsan/overflow-mul-3.c
gcc/testsuite/c-c++-common/ubsan/overflow-negate-2.c
gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c
gcc/testsuite/c-c++-common/ubsan/pr59503.c
gcc/testsuite/c-c++-common/ubsan/pr60613-1.c
gcc/testsuite/c-c++-common/ubsan/save-expr-1.c
gcc/testsuite/c-c++-common/ubsan/shift-3.c
gcc/testsuite/c-c++-common/ubsan/shift-6.c
gcc/testsuite/c-c++-common/ubsan/undefined-1.c
gcc/testsuite/c-c++-common/ubsan/vla-2.c
gcc/testsuite/c-c++-common/ubsan/vla-3.c
gcc/testsuite/c-c++-common/ubsan/vla-4.c
gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C
gcc/testsuite/g++.dg/ubsan/cxx11-shift-2.C
gcc/testsuite/g++.dg/ubsan/cxx1y-vla.C
gcc/testsuite/g++.dg/ubsan/return-2.C
gcc/ubsan.c

index 61987af01bffe04a17ed0623047a89027c777986..109808960608d083fd424c66880d6f4ab0351a01 100644 (file)
@@ -1,3 +1,31 @@
+2014-04-22  Jakub Jelinek  <jakub@redhat.com>
+
+       PR sanitizer/60275
+       * common.opt (fsanitize-recover, fsanitize-undefined-trap-on-error):
+       New options.
+       * gcc.c (sanitize_spec_function): Don't return "" for "undefined"
+       if flag_sanitize_undefined_trap_on_error.
+       * sanitizer.def (BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT,
+       BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS_ABORT,
+       BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE_ABORT,
+       BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT,
+       BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT,
+       BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT,
+       BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT,
+       BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT,
+       BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT): New builtins.
+       * ubsan.c (ubsan_instrument_unreachable): Return
+       __builtin_trap () if flag_sanitize_undefined_trap_on_error.
+       (ubsan_expand_null_ifn): Emit __builtin_trap ()
+       if flag_sanitize_undefined_trap_on_error and
+       __ubsan_handle_type_mismatch_abort if !flag_sanitize_recover.
+       (ubsan_expand_null_ifn, ubsan_build_overflow_builtin,
+       instrument_bool_enum_load): Emit __builtin_trap () if
+       flag_sanitize_undefined_trap_on_error and
+       __builtin_handle_*_abort () if !flag_sanitize_recover.
+       * doc/invoke.texi (-fsanitize-recover,
+       -fsanitize-undefined-trap-on-error): Document.
+
 2014-04-22  Christian Bruel  <christian.bruel@st.com>
 
        * config/sh/sh.md (mov<mode>): Replace movQIHI.
index 66158caa6a95be31836fc78c608dd51a7b45007a..11b4bc437eaec93fdfe3c3768982c4b5fbb521f6 100644 (file)
@@ -1,3 +1,12 @@
+2014-04-22  Jakub Jelinek  <jakub@redhat.com>
+
+       PR sanitizer/60275
+       * c-ubsan.c (ubsan_instrument_return): Return __builtin_trap ()
+       if flag_sanitize_undefined_trap_on_error.
+       (ubsan_instrument_division, ubsan_instrument_shift,
+       ubsan_instrument_vla): Likewise.  Use __ubsan_handle_*_abort ()
+       if !flag_sanitize_recover.
+
 2014-04-22  Marc Glisse  <marc.glisse@inria.fr>
 
        PR libstdc++/43622
index e89ebc1873befae7a71af8a01b0f0f72ddb935d0..e4f6f327277b69b61516978d67794c8b80f95692 100644 (file)
@@ -73,14 +73,22 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
   /* In case we have a SAVE_EXPR in a conditional context, we need to
      make sure it gets evaluated before the condition.  */
   t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
-  tree data = ubsan_create_data ("__ubsan_overflow_data",
-                                &loc, NULL,
-                                ubsan_type_descriptor (type, false),
-                                NULL_TREE);
-  data = build_fold_addr_expr_loc (loc, data);
-  tt = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW);
-  tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
-                           ubsan_encode_value (op1));
+  if (flag_sanitize_undefined_trap_on_error)
+    tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
+  else
+    {
+      tree data = ubsan_create_data ("__ubsan_overflow_data", &loc, NULL,
+                                    ubsan_type_descriptor (type, false),
+                                    NULL_TREE);
+      data = build_fold_addr_expr_loc (loc, data);
+      enum built_in_function bcode
+       = flag_sanitize_recover
+         ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
+         : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT;
+      tt = builtin_decl_explicit (bcode);
+      tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
+                               ubsan_encode_value (op1));
+    }
   t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node);
 
   return t;
@@ -142,19 +150,28 @@ ubsan_instrument_shift (location_t loc, enum tree_code code,
   /* In case we have a SAVE_EXPR in a conditional context, we need to
      make sure it gets evaluated before the condition.  */
   t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
-  tree data = ubsan_create_data ("__ubsan_shift_data",
-                                &loc, NULL,
-                                ubsan_type_descriptor (type0, false),
-                                ubsan_type_descriptor (type1, false),
-                                NULL_TREE);
-
-  data = build_fold_addr_expr_loc (loc, data);
-
   t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t,
                   tt ? tt : integer_zero_node);
-  tt = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS);
-  tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
-                           ubsan_encode_value (op1));
+
+  if (flag_sanitize_undefined_trap_on_error)
+    tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
+  else
+    {
+      tree data = ubsan_create_data ("__ubsan_shift_data", &loc, NULL,
+                                    ubsan_type_descriptor (type0, false),
+                                    ubsan_type_descriptor (type1, false),
+                                    NULL_TREE);
+
+      data = build_fold_addr_expr_loc (loc, data);
+
+      enum built_in_function bcode
+       = flag_sanitize_recover
+         ? BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS
+         : BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS_ABORT;
+      tt = builtin_decl_explicit (bcode);
+      tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
+                               ubsan_encode_value (op1));
+    }
   t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node);
 
   return t;
@@ -169,13 +186,21 @@ ubsan_instrument_vla (location_t loc, tree size)
   tree t, tt;
 
   t = fold_build2 (LE_EXPR, boolean_type_node, size, build_int_cst (type, 0));
-  tree data = ubsan_create_data ("__ubsan_vla_data",
-                                &loc, NULL,
-                                ubsan_type_descriptor (type, false),
-                                NULL_TREE);
-  data = build_fold_addr_expr_loc (loc, data);
-  tt = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE);
-  tt = build_call_expr_loc (loc, tt, 2, data, ubsan_encode_value (size));
+  if (flag_sanitize_undefined_trap_on_error)
+    tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
+  else
+    {
+      tree data = ubsan_create_data ("__ubsan_vla_data", &loc, NULL,
+                                    ubsan_type_descriptor (type, false),
+                                    NULL_TREE);
+      data = build_fold_addr_expr_loc (loc, data);
+      enum built_in_function bcode
+       = flag_sanitize_recover
+         ? BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE
+         : BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE_ABORT;
+      tt = builtin_decl_explicit (bcode);
+      tt = build_call_expr_loc (loc, tt, 2, data, ubsan_encode_value (size));
+    }
   t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node);
 
   return t;
@@ -186,6 +211,8 @@ ubsan_instrument_vla (location_t loc, tree size)
 tree
 ubsan_instrument_return (location_t loc)
 {
+  if (flag_sanitize_undefined_trap_on_error)
+    return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
   /* It is possible that PCH zapped table with definitions of sanitizer
      builtins.  Reinitialize them if needed.  */
   initialize_sanitizer_builtins ();
index da275e5cb45053ab9b62475926111fd0ec1ceeb6..d46d4c7e70a244451d117ca843859b6020f0a033 100644 (file)
@@ -862,6 +862,14 @@ fsanitize=
 Common Driver Report Joined
 Select what to sanitize
 
+fsanitize-recover
+Common Report Var(flag_sanitize_recover) Init(1)
+After diagnosing undefined behavior attempt to continue execution
+
+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
+
 fasynchronous-unwind-tables
 Common Report Var(flag_asynchronous_unwind_tables) Optimization
 Generate unwind tables that are exact at each instruction boundary
index 7d039098c4dffe232ab47d4ac28388908182bc30..c5572b6fea3797bd17f1880f33e5044e9b6817be 100644 (file)
@@ -288,7 +288,8 @@ 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} @gol
+-fsanitize=@var{style} -fsanitize-recover @gol
+-fsanitize-undefined-trap-on-error @gol
 -fdbg-cnt-list -fdbg-cnt=@var{counter-value-list} @gol
 -fdisable-ipa-@var{pass_name} @gol
 -fdisable-rtl-@var{pass_name} @gol
@@ -5380,6 +5381,26 @@ 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
+@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
+and program will exit after that with non-zero exit code.
+
+@item -fsanitize-undefined-trap-on-error
+@opindex fsanitize-undefined-trap-on-error
+The @option{-fsanitize-undefined-trap-on-error} instructs the compiler to
+report undefined behavior using @code{__builtin_trap ()} rather than
+a @code{libubsan} library routine.  The advantage of this is that the
+@code{libubsan} library is not needed and will not be linked in, so this
+is usable even for use in freestanding environments.
+
 @item -fdump-final-insns@r{[}=@var{file}@r{]}
 @opindex fdump-final-insns
 Dump the final internal representation (RTL) to @var{file}.  If the
index c8ab7d674845341531a8a4f729cc397fdacbc88d..e5130d13535604a1e852434925fbe734440d2996 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -8170,7 +8170,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) ? "" : NULL;
+    return ((flag_sanitize & SANITIZE_UNDEFINED)
+           && !flag_sanitize_undefined_trap_on_error) ? "" : NULL;
   if (strcmp (argv[0], "leak") == 0)
     return ((flag_sanitize
             & (SANITIZE_ADDRESS | SANITIZE_LEAK | SANITIZE_THREAD))
index 015b1d85f5f166ed29129c0943d48af9d1c30550..6184b5ad58bdd79aaa81b56c42a93a705ed117f0 100644 (file)
@@ -335,3 +335,39 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE,
                      "__ubsan_handle_load_invalid_value",
                      BT_FN_VOID_PTR_PTR,
                      ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT,
+                     "__ubsan_handle_divrem_overflow_abort",
+                     BT_FN_VOID_PTR_PTR_PTR,
+                     ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS_ABORT,
+                     "__ubsan_handle_shift_out_of_bounds_abort",
+                     BT_FN_VOID_PTR_PTR_PTR,
+                     ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE_ABORT,
+                     "__ubsan_handle_vla_bound_not_positive_abort",
+                     BT_FN_VOID_PTR_PTR,
+                     ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT,
+                     "__ubsan_handle_type_mismatch_abort",
+                     BT_FN_VOID_PTR_PTR,
+                     ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT,
+                     "__ubsan_handle_add_overflow_abort",
+                     BT_FN_VOID_PTR_PTR_PTR,
+                     ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT,
+                     "__ubsan_handle_sub_overflow_abort",
+                     BT_FN_VOID_PTR_PTR_PTR,
+                     ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT,
+                     "__ubsan_handle_mul_overflow_abort",
+                     BT_FN_VOID_PTR_PTR_PTR,
+                     ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT,
+                     "__ubsan_handle_negate_overflow_abort",
+                     BT_FN_VOID_PTR_PTR,
+                     ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT,
+                     "__ubsan_handle_load_invalid_value_abort",
+                     BT_FN_VOID_PTR_PTR,
+                     ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
index 69a566757ef78c6b428b6c77508f11b3bf456be9..abbd1cfee87a1b625efbeea719a4fe8e1bbb75fc 100644 (file)
@@ -1,3 +1,34 @@
+2014-04-22  Jakub Jelinek  <jakub@redhat.com>
+
+       PR sanitizer/60275
+       * g++.dg/ubsan/return-2.C: Revert 2014-03-24 changes, add
+       -fno-sanitize-recover to dg-options.
+       * g++.dg/ubsan/cxx11-shift-1.C: Remove c++11 target restriction,
+       add -std=c++11 to dg-options.
+       * g++.dg/ubsan/cxx11-shift-2.C: Likewise.
+       * g++.dg/ubsan/cxx1y-vla.C: Remove c++1y target restriction,
+       add -std=c++1y to dg-options.
+       * c-c++-common/ubsan/undefined-1.c: Revert 2014-03-24 changes, add
+       -fno-sanitize-recover to dg-options.
+       * c-c++-common/ubsan/overflow-sub-1.c: Likewise.
+       * c-c++-common/ubsan/vla-4.c: Likewise.
+       * c-c++-common/ubsan/pr59503.c: Likewise.
+       * c-c++-common/ubsan/vla-3.c: Likewise.
+       * c-c++-common/ubsan/save-expr-1.c: Likewise.
+       * c-c++-common/ubsan/overflow-add-1.c: Likewise.
+       * c-c++-common/ubsan/shift-3.c: Likewise.
+       * c-c++-common/ubsan/overflow-1.c: Likewise.
+       * c-c++-common/ubsan/overflow-negate-2.c: Likewise.
+       * c-c++-common/ubsan/vla-2.c: Likewise.
+       * c-c++-common/ubsan/overflow-mul-1.c: Likewise.
+       * c-c++-common/ubsan/pr60613-1.c: Likewise.
+       * c-c++-common/ubsan/shift-6.c: Likewise.
+       * c-c++-common/ubsan/overflow-mul-3.c: Likewise.
+       * c-c++-common/ubsan/overflow-add-3.c: New test.
+       * c-c++-common/ubsan/overflow-add-4.c: New test.
+       * c-c++-common/ubsan/div-by-zero-6.c: New test.
+       * c-c++-common/ubsan/div-by-zero-7.c: New test.
+
 2014-04-22  Christian Bruel  <christian.bruel@st.com>
 
        * gcc.target/sh/hiconst.c: New test.
diff --git a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-6.c b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-6.c
new file mode 100644 (file)
index 0000000..27a18bb
--- /dev/null
@@ -0,0 +1,49 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-div-by-zero" } */
+
+#include <stdio.h>
+
+int x;
+
+__attribute__((noinline, noclone))
+void
+barrier (void)
+{
+  asm volatile ("" : : : "memory");
+  if (x)
+    __builtin_exit (1);
+}
+
+int
+main (void)
+{
+  volatile int a = 0;
+  volatile long long int b = 0;
+  volatile unsigned int c = 1;
+
+  barrier (); fputs ("1st\n", stderr); barrier ();
+  a / b;
+  barrier (); fputs ("2nd\n", stderr); barrier ();
+  0 / 0;
+  barrier (); fputs ("3rd\n", stderr); barrier ();
+  a / 0;
+  barrier (); fputs ("4th\n", stderr); barrier ();
+  0 / b;
+  barrier (); fputs ("5th\n", stderr); barrier ();
+  2 / --c;
+  barrier (); fputs ("6th\n", stderr); barrier ();
+
+  return 0;
+}
+
+/* { dg-output "1st(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*division by zero\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "2nd(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*division by zero\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "3rd(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*division by zero\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "4th(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*division by zero\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "5th(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*division by zero\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "6th" } */
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
new file mode 100644 (file)
index 0000000..b65a0bc
--- /dev/null
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-div-by-zero -fno-sanitize-recover" } */
+/* { dg-shouldfail "ubsan" } */
+
+#include <stdio.h>
+
+int x;
+
+__attribute__((noinline, noclone))
+void
+barrier (void)
+{
+  asm volatile ("" : : : "memory");
+  if (++x == 3)
+    __builtin_exit (0);
+}
+
+int
+main (void)
+{
+  volatile int a = 0;
+  volatile long long int b = 0;
+  volatile unsigned int c = 1;
+
+  barrier (); fputs ("1st\n", stderr); barrier ();
+  a / b;
+  barrier (); fputs ("2nd\n", stderr); barrier ();
+  0 / 0;
+  barrier (); fputs ("3rd\n", stderr); barrier ();
+  a / 0;
+  barrier (); fputs ("4th\n", stderr); barrier ();
+  0 / b;
+  barrier (); fputs ("5th\n", stderr); barrier ();
+  2 / --c;
+  barrier (); fputs ("6th\n", stderr); barrier ();
+
+  return 0;
+}
+
+/* { dg-output "1st(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*division by zero" } */
index 68199551b497cda8dac476a44b1d13aa9a357e4f..b0ef25924e8db82a2605c0b7dc350ca2dcbdf036 100644 (file)
@@ -1,7 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow" } */
-
-#include <stdio.h>
+/* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover" } */
 
 #ifndef ASM1
 # define ASM1(a) /* Nothing */
@@ -53,8 +51,6 @@
 int
 main (void)
 {
-  fputs ("UBSAN TEST START\n", stderr);
-
   CHECK (FN1 (char, char, +), 23);
   CHECK (FN1 (char, char, -), 5);
   CHECK (FN1 (char, char, *), 126);
@@ -261,9 +257,5 @@ main (void)
   CHECK (FN5 (unsigned long int), -77);
   CHECK (FN5 (long long int), -77);
   CHECK (FN5 (unsigned long long int), -77);
-
-  fputs ("UBSAN TEST END\n", stderr);
   return 0;
 }
-
-/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
index fd6c6d325e8137e09bceb289c3151acc84fbfeab..b009f5bb18614a4c0b5852d55053fda2a0aa1823 100644 (file)
@@ -1,7 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable" } */
-
-#include <stdio.h>
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
 
 #define SCHAR_MAX __SCHAR_MAX__
 #define SHRT_MAX __SHRT_MAX__
@@ -18,8 +16,6 @@ check (int i, int j)
 int
 main (void)
 {
-  fputs ("UBSAN TEST START\n", stderr);
-
 #if __INT_MAX__ == 2147483647
   /* Here, nothing should fail.  */
   volatile int j = INT_MAX;
@@ -59,9 +55,5 @@ main (void)
   d++;
   check (d, -32768);
 #endif
-
-  fputs ("UBSAN TEST END\n", stderr);
   return 0;
 }
-
-/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-add-3.c b/gcc/testsuite/c-c++-common/ubsan/overflow-add-3.c
new file mode 100644 (file)
index 0000000..6475d10
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
+/* { dg-shouldfail "ubsan" } */
+
+#define INT_MAX __INT_MAX__
+#define INT_MIN (-__INT_MAX__ - 1)
+
+int
+main (void)
+{
+  volatile int j = INT_MAX;
+  volatile int i = 1;
+  volatile int k = j + i;
+  return 0;
+}
+
+/* { dg-output "signed integer overflow: 2147483647 \\+ 1 cannot be represented in type 'int'" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-add-4.c b/gcc/testsuite/c-c++-common/ubsan/overflow-add-4.c
new file mode 100644 (file)
index 0000000..3f6f6bd
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fsanitize-undefined-trap-on-error" } */
+/* { dg-shouldfail "ubsan" } */
+
+#define INT_MAX __INT_MAX__
+#define INT_MIN (-__INT_MAX__ - 1)
+
+int
+main (void)
+{
+  volatile int j = INT_MAX;
+  volatile int i = 1;
+  volatile int k = j + i;
+  return 0;
+}
index afb1a25967634e0cdd9cdde338e1a0fdeb8752bd..22ea6398752b19eff795558b8d8b161189873b2b 100644 (file)
@@ -1,7 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable" } */
-
-#include <stdio.h>
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
 
 #define SCHAR_MAX __SCHAR_MAX__
 #define SHRT_MAX __SHRT_MAX__
@@ -18,8 +16,6 @@ check (int i, int j)
 int
 main (void)
 {
-  fputs ("UBSAN TEST START\n", stderr);
-
   /* Test integer promotion.  */
 #if __SCHAR_MAX__ == 127
   volatile signed char a = -2;
@@ -45,9 +41,5 @@ main (void)
   o = m * n;
   check (o, INT_MIN);
 #endif
-
-  fputs ("UBSAN TEST END\n", stderr);
   return 0;
 }
-
-/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
index 037609be0ac10764edc033fe7056e466e001238b..896c0bc0279548baa8a48d88ac7640a9232edaf1 100644 (file)
@@ -1,7 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow" } */
-
-#include <stdio.h>
+/* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover" } */
 
 __attribute__((noinline, noclone)) long long
 mul (long long x, long long y)
@@ -31,16 +29,10 @@ long long tab[] = {
 int
 main ()
 {
-  fputs ("UBSAN TEST START\n", stderr);
-
   unsigned int i;
   for (i = 0; i < sizeof (tab) / sizeof (long long); i += 3)
     if (mul (tab[i], tab[i + 1]) != tab[i + 2]
         || mul (tab[i + 1], tab[i]) != tab[i + 2])
       __builtin_abort ();
-
-  fputs ("UBSAN TEST END\n", stderr);
   return 0;
 }
-
-/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
index 6a4f288bbe0c509d109a10b5a776a36881bc1bc5..8b5ffa5893a8bb5c1bab92de4b42f9249294ac3a 100644 (file)
@@ -1,7 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable" } */
-
-#include <stdio.h>
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
 
 #define SCHAR_MIN (-__SCHAR_MAX__ - 1)
 #define SHRT_MIN (-__SHRT_MAX__ - 1)
@@ -14,8 +12,6 @@
 int
 main (void)
 {
-  fputs ("UBSAN TEST START\n", stderr);
-
   volatile signed char c = -SCHAR_MIN;
   CHECK (c, -128);
 
@@ -37,9 +33,5 @@ main (void)
   volatile long long lli = LLONG_MIN;
   lli = -(unsigned long long) lli;
   CHECK (lli, -0x8000000000000000L);
-
-  fputs ("UBSAN TEST END\n", stderr);
   return 0;
 }
-
-/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
index 15f04455e6eda8caa71d72064f5413b808622809..2b10f9e5905c885dff2e0cd68299aaba01aa3719 100644 (file)
@@ -1,7 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable" } */
-
-#include <stdio.h>
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
 
 #define SCHAR_MAX __SCHAR_MAX__
 #define SCHAR_MIN (-__SCHAR_MAX__ - 1)
@@ -20,8 +18,6 @@ check (int i, int j)
 int
 main (void)
 {
-  fputs ("UBSAN TEST START\n", stderr);
-
 #if __INT_MAX__ == 2147483647
   /* Here, nothing should fail.  */
   volatile int i = -1;
@@ -61,9 +57,5 @@ main (void)
   d--;
   check (d, 32767);
 #endif
-
-  fputs ("UBSAN TEST END\n", stderr);
   return 0;
 }
-
-/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
index 1637f01b5a1fa6f500a6efbcd0838cc8fe25f4bd..81447d7e16b7c118bc7cb52ae075e32ebaf0c8a3 100644 (file)
@@ -1,21 +1,13 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=signed-integer-overflow" } */
-
-#include <stdio.h>
+/* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover" } */
 
 int
 main (void)
 {
-  fputs ("UBSAN TEST START\n", stderr);
-
   long long int a = 14;
   long int b = 9;
   asm volatile ("" : "+r" (a), "+r" (b));
   if ((a - b) != 5)
     __builtin_abort ();
-
-  fputs ("UBSAN TEST END\n", stderr);
   return 0;
 }
-
-/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
index 6794532a486881e00b4f1d879a2b3828e1017c62..4c0810b5de2b972c79bf97355799bf751e654c77 100644 (file)
@@ -1,8 +1,6 @@
 /* PR sanitizer/60613 */
 /* { dg-do run } */
-/* { dg-options "-fsanitize=undefined" } */
-
-#include <stdio.h>
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
 
 long long y;
 
@@ -26,16 +24,10 @@ bar (long long x)
 int
 main ()
 {
-  fputs ("UBSAN TEST START\n", stderr);
-
   y = 1;
   if (foo (8 - 2040) != 8 - 1)
     __builtin_abort ();
   if (bar (1) != 8 - 1)
     __builtin_abort ();
-
-  fputs ("UBSAN TEST END\n", stderr);
   return 0;
 }
-
-/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
index 19b1eb08bd662c01fc0cc61c5f615c9befd160d6..89ac58c281e4e9b8af10bf91ace8eedd7d1e8eba 100644 (file)
@@ -1,19 +1,11 @@
 /* { dg-do compile } */
-/* { dg-options "-fsanitize=shift -Wall -Werror -O" } */
-
-#include <stdio.h>
+/* { dg-options "-fsanitize=shift -Wall -Werror -O -fno-sanitize-recover" } */
 
 static int x;
 int
 main (void)
 {
-  fputs ("UBSAN TEST START\n", stderr);
-
   int o = 1;
   int y = x << o;
-
-  fputs ("UBSAN TEST END\n", stderr);
   return y;
 }
-
-/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
index 65ee5d8821e06adeded76a99492040c712d21fe1..67f1b6961776bd3eefb26f60ba45597e1db5f8c3 100644 (file)
@@ -1,19 +1,11 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=shift -w" } */
-
-#include <stdio.h>
+/* { dg-options "-fsanitize=shift -w -fno-sanitize-recover" } */
 
 int
 main (void)
 {
-  fputs ("UBSAN TEST START\n", stderr);
-
   unsigned int a = 1;
   a <<= 31;
   a <<= 1;
-
-  fputs ("UBSAN TEST END\n", stderr);
   return 0;
 }
-
-/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
index d88a42910a6046916bb792e683e81b425a414598..e26e6846ca769e867e986dfafd7f862e73e6d391 100644 (file)
@@ -1,15 +1,11 @@
 /* PR sanitizer/58413 */
 /* { dg-do run { target int32plus } } */
-/* { dg-options "-fsanitize=shift -w" } */
-
-#include <stdio.h>
+/* { dg-options "-fsanitize=shift -w -fno-sanitize-recover" } */
 
 int x = 7;
 int
 main (void)
 {
-  fputs ("UBSAN TEST START\n", stderr);
-
   /* All of the following should pass.  */
   int A[128 >> 5] = {};
   int B[128 << 5] = {};
@@ -30,9 +26,5 @@ main (void)
     case 128 >> (4 + 1):
       return 1;
     }
-
-  fputs ("UBSAN TEST END\n", stderr);
   return 0;
 }
-
-/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
index d1b9ce78771f5fdf68aa46edf1c7290169739466..201818ddd7f371d49eb5e2a8c4a0d1020bf8ef34 100644 (file)
@@ -1,7 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=undefined" } */
-
-#include <stdio.h>
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
 
 int
 foo (int x, int y)
@@ -21,13 +19,7 @@ bar (int x, int y)
 int
 main (void)
 {
-  fputs ("UBSAN TEST START\n", stderr);
-
   foo (3, 2);
   bar (12, 42);
-
-  fputs ("UBSAN TEST END\n", stderr);
   return 0;
 }
-
-/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
index a11e4e7227ff2b3b4e2a28136a0cf5cecb01b80e..c7670423baba075368c75030b247b3f945515f29 100644 (file)
@@ -1,22 +1,14 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=vla-bound -Wall -Wno-unused-variable" } */
-
-#include <stdio.h>
+/* { dg-options "-fsanitize=vla-bound -Wall -Wno-unused-variable -fno-sanitize-recover" } */
 
 int
 main (void)
 {
-  fputs ("UBSAN TEST START\n", stderr);
-
   const int t = 0;
   struct s {
     int x;
     /* Don't instrument this one.  */
     int g[t];
   };
-
-  fputs ("UBSAN TEST END\n", stderr);
   return 0;
 }
-
-/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
index 7772857fdea95165485c0474480484fd24d5faf9..06c69393e7e48cece6f0a6fe3440863dca224daf 100644 (file)
@@ -1,7 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=vla-bound" } */
-
-#include <stdio.h>
+/* { dg-options "-fsanitize=vla-bound -fno-sanitize-recover" } */
 
 /* Don't instrument the arrays here.  */
 int
@@ -13,13 +11,7 @@ foo (int n, int a[])
 int
 main (void)
 {
-  fputs ("UBSAN TEST START\n", stderr);
-
   int a[6] = { };
   int ret = foo (3, a);
-
-  fputs ("UBSAN TEST END\n", stderr);
   return ret;
 }
-
-/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
index 8a7bbac9a7166213cb3f0cb146beba1bb1b93146..d47f26bf37f81a42d8192d9ef6ab0865eaff895a 100644 (file)
@@ -1,21 +1,13 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=vla-bound" } */
-
-#include <stdio.h>
+/* { dg-options "-fsanitize=vla-bound -fno-sanitize-recover" } */
 
 int
 main (void)
 {
-  fputs ("UBSAN TEST START\n", stderr);
-
   int x = 1;
   /* Check that the size of an array is evaluated only once.  */
   int a[++x];
   if (x != 2)
     __builtin_abort ();
-
-  fputs ("UBSAN TEST END\n", stderr);
   return 0;
 }
-
-/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
index f2b2cbd1c2fb8925c611ae2a5421d6d299493f2a..23a7b154d00f15c64f8ee088f73ab1c508db26bb 100644 (file)
@@ -1,18 +1,10 @@
-/* { dg-do run { target c++11 } } */
-/* { dg-options "-fsanitize=shift -w" } */
-
-#include <stdio.h>
+/* { dg-do run } */
+/* { dg-options "-fsanitize=shift -w -fno-sanitize-recover -std=c++11" } */
 
 int
 main (void)
 {
-  fputs ("UBSAN TEST START\n", stderr);
-
   int a = 1;
   a <<= 31;
-
-  fputs ("UBSAN TEST END\n", stderr);
   return 0;
 }
-
-/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
index 867908aef7912181354ab82c9376bfaa74133521..fbc16dfd3d8d1f27c5a128e1c4db6c7fe281d035 100644 (file)
@@ -1,5 +1,5 @@
-/* { dg-do run { target c++11 } } */
-/* { dg-options "-fsanitize=shift -w" } */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=shift -w -std=c++11" } */
 
 int
 main (void)
index ca1e922d69a4d4fac288166bfbff411e2d04de57..7023c70cea0dfa51c484b3260fbef5dc3569ee47 100644 (file)
@@ -1,5 +1,5 @@
-/* { dg-do run { target c++1y } } */
-/* { dg-options "-fsanitize=vla-bound -Wall -Wno-unused-variable" } */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=vla-bound -Wall -Wno-unused-variable -std=c++1y" } */
 /* { dg-shouldfail "ubsan" } */
 
 int
index 546f1781057955e71ac7b4273325f3ddc4e3b0ce..a1829990a811120558ddc085aa30b875a762fdfb 100644 (file)
@@ -1,7 +1,5 @@
 // { dg-do run }
-// { dg-options "-fsanitize=return" }
-
-#include <stdio.h>
+// { dg-options "-fsanitize=return -fno-sanitize-recover" }
 
 struct S { S (); ~S (); };
 
@@ -22,12 +20,6 @@ foo (int x)
 int
 main ()
 {
-  fputs ("UBSAN TEST START\n", stderr);
-
   foo (1);
   foo (14);
-
-  fputs ("UBSAN TEST END\n", stderr);
 }
-
-/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
index cf25aa3edf60476ec239642dd44ab530b4038dbd..d9d740c7cd37b6bc2b8b4de69eafff75d01eb3e5 100644 (file)
@@ -516,6 +516,9 @@ ubsan_create_data (const char *name, const location_t *ploc,
 tree
 ubsan_instrument_unreachable (location_t loc)
 {
+  if (flag_sanitize_undefined_trap_on_error)
+    return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
+
   initialize_sanitizer_builtins ();
   tree data = ubsan_create_data ("__ubsan_unreachable_data", &loc, NULL,
                                 NULL_TREE);
@@ -583,16 +586,25 @@ ubsan_expand_null_ifn (gimple_stmt_iterator gsi)
     set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
 
   /* Put the ubsan builtin call into the newly created BB.  */
-  tree fn = builtin_decl_implicit (BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH);
-  const struct ubsan_mismatch_data m
-    = { build_zero_cst (pointer_sized_int_node), ckind };
-  tree data = ubsan_create_data ("__ubsan_null_data",
-                                &loc, &m,
-                                ubsan_type_descriptor (TREE_TYPE (ptr), true),
-                                NULL_TREE);
-  data = build_fold_addr_expr_loc (loc, data);
-  gimple g = gimple_build_call (fn, 2, data,
-                               build_zero_cst (pointer_sized_int_node));
+  gimple g;
+  if (flag_sanitize_undefined_trap_on_error)
+    g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
+  else
+    {
+      enum built_in_function bcode
+       = flag_sanitize_recover
+         ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
+         : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
+      tree fn = builtin_decl_implicit (bcode);
+      const struct ubsan_mismatch_data m
+       = { build_zero_cst (pointer_sized_int_node), ckind };
+      tree data = ubsan_create_data ("__ubsan_null_data", &loc, &m,
+                                    ubsan_type_descriptor (TREE_TYPE (ptr),
+                                                           true), NULL_TREE);
+      data = build_fold_addr_expr_loc (loc, data);
+      g = gimple_build_call (fn, 2, data,
+                            build_zero_cst (pointer_sized_int_node));
+    }
   gimple_set_location (g, loc);
   gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
   gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
@@ -662,6 +674,9 @@ tree
 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
                              tree op0, tree op1)
 {
+  if (flag_sanitize_undefined_trap_on_error)
+    return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
+
   tree data = ubsan_create_data ("__ubsan_overflow_data", &loc, NULL,
                                 ubsan_type_descriptor (lhstype, false),
                                 NULL_TREE);
@@ -670,16 +685,24 @@ ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
   switch (code)
     {
     case PLUS_EXPR:
-      fn_code = BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW;
+      fn_code = flag_sanitize_recover
+               ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
+               : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
       break;
     case MINUS_EXPR:
-      fn_code = BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW;
+      fn_code = flag_sanitize_recover
+               ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
+               : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
       break;
     case MULT_EXPR:
-      fn_code = BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW;
+      fn_code = flag_sanitize_recover
+               ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
+               : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
       break;
     case NEGATE_EXPR:
-      fn_code = BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW;
+      fn_code = flag_sanitize_recover
+               ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
+               : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
       break;
     default:
       gcc_unreachable ();
@@ -844,17 +867,26 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi)
   gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs, NULL_TREE);
   update_stmt (stmt);
 
-  tree data = ubsan_create_data ("__ubsan_invalid_value_data",
-                                &loc, NULL,
-                                ubsan_type_descriptor (type, false),
-                                NULL_TREE);
-  data = build_fold_addr_expr_loc (loc, data);
-  tree fn = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE);
-
   gsi2 = gsi_after_labels (then_bb);
-  tree val = force_gimple_operand_gsi (&gsi2, ubsan_encode_value (urhs),
-                                      true, NULL_TREE, true, GSI_SAME_STMT);
-  g = gimple_build_call (fn, 2, data, val);
+  if (flag_sanitize_undefined_trap_on_error)
+    g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
+  else
+    {
+      tree data = ubsan_create_data ("__ubsan_invalid_value_data", &loc, NULL,
+                                    ubsan_type_descriptor (type, false),
+                                    NULL_TREE);
+      data = build_fold_addr_expr_loc (loc, data);
+      enum built_in_function bcode
+       = flag_sanitize_recover
+         ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
+         : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
+      tree fn = builtin_decl_explicit (bcode);
+
+      tree val = force_gimple_operand_gsi (&gsi2, ubsan_encode_value (urhs),
+                                          true, NULL_TREE, true,
+                                          GSI_SAME_STMT);
+      g = gimple_build_call (fn, 2, data, val);
+    }
   gimple_set_location (g, loc);
   gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
 }