Commit 1c33c9b7 by Jakub Jelinek Committed by Jakub Jelinek

re PR sanitizer/60275 ([UBSAN] Add…

re PR sanitizer/60275 ([UBSAN] Add -f[no-]sanitize-recover/-fsanitize-undefined-trap-on-error to make UBSAN's runtime errors fatal)

	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
parent 5e66b2e5
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> 2014-04-22 Christian Bruel <christian.bruel@st.com>
* config/sh/sh.md (mov<mode>): Replace movQIHI. * config/sh/sh.md (mov<mode>): Replace movQIHI.
......
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> 2014-04-22 Marc Glisse <marc.glisse@inria.fr>
PR libstdc++/43622 PR libstdc++/43622
......
...@@ -73,14 +73,22 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1) ...@@ -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 /* In case we have a SAVE_EXPR in a conditional context, we need to
make sure it gets evaluated before the condition. */ make sure it gets evaluated before the condition. */
t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t); t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
tree data = ubsan_create_data ("__ubsan_overflow_data", if (flag_sanitize_undefined_trap_on_error)
&loc, NULL, 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), ubsan_type_descriptor (type, false),
NULL_TREE); NULL_TREE);
data = build_fold_addr_expr_loc (loc, data); data = build_fold_addr_expr_loc (loc, data);
tt = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW); 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), tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
ubsan_encode_value (op1)); ubsan_encode_value (op1));
}
t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node); t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node);
return t; return t;
...@@ -142,19 +150,28 @@ ubsan_instrument_shift (location_t loc, enum tree_code code, ...@@ -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 /* In case we have a SAVE_EXPR in a conditional context, we need to
make sure it gets evaluated before the condition. */ make sure it gets evaluated before the condition. */
t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t); t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
tree data = ubsan_create_data ("__ubsan_shift_data", t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t,
&loc, NULL, tt ? tt : integer_zero_node);
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 (type0, false),
ubsan_type_descriptor (type1, false), ubsan_type_descriptor (type1, false),
NULL_TREE); NULL_TREE);
data = build_fold_addr_expr_loc (loc, data); data = build_fold_addr_expr_loc (loc, data);
t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, enum built_in_function bcode
tt ? tt : integer_zero_node); = flag_sanitize_recover
tt = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS); ? 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), tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
ubsan_encode_value (op1)); ubsan_encode_value (op1));
}
t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node); t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node);
return t; return t;
...@@ -169,13 +186,21 @@ ubsan_instrument_vla (location_t loc, tree size) ...@@ -169,13 +186,21 @@ ubsan_instrument_vla (location_t loc, tree size)
tree t, tt; tree t, tt;
t = fold_build2 (LE_EXPR, boolean_type_node, size, build_int_cst (type, 0)); t = fold_build2 (LE_EXPR, boolean_type_node, size, build_int_cst (type, 0));
tree data = ubsan_create_data ("__ubsan_vla_data", if (flag_sanitize_undefined_trap_on_error)
&loc, NULL, 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), ubsan_type_descriptor (type, false),
NULL_TREE); NULL_TREE);
data = build_fold_addr_expr_loc (loc, data); data = build_fold_addr_expr_loc (loc, data);
tt = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE); 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)); 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); t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node);
return t; return t;
...@@ -186,6 +211,8 @@ ubsan_instrument_vla (location_t loc, tree size) ...@@ -186,6 +211,8 @@ ubsan_instrument_vla (location_t loc, tree size)
tree tree
ubsan_instrument_return (location_t loc) 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 /* It is possible that PCH zapped table with definitions of sanitizer
builtins. Reinitialize them if needed. */ builtins. Reinitialize them if needed. */
initialize_sanitizer_builtins (); initialize_sanitizer_builtins ();
......
...@@ -862,6 +862,14 @@ fsanitize= ...@@ -862,6 +862,14 @@ fsanitize=
Common Driver Report Joined Common Driver Report Joined
Select what to sanitize 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 fasynchronous-unwind-tables
Common Report Var(flag_asynchronous_unwind_tables) Optimization Common Report Var(flag_asynchronous_unwind_tables) Optimization
Generate unwind tables that are exact at each instruction boundary Generate unwind tables that are exact at each instruction boundary
......
...@@ -288,7 +288,8 @@ Objective-C and Objective-C++ Dialects}. ...@@ -288,7 +288,8 @@ Objective-C and Objective-C++ Dialects}.
@item Debugging Options @item Debugging Options
@xref{Debugging Options,,Options for Debugging Your Program or GCC}. @xref{Debugging Options,,Options for Debugging Your Program or GCC}.
@gccoptlist{-d@var{letters} -dumpspecs -dumpmachine -dumpversion @gol @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 -fdbg-cnt-list -fdbg-cnt=@var{counter-value-list} @gol
-fdisable-ipa-@var{pass_name} @gol -fdisable-ipa-@var{pass_name} @gol
-fdisable-rtl-@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, ...@@ -5380,6 +5381,26 @@ While @option{-ftrapv} causes traps for signed overflows to be emitted,
@option{-fsanitize=undefined} gives a diagnostic message. @option{-fsanitize=undefined} gives a diagnostic message.
This currently works only for the C family of languages. 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{]} @item -fdump-final-insns@r{[}=@var{file}@r{]}
@opindex fdump-final-insns @opindex fdump-final-insns
Dump the final internal representation (RTL) to @var{file}. If the Dump the final internal representation (RTL) to @var{file}. If the
......
...@@ -8170,7 +8170,8 @@ sanitize_spec_function (int argc, const char **argv) ...@@ -8170,7 +8170,8 @@ sanitize_spec_function (int argc, const char **argv)
if (strcmp (argv[0], "thread") == 0) if (strcmp (argv[0], "thread") == 0)
return (flag_sanitize & SANITIZE_THREAD) ? "" : NULL; return (flag_sanitize & SANITIZE_THREAD) ? "" : NULL;
if (strcmp (argv[0], "undefined") == 0) 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) if (strcmp (argv[0], "leak") == 0)
return ((flag_sanitize return ((flag_sanitize
& (SANITIZE_ADDRESS | SANITIZE_LEAK | SANITIZE_THREAD)) & (SANITIZE_ADDRESS | SANITIZE_LEAK | SANITIZE_THREAD))
......
...@@ -335,3 +335,39 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE, ...@@ -335,3 +335,39 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE,
"__ubsan_handle_load_invalid_value", "__ubsan_handle_load_invalid_value",
BT_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR,
ATTR_COLD_NOTHROW_LEAF_LIST) 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)
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> 2014-04-22 Christian Bruel <christian.bruel@st.com>
* gcc.target/sh/hiconst.c: New test. * gcc.target/sh/hiconst.c: New test.
......
/* { 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" } */
/* { 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" } */
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-fsanitize=signed-integer-overflow" } */ /* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover" } */
#include <stdio.h>
#ifndef ASM1 #ifndef ASM1
# define ASM1(a) /* Nothing */ # define ASM1(a) /* Nothing */
...@@ -53,8 +51,6 @@ ...@@ -53,8 +51,6 @@
int int
main (void) main (void)
{ {
fputs ("UBSAN TEST START\n", stderr);
CHECK (FN1 (char, char, +), 23); CHECK (FN1 (char, char, +), 23);
CHECK (FN1 (char, char, -), 5); CHECK (FN1 (char, char, -), 5);
CHECK (FN1 (char, char, *), 126); CHECK (FN1 (char, char, *), 126);
...@@ -261,9 +257,5 @@ main (void) ...@@ -261,9 +257,5 @@ main (void)
CHECK (FN5 (unsigned long int), -77); CHECK (FN5 (unsigned long int), -77);
CHECK (FN5 (long long int), -77); CHECK (FN5 (long long int), -77);
CHECK (FN5 (unsigned long long int), -77); CHECK (FN5 (unsigned long long int), -77);
fputs ("UBSAN TEST END\n", stderr);
return 0; return 0;
} }
/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable" } */ /* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
#include <stdio.h>
#define SCHAR_MAX __SCHAR_MAX__ #define SCHAR_MAX __SCHAR_MAX__
#define SHRT_MAX __SHRT_MAX__ #define SHRT_MAX __SHRT_MAX__
...@@ -18,8 +16,6 @@ check (int i, int j) ...@@ -18,8 +16,6 @@ check (int i, int j)
int int
main (void) main (void)
{ {
fputs ("UBSAN TEST START\n", stderr);
#if __INT_MAX__ == 2147483647 #if __INT_MAX__ == 2147483647
/* Here, nothing should fail. */ /* Here, nothing should fail. */
volatile int j = INT_MAX; volatile int j = INT_MAX;
...@@ -59,9 +55,5 @@ main (void) ...@@ -59,9 +55,5 @@ main (void)
d++; d++;
check (d, -32768); check (d, -32768);
#endif #endif
fputs ("UBSAN TEST END\n", stderr);
return 0; return 0;
} }
/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
/* { 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'" } */
/* { 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;
}
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable" } */ /* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
#include <stdio.h>
#define SCHAR_MAX __SCHAR_MAX__ #define SCHAR_MAX __SCHAR_MAX__
#define SHRT_MAX __SHRT_MAX__ #define SHRT_MAX __SHRT_MAX__
...@@ -18,8 +16,6 @@ check (int i, int j) ...@@ -18,8 +16,6 @@ check (int i, int j)
int int
main (void) main (void)
{ {
fputs ("UBSAN TEST START\n", stderr);
/* Test integer promotion. */ /* Test integer promotion. */
#if __SCHAR_MAX__ == 127 #if __SCHAR_MAX__ == 127
volatile signed char a = -2; volatile signed char a = -2;
...@@ -45,9 +41,5 @@ main (void) ...@@ -45,9 +41,5 @@ main (void)
o = m * n; o = m * n;
check (o, INT_MIN); check (o, INT_MIN);
#endif #endif
fputs ("UBSAN TEST END\n", stderr);
return 0; return 0;
} }
/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-fsanitize=signed-integer-overflow" } */ /* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover" } */
#include <stdio.h>
__attribute__((noinline, noclone)) long long __attribute__((noinline, noclone)) long long
mul (long long x, long long y) mul (long long x, long long y)
...@@ -31,16 +29,10 @@ long long tab[] = { ...@@ -31,16 +29,10 @@ long long tab[] = {
int int
main () main ()
{ {
fputs ("UBSAN TEST START\n", stderr);
unsigned int i; unsigned int i;
for (i = 0; i < sizeof (tab) / sizeof (long long); i += 3) for (i = 0; i < sizeof (tab) / sizeof (long long); i += 3)
if (mul (tab[i], tab[i + 1]) != tab[i + 2] if (mul (tab[i], tab[i + 1]) != tab[i + 2]
|| mul (tab[i + 1], tab[i]) != tab[i + 2]) || mul (tab[i + 1], tab[i]) != tab[i + 2])
__builtin_abort (); __builtin_abort ();
fputs ("UBSAN TEST END\n", stderr);
return 0; return 0;
} }
/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable" } */ /* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
#include <stdio.h>
#define SCHAR_MIN (-__SCHAR_MAX__ - 1) #define SCHAR_MIN (-__SCHAR_MAX__ - 1)
#define SHRT_MIN (-__SHRT_MAX__ - 1) #define SHRT_MIN (-__SHRT_MAX__ - 1)
...@@ -14,8 +12,6 @@ ...@@ -14,8 +12,6 @@
int int
main (void) main (void)
{ {
fputs ("UBSAN TEST START\n", stderr);
volatile signed char c = -SCHAR_MIN; volatile signed char c = -SCHAR_MIN;
CHECK (c, -128); CHECK (c, -128);
...@@ -37,9 +33,5 @@ main (void) ...@@ -37,9 +33,5 @@ main (void)
volatile long long lli = LLONG_MIN; volatile long long lli = LLONG_MIN;
lli = -(unsigned long long) lli; lli = -(unsigned long long) lli;
CHECK (lli, -0x8000000000000000L); CHECK (lli, -0x8000000000000000L);
fputs ("UBSAN TEST END\n", stderr);
return 0; return 0;
} }
/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable" } */ /* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable -fno-sanitize-recover" } */
#include <stdio.h>
#define SCHAR_MAX __SCHAR_MAX__ #define SCHAR_MAX __SCHAR_MAX__
#define SCHAR_MIN (-__SCHAR_MAX__ - 1) #define SCHAR_MIN (-__SCHAR_MAX__ - 1)
...@@ -20,8 +18,6 @@ check (int i, int j) ...@@ -20,8 +18,6 @@ check (int i, int j)
int int
main (void) main (void)
{ {
fputs ("UBSAN TEST START\n", stderr);
#if __INT_MAX__ == 2147483647 #if __INT_MAX__ == 2147483647
/* Here, nothing should fail. */ /* Here, nothing should fail. */
volatile int i = -1; volatile int i = -1;
...@@ -61,9 +57,5 @@ main (void) ...@@ -61,9 +57,5 @@ main (void)
d--; d--;
check (d, 32767); check (d, 32767);
#endif #endif
fputs ("UBSAN TEST END\n", stderr);
return 0; return 0;
} }
/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-fsanitize=signed-integer-overflow" } */ /* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover" } */
#include <stdio.h>
int int
main (void) main (void)
{ {
fputs ("UBSAN TEST START\n", stderr);
long long int a = 14; long long int a = 14;
long int b = 9; long int b = 9;
asm volatile ("" : "+r" (a), "+r" (b)); asm volatile ("" : "+r" (a), "+r" (b));
if ((a - b) != 5) if ((a - b) != 5)
__builtin_abort (); __builtin_abort ();
fputs ("UBSAN TEST END\n", stderr);
return 0; return 0;
} }
/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
/* PR sanitizer/60613 */ /* PR sanitizer/60613 */
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-fsanitize=undefined" } */ /* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
#include <stdio.h>
long long y; long long y;
...@@ -26,16 +24,10 @@ bar (long long x) ...@@ -26,16 +24,10 @@ bar (long long x)
int int
main () main ()
{ {
fputs ("UBSAN TEST START\n", stderr);
y = 1; y = 1;
if (foo (8 - 2040) != 8 - 1) if (foo (8 - 2040) != 8 - 1)
__builtin_abort (); __builtin_abort ();
if (bar (1) != 8 - 1) if (bar (1) != 8 - 1)
__builtin_abort (); __builtin_abort ();
fputs ("UBSAN TEST END\n", stderr);
return 0; return 0;
} }
/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-fsanitize=shift -Wall -Werror -O" } */ /* { dg-options "-fsanitize=shift -Wall -Werror -O -fno-sanitize-recover" } */
#include <stdio.h>
static int x; static int x;
int int
main (void) main (void)
{ {
fputs ("UBSAN TEST START\n", stderr);
int o = 1; int o = 1;
int y = x << o; int y = x << o;
fputs ("UBSAN TEST END\n", stderr);
return y; return y;
} }
/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-fsanitize=shift -w" } */ /* { dg-options "-fsanitize=shift -w -fno-sanitize-recover" } */
#include <stdio.h>
int int
main (void) main (void)
{ {
fputs ("UBSAN TEST START\n", stderr);
unsigned int a = 1; unsigned int a = 1;
a <<= 31; a <<= 31;
a <<= 1; a <<= 1;
fputs ("UBSAN TEST END\n", stderr);
return 0; return 0;
} }
/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
/* PR sanitizer/58413 */ /* PR sanitizer/58413 */
/* { dg-do run { target int32plus } } */ /* { dg-do run { target int32plus } } */
/* { dg-options "-fsanitize=shift -w" } */ /* { dg-options "-fsanitize=shift -w -fno-sanitize-recover" } */
#include <stdio.h>
int x = 7; int x = 7;
int int
main (void) main (void)
{ {
fputs ("UBSAN TEST START\n", stderr);
/* All of the following should pass. */ /* All of the following should pass. */
int A[128 >> 5] = {}; int A[128 >> 5] = {};
int B[128 << 5] = {}; int B[128 << 5] = {};
...@@ -30,9 +26,5 @@ main (void) ...@@ -30,9 +26,5 @@ main (void)
case 128 >> (4 + 1): case 128 >> (4 + 1):
return 1; return 1;
} }
fputs ("UBSAN TEST END\n", stderr);
return 0; return 0;
} }
/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-fsanitize=undefined" } */ /* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
#include <stdio.h>
int int
foo (int x, int y) foo (int x, int y)
...@@ -21,13 +19,7 @@ bar (int x, int y) ...@@ -21,13 +19,7 @@ bar (int x, int y)
int int
main (void) main (void)
{ {
fputs ("UBSAN TEST START\n", stderr);
foo (3, 2); foo (3, 2);
bar (12, 42); bar (12, 42);
fputs ("UBSAN TEST END\n", stderr);
return 0; return 0;
} }
/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-fsanitize=vla-bound -Wall -Wno-unused-variable" } */ /* { dg-options "-fsanitize=vla-bound -Wall -Wno-unused-variable -fno-sanitize-recover" } */
#include <stdio.h>
int int
main (void) main (void)
{ {
fputs ("UBSAN TEST START\n", stderr);
const int t = 0; const int t = 0;
struct s { struct s {
int x; int x;
/* Don't instrument this one. */ /* Don't instrument this one. */
int g[t]; int g[t];
}; };
fputs ("UBSAN TEST END\n", stderr);
return 0; return 0;
} }
/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-fsanitize=vla-bound" } */ /* { dg-options "-fsanitize=vla-bound -fno-sanitize-recover" } */
#include <stdio.h>
/* Don't instrument the arrays here. */ /* Don't instrument the arrays here. */
int int
...@@ -13,13 +11,7 @@ foo (int n, int a[]) ...@@ -13,13 +11,7 @@ foo (int n, int a[])
int int
main (void) main (void)
{ {
fputs ("UBSAN TEST START\n", stderr);
int a[6] = { }; int a[6] = { };
int ret = foo (3, a); int ret = foo (3, a);
fputs ("UBSAN TEST END\n", stderr);
return ret; return ret;
} }
/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-fsanitize=vla-bound" } */ /* { dg-options "-fsanitize=vla-bound -fno-sanitize-recover" } */
#include <stdio.h>
int int
main (void) main (void)
{ {
fputs ("UBSAN TEST START\n", stderr);
int x = 1; int x = 1;
/* Check that the size of an array is evaluated only once. */ /* Check that the size of an array is evaluated only once. */
int a[++x]; int a[++x];
if (x != 2) if (x != 2)
__builtin_abort (); __builtin_abort ();
fputs ("UBSAN TEST END\n", stderr);
return 0; return 0;
} }
/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
/* { dg-do run { target c++11 } } */ /* { dg-do run } */
/* { dg-options "-fsanitize=shift -w" } */ /* { dg-options "-fsanitize=shift -w -fno-sanitize-recover -std=c++11" } */
#include <stdio.h>
int int
main (void) main (void)
{ {
fputs ("UBSAN TEST START\n", stderr);
int a = 1; int a = 1;
a <<= 31; a <<= 31;
fputs ("UBSAN TEST END\n", stderr);
return 0; return 0;
} }
/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
/* { dg-do run { target c++11 } } */ /* { dg-do run } */
/* { dg-options "-fsanitize=shift -w" } */ /* { dg-options "-fsanitize=shift -w -std=c++11" } */
int int
main (void) main (void)
......
/* { dg-do run { target c++1y } } */ /* { dg-do run } */
/* { dg-options "-fsanitize=vla-bound -Wall -Wno-unused-variable" } */ /* { dg-options "-fsanitize=vla-bound -Wall -Wno-unused-variable -std=c++1y" } */
/* { dg-shouldfail "ubsan" } */ /* { dg-shouldfail "ubsan" } */
int int
......
// { dg-do run } // { dg-do run }
// { dg-options "-fsanitize=return" } // { dg-options "-fsanitize=return -fno-sanitize-recover" }
#include <stdio.h>
struct S { S (); ~S (); }; struct S { S (); ~S (); };
...@@ -22,12 +20,6 @@ foo (int x) ...@@ -22,12 +20,6 @@ foo (int x)
int int
main () main ()
{ {
fputs ("UBSAN TEST START\n", stderr);
foo (1); foo (1);
foo (14); foo (14);
fputs ("UBSAN TEST END\n", stderr);
} }
/* { dg-output "UBSAN TEST START(\n|\r\n|\r)UBSAN TEST END" } */
...@@ -516,6 +516,9 @@ ubsan_create_data (const char *name, const location_t *ploc, ...@@ -516,6 +516,9 @@ ubsan_create_data (const char *name, const location_t *ploc,
tree tree
ubsan_instrument_unreachable (location_t loc) 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 (); initialize_sanitizer_builtins ();
tree data = ubsan_create_data ("__ubsan_unreachable_data", &loc, NULL, tree data = ubsan_create_data ("__ubsan_unreachable_data", &loc, NULL,
NULL_TREE); NULL_TREE);
...@@ -583,16 +586,25 @@ ubsan_expand_null_ifn (gimple_stmt_iterator gsi) ...@@ -583,16 +586,25 @@ ubsan_expand_null_ifn (gimple_stmt_iterator gsi)
set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb); set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
/* Put the ubsan builtin call into the newly created BB. */ /* Put the ubsan builtin call into the newly created BB. */
tree fn = builtin_decl_implicit (BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH); 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 const struct ubsan_mismatch_data m
= { build_zero_cst (pointer_sized_int_node), ckind }; = { build_zero_cst (pointer_sized_int_node), ckind };
tree data = ubsan_create_data ("__ubsan_null_data", tree data = ubsan_create_data ("__ubsan_null_data", &loc, &m,
&loc, &m, ubsan_type_descriptor (TREE_TYPE (ptr),
ubsan_type_descriptor (TREE_TYPE (ptr), true), true), NULL_TREE);
NULL_TREE);
data = build_fold_addr_expr_loc (loc, data); data = build_fold_addr_expr_loc (loc, data);
gimple g = gimple_build_call (fn, 2, data, g = gimple_build_call (fn, 2, data,
build_zero_cst (pointer_sized_int_node)); build_zero_cst (pointer_sized_int_node));
}
gimple_set_location (g, loc); gimple_set_location (g, loc);
gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb); gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
gsi_insert_after (&gsi2, g, GSI_NEW_STMT); gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
...@@ -662,6 +674,9 @@ tree ...@@ -662,6 +674,9 @@ tree
ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype, ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
tree op0, tree op1) 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, tree data = ubsan_create_data ("__ubsan_overflow_data", &loc, NULL,
ubsan_type_descriptor (lhstype, false), ubsan_type_descriptor (lhstype, false),
NULL_TREE); NULL_TREE);
...@@ -670,16 +685,24 @@ ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype, ...@@ -670,16 +685,24 @@ ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
switch (code) switch (code)
{ {
case PLUS_EXPR: 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; break;
case MINUS_EXPR: 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; break;
case MULT_EXPR: 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; break;
case NEGATE_EXPR: 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; break;
default: default:
gcc_unreachable (); gcc_unreachable ();
...@@ -844,17 +867,26 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi) ...@@ -844,17 +867,26 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi)
gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs, NULL_TREE); gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs, NULL_TREE);
update_stmt (stmt); update_stmt (stmt);
tree data = ubsan_create_data ("__ubsan_invalid_value_data", gsi2 = gsi_after_labels (then_bb);
&loc, NULL, 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), ubsan_type_descriptor (type, false),
NULL_TREE); NULL_TREE);
data = build_fold_addr_expr_loc (loc, data); data = build_fold_addr_expr_loc (loc, data);
tree fn = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE); 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);
gsi2 = gsi_after_labels (then_bb);
tree val = force_gimple_operand_gsi (&gsi2, ubsan_encode_value (urhs), tree val = force_gimple_operand_gsi (&gsi2, ubsan_encode_value (urhs),
true, NULL_TREE, true, GSI_SAME_STMT); true, NULL_TREE, true,
GSI_SAME_STMT);
g = gimple_build_call (fn, 2, data, val); g = gimple_build_call (fn, 2, data, val);
}
gimple_set_location (g, loc); gimple_set_location (g, loc);
gsi_insert_before (&gsi2, g, GSI_SAME_STMT); gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment