From: Martin Liska Date: Mon, 26 Sep 2016 10:55:34 +0000 (+0200) Subject: Fix handling of -fsanitize-recover* options. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5cc6c41c2ee95585418a5820d34a4356b91dda18;p=gcc.git Fix handling of -fsanitize-recover* options. * common.opt: Exclude SANITIZE_UNREACHABLE and SANITIZE_RETURN from default sanitize recover values. * doc/invoke.texi: Fix documentation related to -fsanitize=leak, -fsanitize=address, -fsanitize=thread and -fsanitize-recover. * flag-types.h: Replace couple of 1 << x to 1UL << x, make it consistent. * opts.c (finish_options): Do a generic loop over options that can be recovered. (parse_sanitizer_options): Exclude SANITIZE_UNREACHABLE and SANITIZE_RETURN. (common_handle_option): Likewise. * opts.h: Declare can_recover to sanitizer_opts_s. * c-c++-common/ubsan/sanitize-recover-1.c: New test. * c-c++-common/ubsan/sanitize-recover-2.c: New test. * c-c++-common/ubsan/sanitize-recover-3.c: New test. * c-c++-common/ubsan/sanitize-recover-4.c: New test. * c-c++-common/ubsan/sanitize-recover-5.c: New test. * c-c++-common/ubsan/sanitize-recover-6.c: New test. * c-c++-common/ubsan/sanitize-recover-7.c: New test. * c-c++-common/ubsan/sanitize-recover-8.c: New test. * c-c++-common/ubsan/sanitize-recover-9.c: New test. From-SVN: r240491 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 12eea1b75f8..a46910dfeef 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2016-09-26 Martin Liska + + * common.opt: Exclude SANITIZE_UNREACHABLE and SANITIZE_RETURN + from default sanitize recover values. + * doc/invoke.texi: Fix documentation related to -fsanitize=leak, + -fsanitize=address, -fsanitize=thread and -fsanitize-recover. + * flag-types.h: Replace couple of 1 << x to 1UL << x, make it + consistent. + * opts.c (finish_options): Do a generic loop over options + that can be recovered. + (parse_sanitizer_options): Exclude SANITIZE_UNREACHABLE and + SANITIZE_RETURN. + (common_handle_option): Likewise. + * opts.h: Declare can_recover to sanitizer_opts_s. + 2016-09-26 Andre Vieira * target.def(elf_flags_numeric): Change documentation to diff --git a/gcc/common.opt b/gcc/common.opt index b1d32fb45a2..0e01577888d 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -228,7 +228,7 @@ unsigned int flag_sanitize ; What sanitizers should recover from errors Variable -unsigned int flag_sanitize_recover = SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT | SANITIZE_KERNEL_ADDRESS +unsigned int flag_sanitize_recover = (SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT | SANITIZE_KERNEL_ADDRESS) & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN) fsanitize-coverage=trace-pc Common Report Var(flag_sanitize_coverage) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index ce0eaef3c90..676746237e3 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -10255,6 +10255,7 @@ more details. The run-time behavior can be influenced using the the available options are shown at startup of the instrumented program. See @url{https://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags} for a list of supported options. +The option can't be combined with @option{-fsanitize=thread}. @item -fsanitize=kernel-address @opindex fsanitize=kernel-address @@ -10270,17 +10271,19 @@ details. The run-time behavior can be influenced using the @env{TSAN_OPTIONS} environment variable; see @url{https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags} for a list of supported options. +The option can't be combined with @option{-fsanitize=address} +and/or @option{-fsanitize=leak}. @item -fsanitize=leak @opindex fsanitize=leak Enable LeakSanitizer, a memory leak detector. -This option only matters for linking of executables and if neither -@option{-fsanitize=address} nor @option{-fsanitize=thread} is used. In that -case the executable is linked against a library that overrides @code{malloc} +This option only matters for linking of executables and +the executable is linked against a library that overrides @code{malloc} and other allocator functions. See @uref{https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer} for more details. The run-time behavior can be influenced using the @env{LSAN_OPTIONS} environment variable. +The option can't be combined with @option{-fsanitize=thread}. @item -fsanitize=undefined @opindex fsanitize=undefined @@ -10454,6 +10457,7 @@ and program then exits with a non-zero exit code. Currently this feature only works for @option{-fsanitize=undefined} (and its suboptions except for @option{-fsanitize=unreachable} and @option{-fsanitize=return}), @option{-fsanitize=float-cast-overflow}, @option{-fsanitize=float-divide-by-zero}, +@option{-fsanitize=bounds-strict}, @option{-fsanitize=kernel-address} and @option{-fsanitize=address}. For these sanitizers error recovery is turned on by default, except @option{-fsanitize=address}, for which this feature is experimental. @@ -10470,12 +10474,12 @@ setting the @code{halt_on_error} flag in the corresponding environment variable. Syntax without explicit @var{opts} parameter is deprecated. It is equivalent to @smallexample --fsanitize-recover=undefined,float-cast-overflow,float-divide-by-zero +-fsanitize-recover=undefined,float-cast-overflow,float-divide-by-zero,bounds-strict @end smallexample @noindent Similarly @option{-fno-sanitize-recover} is equivalent to @smallexample --fno-sanitize-recover=undefined,float-cast-overflow,float-divide-by-zero +-fno-sanitize-recover=undefined,float-cast-overflow,float-divide-by-zero,bounds-strict @end smallexample @item -fsanitize-undefined-trap-on-error diff --git a/gcc/flag-types.h b/gcc/flag-types.h index dd57e167098..816df6b4ad9 100644 --- a/gcc/flag-types.h +++ b/gcc/flag-types.h @@ -203,25 +203,25 @@ enum vect_cost_model { /* Different instrumentation modes. */ enum sanitize_code { /* AddressSanitizer. */ - SANITIZE_ADDRESS = 1 << 0, - SANITIZE_USER_ADDRESS = 1 << 1, - SANITIZE_KERNEL_ADDRESS = 1 << 2, + SANITIZE_ADDRESS = 1UL << 0, + SANITIZE_USER_ADDRESS = 1UL << 1, + SANITIZE_KERNEL_ADDRESS = 1UL << 2, /* ThreadSanitizer. */ - SANITIZE_THREAD = 1 << 3, + SANITIZE_THREAD = 1UL << 3, /* LeakSanitizer. */ - SANITIZE_LEAK = 1 << 4, + SANITIZE_LEAK = 1UL << 4, /* UndefinedBehaviorSanitizer. */ - SANITIZE_SHIFT = 1 << 5, - SANITIZE_DIVIDE = 1 << 6, - SANITIZE_UNREACHABLE = 1 << 7, - SANITIZE_VLA = 1 << 8, - SANITIZE_NULL = 1 << 9, - SANITIZE_RETURN = 1 << 10, - SANITIZE_SI_OVERFLOW = 1 << 11, - SANITIZE_BOOL = 1 << 12, - SANITIZE_ENUM = 1 << 13, - SANITIZE_FLOAT_DIVIDE = 1 << 14, - SANITIZE_FLOAT_CAST = 1 << 15, + SANITIZE_SHIFT = 1UL << 5, + SANITIZE_DIVIDE = 1UL << 6, + SANITIZE_UNREACHABLE = 1UL << 7, + SANITIZE_VLA = 1UL << 8, + SANITIZE_NULL = 1UL << 9, + SANITIZE_RETURN = 1UL << 10, + SANITIZE_SI_OVERFLOW = 1UL << 11, + SANITIZE_BOOL = 1UL << 12, + SANITIZE_ENUM = 1UL << 13, + SANITIZE_FLOAT_DIVIDE = 1UL << 14, + SANITIZE_FLOAT_CAST = 1UL << 15, SANITIZE_BOUNDS = 1UL << 16, SANITIZE_ALIGNMENT = 1UL << 17, SANITIZE_NONNULL_ATTRIBUTE = 1UL << 18, diff --git a/gcc/opts.c b/gcc/opts.c index f6259731263..45f1f89cd16 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -941,7 +941,6 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, opts->x_debug_generate_pub_sections = 2; /* Userspace and kernel ASan conflict with each other. */ - if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS) && (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS)) error_at (loc, @@ -949,20 +948,23 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, "-fsanitize=kernel-address"); /* And with TSan. */ - if ((opts->x_flag_sanitize & SANITIZE_ADDRESS) && (opts->x_flag_sanitize & SANITIZE_THREAD)) error_at (loc, "-fsanitize=address and -fsanitize=kernel-address " "are incompatible with -fsanitize=thread"); - /* Error recovery is not allowed for LSan and TSan. */ - - if (opts->x_flag_sanitize_recover & SANITIZE_THREAD) - error_at (loc, "-fsanitize-recover=thread is not supported"); + if ((opts->x_flag_sanitize & SANITIZE_LEAK) + && (opts->x_flag_sanitize & SANITIZE_THREAD)) + error_at (loc, + "-fsanitize=leak is incompatible with -fsanitize=thread"); - if (opts->x_flag_sanitize_recover & SANITIZE_LEAK) - error_at (loc, "-fsanitize-recover=leak is not supported"); + /* Check error recovery for -fsanitize-recover option. */ + for (int i = 0; sanitizer_opts[i].name != NULL; ++i) + if ((opts->x_flag_sanitize_recover & sanitizer_opts[i].flag) + && !sanitizer_opts[i].can_recover) + error_at (loc, "-fsanitize-recover=%s is not supported", + sanitizer_opts[i].name); /* When instrumenting the pointers, we don't want to remove the null pointer checks. */ @@ -1448,33 +1450,36 @@ enable_fdo_optimizations (struct gcc_options *opts, /* -f{,no-}sanitize{,-recover}= suboptions. */ const struct sanitizer_opts_s sanitizer_opts[] = { -#define SANITIZER_OPT(name, flags) { #name, flags, sizeof #name - 1 } - SANITIZER_OPT (address, SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS), - SANITIZER_OPT (kernel-address, SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS), - SANITIZER_OPT (thread, SANITIZE_THREAD), - SANITIZER_OPT (leak, SANITIZE_LEAK), - SANITIZER_OPT (shift, SANITIZE_SHIFT), - SANITIZER_OPT (integer-divide-by-zero, SANITIZE_DIVIDE), - SANITIZER_OPT (undefined, SANITIZE_UNDEFINED), - SANITIZER_OPT (unreachable, SANITIZE_UNREACHABLE), - SANITIZER_OPT (vla-bound, SANITIZE_VLA), - SANITIZER_OPT (return, SANITIZE_RETURN), - SANITIZER_OPT (null, SANITIZE_NULL), - SANITIZER_OPT (signed-integer-overflow, SANITIZE_SI_OVERFLOW), - SANITIZER_OPT (bool, SANITIZE_BOOL), - SANITIZER_OPT (enum, SANITIZE_ENUM), - SANITIZER_OPT (float-divide-by-zero, SANITIZE_FLOAT_DIVIDE), - SANITIZER_OPT (float-cast-overflow, SANITIZE_FLOAT_CAST), - SANITIZER_OPT (bounds, SANITIZE_BOUNDS), - SANITIZER_OPT (bounds-strict, SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT), - SANITIZER_OPT (alignment, SANITIZE_ALIGNMENT), - SANITIZER_OPT (nonnull-attribute, SANITIZE_NONNULL_ATTRIBUTE), - SANITIZER_OPT (returns-nonnull-attribute, SANITIZE_RETURNS_NONNULL_ATTRIBUTE), - SANITIZER_OPT (object-size, SANITIZE_OBJECT_SIZE), - SANITIZER_OPT (vptr, SANITIZE_VPTR), - SANITIZER_OPT (all, ~0U), +#define SANITIZER_OPT(name, flags, recover) \ + { #name, flags, sizeof #name - 1, recover } + SANITIZER_OPT (address, SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS, true), + SANITIZER_OPT (kernel-address, SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS, + true), + SANITIZER_OPT (thread, SANITIZE_THREAD, false), + SANITIZER_OPT (leak, SANITIZE_LEAK, false), + SANITIZER_OPT (shift, SANITIZE_SHIFT, true), + SANITIZER_OPT (integer-divide-by-zero, SANITIZE_DIVIDE, true), + SANITIZER_OPT (undefined, SANITIZE_UNDEFINED, true), + SANITIZER_OPT (unreachable, SANITIZE_UNREACHABLE, false), + SANITIZER_OPT (vla-bound, SANITIZE_VLA, true), + SANITIZER_OPT (return, SANITIZE_RETURN, false), + SANITIZER_OPT (null, SANITIZE_NULL, true), + SANITIZER_OPT (signed-integer-overflow, SANITIZE_SI_OVERFLOW, true), + SANITIZER_OPT (bool, SANITIZE_BOOL, true), + SANITIZER_OPT (enum, SANITIZE_ENUM, true), + SANITIZER_OPT (float-divide-by-zero, SANITIZE_FLOAT_DIVIDE, true), + SANITIZER_OPT (float-cast-overflow, SANITIZE_FLOAT_CAST, true), + SANITIZER_OPT (bounds, SANITIZE_BOUNDS, true), + SANITIZER_OPT (bounds-strict, SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT, true), + SANITIZER_OPT (alignment, SANITIZE_ALIGNMENT, true), + SANITIZER_OPT (nonnull-attribute, SANITIZE_NONNULL_ATTRIBUTE, true), + SANITIZER_OPT (returns-nonnull-attribute, SANITIZE_RETURNS_NONNULL_ATTRIBUTE, + true), + SANITIZER_OPT (object-size, SANITIZE_OBJECT_SIZE, true), + SANITIZER_OPT (vptr, SANITIZE_VPTR, true), + SANITIZER_OPT (all, ~0U, true), #undef SANITIZER_OPT - { NULL, 0U, 0UL } + { NULL, 0U, 0UL, false } }; /* Parse comma separated sanitizer suboptions from P for option SCODE, @@ -1516,11 +1521,20 @@ parse_sanitizer_options (const char *p, location_t loc, int scode, error_at (loc, "-fsanitize=all option is not valid"); } else - flags |= ~(SANITIZE_USER_ADDRESS | SANITIZE_THREAD - | SANITIZE_LEAK); + flags |= ~(SANITIZE_THREAD | SANITIZE_LEAK + | SANITIZE_UNREACHABLE | SANITIZE_RETURN); } else if (value) - flags |= sanitizer_opts[i].flag; + { + /* Do not enable -fsanitize-recover=unreachable and + -fsanitize-recover=return if -fsanitize-recover=undefined + is selected. */ + if (sanitizer_opts[i].flag == SANITIZE_UNDEFINED) + flags |= (SANITIZE_UNDEFINED + & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN)); + else + flags |= sanitizer_opts[i].flag; + } else flags &= ~sanitizer_opts[i].flag; found = true; @@ -1770,7 +1784,8 @@ common_handle_option (struct gcc_options *opts, case OPT_fsanitize_recover: if (value) opts->x_flag_sanitize_recover - |= SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT; + |= (SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT) + & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN); else opts->x_flag_sanitize_recover &= ~(SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT); diff --git a/gcc/opts.h b/gcc/opts.h index 4132432bd7c..b3e64353c8a 100644 --- a/gcc/opts.h +++ b/gcc/opts.h @@ -414,6 +414,7 @@ extern const struct sanitizer_opts_s const char *const name; unsigned int flag; size_t len; + bool can_recover; } sanitizer_opts[]; extern void add_misspelling_candidates (auto_vec *candidates, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2dd006e1940..f8567e1a53c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2016-09-26 Martin Liska + + * c-c++-common/ubsan/sanitize-recover-1.c: New test. + * c-c++-common/ubsan/sanitize-recover-2.c: New test. + * c-c++-common/ubsan/sanitize-recover-3.c: New test. + * c-c++-common/ubsan/sanitize-recover-4.c: New test. + * c-c++-common/ubsan/sanitize-recover-5.c: New test. + * c-c++-common/ubsan/sanitize-recover-6.c: New test. + * c-c++-common/ubsan/sanitize-recover-7.c: New test. + * c-c++-common/ubsan/sanitize-recover-8.c: New test. + * c-c++-common/ubsan/sanitize-recover-9.c: New test. + 2016-09-26 Marek Polacek PR c/7652 diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-1.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-1.c new file mode 100644 index 00000000000..4d8c27e945a --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-1.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize-recover=unreachable" } */ + +int i; + +/* { dg-error "-fsanitize-recover=unreachable is not supported" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-2.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-2.c new file mode 100644 index 00000000000..e9849bd50ab --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-2.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize-recover=return" } */ + +int i; + +/* { dg-error "-fsanitize-recover=return is not supported" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-3.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-3.c new file mode 100644 index 00000000000..844f3fde018 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-3.c @@ -0,0 +1,4 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize-recover=all" } */ + +int i; diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-4.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-4.c new file mode 100644 index 00000000000..45fa5b9a00f --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-4.c @@ -0,0 +1,4 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize-recover=undefined" } */ + +int i; diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-5.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-5.c new file mode 100644 index 00000000000..9c1ed322d5e --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-5.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize-recover=undefined,unreachable" } */ + +int i; + +/* { dg-error "-fsanitize-recover=unreachable is not supported" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-6.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-6.c new file mode 100644 index 00000000000..e309e1b71c0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-6.c @@ -0,0 +1,4 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize-recover=undefined,unreachable -fno-sanitize-recover=unreachable" } */ + +int i; diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c new file mode 100644 index 00000000000..2e6599fe312 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=address -fsanitize=thread" } */ + +int i; + +/* { dg-error "-fsanitize=address and -fsanitize=kernel-address are incompatible with -fsanitize=thread" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-8.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-8.c new file mode 100644 index 00000000000..ecaf0e648af --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-8.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=leak -fsanitize=thread" } */ + +int i; + +/* { dg-error "-fsanitize=leak is incompatible with -fsanitize=thread" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-9.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-9.c new file mode 100644 index 00000000000..ef80ef1e27d --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-9.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize-recover=unreachable -fsanitize-recover=undefined" } */ + +int i; + +/* { dg-error "-fsanitize-recover=unreachable is not supported" "" { target *-*-* } 0 } */