From patchwork Mon Jun 13 19:53:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 55061 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E118A3850402 for ; Mon, 13 Jun 2022 19:53:48 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E118A3850402 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1655150028; bh=T2x3jHocLo8o2R/KAIFmspYhUUftTJo8A7IQoXNOGJ4=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=s5Qr8PyQSsS7nmzmcTkjZ08VRqkWSFGcqRy7MP9x6Bf0W9dkQem1zqw6AGBZhGv0j YZRsXi9jgiQ7HuXkQgdhLAVr6dQMbub5PNq49El7590WbRaFlBU+5KaGqcG1GnDur4 nqLbqnNe3Md32g3/JOCImvkuPOLdDFinn+Qh7coA= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 927563858430 for ; Mon, 13 Jun 2022 19:53:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 927563858430 Received: from mail-qk1-f199.google.com (mail-qk1-f199.google.com [209.85.222.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-620-BGIQBhsCNz-w3azqtM2LGw-1; Mon, 13 Jun 2022 15:53:16 -0400 X-MC-Unique: BGIQBhsCNz-w3azqtM2LGw-1 Received: by mail-qk1-f199.google.com with SMTP id bi36-20020a05620a31a400b006a79f0706e5so1565002qkb.2 for ; Mon, 13 Jun 2022 12:53:16 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=T2x3jHocLo8o2R/KAIFmspYhUUftTJo8A7IQoXNOGJ4=; b=fwQkoLX1oPQwJx3Yehso8uo5ovHUIwgmu49CnuKNdfu9L3+T3yUFriH+9mSAALDOG9 McdeqoWhhXPmsHK1rUX+7oW8m9mHe+qbB+Muc+VNMTxq+HlkrkRN4kSmV3cz8ObSWpsi 4zdI9tF4Bnj5DJtsA6jvvapYUpughwuuMCvLIeDXI7LIwkiZ68KD3uJvRSVT9lTzjc+8 2zH5Wx1s4973rKDKKhckrqNKgsaVKTwfDj2SvDdfB0faHgs7KEKFeJyzTOWBThglkv+F JRsoAadsbJjPGtvcbvOCYI5tt558ZUn1vzJjPH3MfdCTIXwudewp9R3zJ35S1tl5djgm 0hBQ== X-Gm-Message-State: AOAM533+pGrOiOBufqXq9nz+dOULUR4/VgE8B+BXRBaIZhTdnUFDqUhd NhokPB6ZdoGIRfiCGv3cI6MIUNk8hiLqXnXGDuHE03eLjm5bddVhKSbyQ14qTq6vsow4gTazi5q R+6xkJZAvI76jYp8wfjGYY/aBO3QyyqlNUJMLRZLoDsJ9MWM+mlCR6/xy1K5jdCHq4A== X-Received: by 2002:a05:620a:370e:b0:6a7:2471:b3eb with SMTP id de14-20020a05620a370e00b006a72471b3ebmr1295327qkb.631.1655149995636; Mon, 13 Jun 2022 12:53:15 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwmUAA79DysEvtxfFNM9r10VhvaLNF9wXdGNDL//Qz5F9VZfORg3d413UCOiPLUmouiByKGBQ== X-Received: by 2002:a05:620a:370e:b0:6a7:2471:b3eb with SMTP id de14-20020a05620a370e00b006a72471b3ebmr1295304qkb.631.1655149995130; Mon, 13 Jun 2022 12:53:15 -0700 (PDT) Received: from barrymore.redhat.com (130-44-159-43.s15913.c3-0.arl-cbr1.sbo-arl.ma.cable.rcncustomer.com. [130.44.159.43]) by smtp.gmail.com with ESMTPSA id d9-20020a05622a15c900b002f93be3ccfdsm5986756qty.18.2022.06.13.12.53.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 12:53:14 -0700 (PDT) To: gcc-patches@gcc.gnu.org, richard.guenther@gmail.com Subject: [PATCH RFA] ubsan: default to trap on unreachable at -O0 and -Og [PR104642] Date: Mon, 13 Jun 2022 15:53:13 -0400 Message-Id: <20220613195313.3240547-1-jason@redhat.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-13.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jason Merrill via Gcc-patches From: Jason Merrill Reply-To: Jason Merrill Cc: jwakely.gcc@gmail.com Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" When not optimizing, we can't do anything useful with unreachability in terms of code performance, so we might as well improve debugging by turning __builtin_unreachable into a trap. In the PR richi suggested introducing an -funreachable-traps flag for this, but this functionality is already implemented as -fsanitize=unreachable -fsanitize-undefined-trap-on-error, we just need to set those flags by default. I think it also makes sense to do this when we're explicitly optimizing for the debugging experience. I then needed to make options-save handle -fsanitize and -fsanitize-undefined-trap-on-error; since -fsanitize is has custom parsing, that meant handling it explicitly in the awk scripts. I also noticed we weren't setting it in opts_set. Do we still want -funreachable-traps as an alias (or separate flag) for this behavior that doesn't mention the sanitizer? Tested x86_64-pc-linux-gnu, OK for trunk? PR c++/104642 gcc/ChangeLog: * doc/invoke.texi (-fsanitize-undefined-trap-on-error): On by default at -O0, implying -fsanitize=unreachable,return * opts.cc (finish_options): At -O0 trap on unreachable code. (common_handle_option): Set opts_set->x_flag_sanitize. * common.opt (fsanitize-undefined-trap-on-error): Add Optimization tag. * optc-save-gen.awk, opth-gen.awk: Include flag_sanitize. gcc/testsuite/ChangeLog: * g++.dg/ubsan/return-8a.C: New test. --- gcc/doc/invoke.texi | 4 ++++ gcc/common.opt | 2 +- gcc/opts.cc | 10 ++++++++++ gcc/testsuite/g++.dg/ubsan/return-8a.C | 17 +++++++++++++++++ gcc/optc-save-gen.awk | 8 ++++++-- gcc/opth-gen.awk | 3 ++- 6 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ubsan/return-8a.C base-commit: 13ea4a6e830da1f245136601e636dec62e74d1a7 prerequisite-patch-id: f75da3aa4e66d8b85562d5dd9ae35c5429c1ea74 diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 174bc09e5cf..446b0691305 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -16100,6 +16100,10 @@ a @code{libubsan} library routine. The advantage of this is that the @code{libubsan} library is not needed and is not linked in, so this is usable even in freestanding environments. +If @option{-fsanitize} has not been specified, this option implies +@option{-fsanitize=unreachable,return}, and is enabled by default at +@option{-O0} and @option{-Og}. + @item -fsanitize-coverage=trace-pc @opindex fsanitize-coverage=trace-pc Enable coverage-guided fuzzing code instrumentation. diff --git a/gcc/common.opt b/gcc/common.opt index 7ca0cceed82..90e3e84913b 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1109,7 +1109,7 @@ fsanitize-address-use-after-scope Common Driver Var(flag_sanitize_address_use_after_scope) Init(0) fsanitize-undefined-trap-on-error -Common Driver Var(flag_sanitize_undefined_trap_on_error) Init(0) +Common Driver Optimization Var(flag_sanitize_undefined_trap_on_error) Init(0) Use trap instead of a library function for undefined behavior sanitization. fasynchronous-unwind-tables diff --git a/gcc/opts.cc b/gcc/opts.cc index bf06a55456a..3699eabb599 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -1122,6 +1122,15 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, opts->x_flag_no_inline = 1; } + /* At -O0 or -Og, turn __builtin_unreachable into a trap. */ + if ((!opts->x_optimize || opts->x_optimize_debug) + && !opts_set->x_flag_sanitize) + SET_OPTION_IF_UNSET (opts, opts_set, + flag_sanitize_undefined_trap_on_error, true); + if (opts->x_flag_sanitize_undefined_trap_on_error) + SET_OPTION_IF_UNSET (opts, opts_set, flag_sanitize, + SANITIZE_UNREACHABLE|SANITIZE_RETURN); + /* Pipelining of outer loops is only possible when general pipelining capabilities are requested. */ if (!opts->x_flag_sel_sched_pipelining) @@ -2613,6 +2622,7 @@ common_handle_option (struct gcc_options *opts, break; case OPT_fsanitize_: + opts_set->x_flag_sanitize = true; opts->x_flag_sanitize = parse_sanitizer_options (arg, loc, code, opts->x_flag_sanitize, value, true); diff --git a/gcc/testsuite/g++.dg/ubsan/return-8a.C b/gcc/testsuite/g++.dg/ubsan/return-8a.C new file mode 100644 index 00000000000..9b2265c4bb0 --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/return-8a.C @@ -0,0 +1,17 @@ +// PR c++/104642 + +// At -O0 we default to +// -fsanitize=unreachable,return -fsanitize-undefined-trap-on-error +// so the below should abort at runtime. + +// { dg-do run } +// { dg-shouldfail { *-*-* } } +// { dg-additional-options "-O0" } + +bool b; + +int f() { + if (b) return 42; +} // { dg-warning "-Wreturn-type" } + +int main() { f(); } diff --git a/gcc/optc-save-gen.awk b/gcc/optc-save-gen.awk index 233d1fbb637..38c02bcc2cf 100644 --- a/gcc/optc-save-gen.awk +++ b/gcc/optc-save-gen.awk @@ -84,7 +84,7 @@ print "{"; n_opt_char = 4; n_opt_short = 0; -n_opt_int = 0; +n_opt_int = 1; n_opt_enum = 0; n_opt_string = 0; n_opt_other = 0; @@ -96,6 +96,7 @@ var_opt_range["optimize"] = "0, 255"; var_opt_range["optimize_size"] = "0, 2"; var_opt_range["optimize_debug"] = "0, 1"; var_opt_range["optimize_fast"] = "0, 1"; +var_opt_int[0] = "flag_sanitize"; # Sort by size to mimic how the structure is laid out to be friendlier to the # cache. @@ -1264,7 +1265,7 @@ for (i = 0; i < n_target_str; i++) { } print "}"; -n_opt_val = 4; +n_opt_val = 5; var_opt_val[0] = "x_optimize" var_opt_val_type[0] = "char " var_opt_hash[0] = 1; @@ -1277,6 +1278,9 @@ var_opt_hash[2] = 1; var_opt_val[3] = "x_optimize_fast" var_opt_val_type[3] = "char " var_opt_hash[3] = 1; +var_opt_val[4] = "x_flag_sanitize" +var_opt_val_type[4] = "unsigned int " +var_opt_hash[4] = 1; for (i = 0; i < n_opts; i++) { if (flag_set_p("(Optimization|PerFunction)", flags[i])) { name = var_name(flags[i]) diff --git a/gcc/opth-gen.awk b/gcc/opth-gen.awk index 8bba8ec4549..b3bedaa6da2 100644 --- a/gcc/opth-gen.awk +++ b/gcc/opth-gen.awk @@ -134,7 +134,7 @@ print "{"; n_opt_char = 4; n_opt_short = 0; -n_opt_int = 0; +n_opt_int = 1; n_opt_enum = 0; n_opt_other = 0; n_opt_explicit = 4; @@ -142,6 +142,7 @@ var_opt_char[0] = "unsigned char x_optimize"; var_opt_char[1] = "unsigned char x_optimize_size"; var_opt_char[2] = "unsigned char x_optimize_debug"; var_opt_char[3] = "unsigned char x_optimize_fast"; +var_opt_int[0] = "unsigned int x_flag_sanitize"; for (i = 0; i < n_opts; i++) { if (flag_set_p("(Optimization|PerFunction)", flags[i])) {