diff options
Diffstat (limited to 'gcc')
32 files changed, 389 insertions, 210 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 61987af..1098089 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 66158ca..11b4bc4 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -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 diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c index e89ebc1..e4f6f32 100644 --- a/gcc/c-family/c-ubsan.c +++ b/gcc/c-family/c-ubsan.c @@ -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 (); diff --git a/gcc/common.opt b/gcc/common.opt index da275e5..d46d4c7 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -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 diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 7d03909..c5572b6 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -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 @@ -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)) diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def index 015b1d8..6184b5a 100644 --- a/gcc/sanitizer.def +++ b/gcc/sanitizer.def @@ -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) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 69a5667..abbd1cf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..27a18bb --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-6.c @@ -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 index 0000000..b65a0bc --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c @@ -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" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-1.c b/gcc/testsuite/c-c++-common/ubsan/overflow-1.c index 6819955..b0ef259 100644 --- a/gcc/testsuite/c-c++-common/ubsan/overflow-1.c +++ b/gcc/testsuite/c-c++-common/ubsan/overflow-1.c @@ -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" } */ 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 fd6c6d3..b009f5b 100644 --- a/gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c +++ b/gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c @@ -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 index 0000000..6475d10 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/overflow-add-3.c @@ -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 index 0000000..3f6f6bd --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/overflow-add-4.c @@ -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; +} 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 afb1a25..22ea639 100644 --- a/gcc/testsuite/c-c++-common/ubsan/overflow-mul-1.c +++ b/gcc/testsuite/c-c++-common/ubsan/overflow-mul-1.c @@ -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" } */ 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 037609b..896c0bc 100644 --- a/gcc/testsuite/c-c++-common/ubsan/overflow-mul-3.c +++ b/gcc/testsuite/c-c++-common/ubsan/overflow-mul-3.c @@ -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" } */ 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 6a4f288..8b5ffa5 100644 --- a/gcc/testsuite/c-c++-common/ubsan/overflow-negate-2.c +++ b/gcc/testsuite/c-c++-common/ubsan/overflow-negate-2.c @@ -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" } */ 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 15f0445..2b10f9e 100644 --- a/gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c +++ b/gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c @@ -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" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/pr59503.c b/gcc/testsuite/c-c++-common/ubsan/pr59503.c index 1637f01..81447d7 100644 --- a/gcc/testsuite/c-c++-common/ubsan/pr59503.c +++ b/gcc/testsuite/c-c++-common/ubsan/pr59503.c @@ -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" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/pr60613-1.c b/gcc/testsuite/c-c++-common/ubsan/pr60613-1.c index 6794532..4c0810b 100644 --- a/gcc/testsuite/c-c++-common/ubsan/pr60613-1.c +++ b/gcc/testsuite/c-c++-common/ubsan/pr60613-1.c @@ -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" } */ 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 19b1eb0..89ac58c 100644 --- a/gcc/testsuite/c-c++-common/ubsan/save-expr-1.c +++ b/gcc/testsuite/c-c++-common/ubsan/save-expr-1.c @@ -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" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/shift-3.c b/gcc/testsuite/c-c++-common/ubsan/shift-3.c index 65ee5d8..67f1b69 100644 --- a/gcc/testsuite/c-c++-common/ubsan/shift-3.c +++ b/gcc/testsuite/c-c++-common/ubsan/shift-3.c @@ -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" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/shift-6.c b/gcc/testsuite/c-c++-common/ubsan/shift-6.c index d88a429..e26e684 100644 --- a/gcc/testsuite/c-c++-common/ubsan/shift-6.c +++ b/gcc/testsuite/c-c++-common/ubsan/shift-6.c @@ -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" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/undefined-1.c b/gcc/testsuite/c-c++-common/ubsan/undefined-1.c index d1b9ce7..201818d 100644 --- a/gcc/testsuite/c-c++-common/ubsan/undefined-1.c +++ b/gcc/testsuite/c-c++-common/ubsan/undefined-1.c @@ -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" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-2.c b/gcc/testsuite/c-c++-common/ubsan/vla-2.c index a11e4e7..c767042 100644 --- a/gcc/testsuite/c-c++-common/ubsan/vla-2.c +++ b/gcc/testsuite/c-c++-common/ubsan/vla-2.c @@ -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" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-3.c b/gcc/testsuite/c-c++-common/ubsan/vla-3.c index 7772857..06c6939 100644 --- a/gcc/testsuite/c-c++-common/ubsan/vla-3.c +++ b/gcc/testsuite/c-c++-common/ubsan/vla-3.c @@ -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" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-4.c b/gcc/testsuite/c-c++-common/ubsan/vla-4.c index 8a7bbac..d47f26b 100644 --- a/gcc/testsuite/c-c++-common/ubsan/vla-4.c +++ b/gcc/testsuite/c-c++-common/ubsan/vla-4.c @@ -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" } */ diff --git a/gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C b/gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C index f2b2cbd..23a7b15 100644 --- a/gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C +++ b/gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C @@ -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" } */ diff --git a/gcc/testsuite/g++.dg/ubsan/cxx11-shift-2.C b/gcc/testsuite/g++.dg/ubsan/cxx11-shift-2.C index 867908a..fbc16df 100644 --- a/gcc/testsuite/g++.dg/ubsan/cxx11-shift-2.C +++ b/gcc/testsuite/g++.dg/ubsan/cxx11-shift-2.C @@ -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) diff --git a/gcc/testsuite/g++.dg/ubsan/cxx1y-vla.C b/gcc/testsuite/g++.dg/ubsan/cxx1y-vla.C index ca1e922..7023c70 100644 --- a/gcc/testsuite/g++.dg/ubsan/cxx1y-vla.C +++ b/gcc/testsuite/g++.dg/ubsan/cxx1y-vla.C @@ -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 diff --git a/gcc/testsuite/g++.dg/ubsan/return-2.C b/gcc/testsuite/g++.dg/ubsan/return-2.C index 546f178..a182999 100644 --- a/gcc/testsuite/g++.dg/ubsan/return-2.C +++ b/gcc/testsuite/g++.dg/ubsan/return-2.C @@ -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" } */ diff --git a/gcc/ubsan.c b/gcc/ubsan.c index cf25aa3..d9d740c 100644 --- a/gcc/ubsan.c +++ b/gcc/ubsan.c @@ -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); } |