From patchwork Fri Sep 23 11:53:48 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Martin_Li=C5=A1ka?= X-Patchwork-Id: 674040 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3sgWx21GCJz9t0q for ; Fri, 23 Sep 2016 21:54:12 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=eYIFcdo6; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to:cc :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=uLS2k2BbLChjh0Etg1ryRocA/Vk+fYPaRCjsklpoSeVe5alcpq 8XYPg/6CyVWBw4hobB0YqTmWAXEABMPWxJvcsMUkfNhXgeLlMqmrvLDcp/z0jyju M9D9lPoFo3ulfXnOh3fsDFV5FafSgQzr9aArMaTF08MMlgitZkah3zfdk= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to:cc :from:subject:message-id:date:mime-version:content-type; s= default; bh=rFxAJUcqtWiKfUrT/aQHRid/g44=; b=eYIFcdo6pTeXWJHG1Ztx /D0PykSBEFi+S+dLTSLBpT+eHKetVAWEQRMQ67l8aygSdFhBh5a3zI0JcBEKd3E7 yi0SgS2E2NX8TeXxnnnbOTTnjtYzRCUaaNwaCn4QSFLNzUIUo1E+SGvBdWYAQ6xa S2enHNguPz0Bl6eFOmiAOhg= Received: (qmail 98673 invoked by alias); 23 Sep 2016 11:54:02 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 98658 invoked by uid 89); 23 Sep 2016 11:54:02 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=BAYES_00, SPF_PASS autolearn=ham version=3.3.2 spammy=recover, can_recover, displayed X-HELO: mx2.suse.de Received: from mx2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 23 Sep 2016 11:53:51 +0000 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id C4E42AC4B; Fri, 23 Sep 2016 11:53:48 +0000 (UTC) To: GCC Patches Cc: Jakub Jelinek From: =?UTF-8?Q?Martin_Li=c5=a1ka?= Subject: [PATCH] Fix handling of -fsanitize-recover* options. Message-ID: <0c0c51b5-8f69-2d64-c967-b859b38b71ac@suse.cz> Date: Fri, 23 Sep 2016 13:53:48 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2 MIME-Version: 1.0 X-IsSubscribed: yes Hi. Following patch handles various issues related to -fsanitize-recover* options: 1) -fsanitize-recover=unreachable and -fsanitize-recover=return are currently not reported as invalid options (error message is not displayed) 2) explanation of -fsanitize-recover is not precise (bounds-strict is not listed) 3) -fsanitize=leak is combinable with -fsanitize=address or -fsanitize=thread Patch can bootstrap on ppc64le-redhat-linux and survives regression tests. Ready to be installed? Martin From 077f6945e612f97ca16b792dd3f0740410b513af Mon Sep 17 00:00:00 2001 From: marxin Date: Fri, 23 Sep 2016 10:16:10 +0200 Subject: [PATCH] Fix handling of -fsanitize-recover* options. gcc/ChangeLog: 2016-09-23 Martin Liska * common.opt: Exclude SANITIZE_UNREACHABLE and SANITIZE_RETURN from default sanitize recover values. * doc/invoke.texi: Fix documentation related to -fsanitize=leak 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. --- gcc/common.opt | 2 +- gcc/doc/invoke.texi | 10 +-- gcc/flag-types.h | 32 ++++----- gcc/opts.c | 82 ++++++++++++---------- gcc/opts.h | 1 + .../c-c++-common/ubsan/sanitize-recover-1.c | 6 ++ .../c-c++-common/ubsan/sanitize-recover-2.c | 6 ++ .../c-c++-common/ubsan/sanitize-recover-3.c | 4 ++ .../c-c++-common/ubsan/sanitize-recover-4.c | 4 ++ .../c-c++-common/ubsan/sanitize-recover-5.c | 6 ++ .../c-c++-common/ubsan/sanitize-recover-6.c | 4 ++ 11 files changed, 99 insertions(+), 58 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/ubsan/sanitize-recover-1.c create mode 100644 gcc/testsuite/c-c++-common/ubsan/sanitize-recover-2.c create mode 100644 gcc/testsuite/c-c++-common/ubsan/sanitize-recover-3.c create mode 100644 gcc/testsuite/c-c++-common/ubsan/sanitize-recover-4.c create mode 100644 gcc/testsuite/c-c++-common/ubsan/sanitize-recover-5.c create mode 100644 gcc/testsuite/c-c++-common/ubsan/sanitize-recover-6.c diff --git a/gcc/common.opt b/gcc/common.opt index 8c0885c..f35660f 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 d474da6..52804c0 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -10173,9 +10173,8 @@ supported options. @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 @@ -10353,6 +10352,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. @@ -10369,12 +10369,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 dd57e16..cd53ec3 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 f625973..d6cfd53 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -957,12 +957,11 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, "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_recover & SANITIZE_LEAK) - error_at (loc, "-fsanitize-recover=leak is not supported"); + 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 +1447,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 +1518,18 @@ 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; + { + 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_UNREACHABLE | SANITIZE_RETURN); + } else flags &= ~sanitizer_opts[i].flag; found = true; @@ -1770,7 +1779,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 4132432..b3e6435 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/c-c++-common/ubsan/sanitize-recover-1.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-1.c new file mode 100644 index 0000000..4d8c27e --- /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 0000000..e9849bd --- /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 0000000..844f3fd --- /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 0000000..45fa5b9 --- /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 0000000..9c1ed32 --- /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 0000000..e309e1b --- /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; -- 2.9.2