From patchwork Mon Nov 15 20:31:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 1555517 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=TDmUFnpV; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HtLTz1znlz9sWJ for ; Tue, 16 Nov 2021 07:32:37 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C79F13857C63 for ; Mon, 15 Nov 2021 20:32:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C79F13857C63 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1637008354; bh=vbYnVGcLmajCnVTEH0Yqv/JKOaD62UJUMDhvOvCPULo=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=TDmUFnpVyD/uzStpnZtYKCeKa67gFkLoqFnPMFzPezXHY8wwjbQRO/d7STVeLNau3 dOu623hZMEsjbUdGpbarAsbVi9S/2M5r9Rb3RA/Vx7tz4W3RirGKev3u2NcTMJzXxr kVAODEzglV4PPz93EO9j16J73bpYs43RMvITVBTg= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pj1-x1029.google.com (mail-pj1-x1029.google.com [IPv6:2607:f8b0:4864:20::1029]) by sourceware.org (Postfix) with ESMTPS id 915513858405 for ; Mon, 15 Nov 2021 20:31:51 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 915513858405 Received: by mail-pj1-x1029.google.com with SMTP id w33-20020a17090a6ba400b001a722a06212so583620pjj.0 for ; Mon, 15 Nov 2021 12:31:51 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version:content-language; bh=vbYnVGcLmajCnVTEH0Yqv/JKOaD62UJUMDhvOvCPULo=; b=TyiMTucsC3tv/cr+/JFn74J4rVovGPByAUrjox3GfLcTXdpNz9QmtJcQL6n9ucCquH f3Tofd1Tw9DFk8CIbqhEPi9bS2GR39nl0+Mk54UGsBoQRKxXQBfom8yS88UC1bIUs0bm pTrshJJkoHIdSf+7IWB268oLKlQTebbAdbK57eZlXd9sf2Q3Gq/VWHuRphEEu9BVhZOL yxZXqaV42HY1ew60tu1ivrdqDbnrn0tD9QaWo+f3782IlVlTfx6sWCNRb/cDntaL+39q pK2vbTsh6Ul3gc7395VA19TIb+Wf1Iq96kU/jCRvjLUqzWaHRP1r5JwwWUz7/o9vtekr PnuA== X-Gm-Message-State: AOAM530ClVxPuEyw6lljqYN9LSHnjjPRcK1tvbL1VluCml7Ot6DWr3AL Z+a7nwEOk3cafmYwDbOO1rK+kO97wRw= X-Google-Smtp-Source: ABdhPJz6UNDWk0xCmlZmNjf6lz4YlnepRZKTxgoq22L+JO+0EAhcSgJinVwQmYevS7Q7IUn0arHQew== X-Received: by 2002:a17:90b:4b90:: with SMTP id lr16mr68543611pjb.57.1637008310179; Mon, 15 Nov 2021 12:31:50 -0800 (PST) Received: from [192.168.0.41] (184-96-250-76.hlrn.qwest.net. [184.96.250.76]) by smtp.gmail.com with ESMTPSA id u19sm15442176pfl.185.2021.11.15.12.31.49 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 15 Nov 2021 12:31:49 -0800 (PST) To: gcc-patches Subject: [PATCH] Avoid pathological function redeclarations when checking access sizes [PR102759] Message-ID: Date: Mon, 15 Nov 2021 13:31:48 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.2.2 MIME-Version: 1.0 Content-Language: en-US X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: Martin Sebor via Gcc-patches From: Martin Sebor Reply-To: Martin Sebor Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Declaring a function with a prototype at block scope and then redeclaring it without a prototype at file scope results in losing the prototype but not the attribute access that was implicitly added to the function decl based on the prototype. The middle end code that checks function calls for out-of-bounds accesses based on the attribute is unprepared for this case and fails with an ICE. The attached patch corrects this by having it ignore these pathological cases. In addition, the change also improves the format of the informational note printed after these warnings to reflect the form of the argument (e.g., to print int[7] rather than int * if the former was the form used in the declaration). Tested on x86_64-linux. Martin Avoid pathological function redeclarations when checking access sizes [PR102759]. Resolves: PR tree-optimization/102759 - ICE: Segmentation fault in maybe_check_access_sizes since r12-2976-gb48d4e6818674898 PR tree-optimization/102759 gcc/ChangeLog: PR tree-optimization/102759 * gimple-array-bounds.cc (build_printable_array_type): Move... * gimple-ssa-warn-access.cc (build_printable_array_type): Avoid pathological function redeclarations that remove a previously declared prototype. Improve formatting of function arguments in informational notes. * pointer-query.cc (build_printable_array_type): ...to here. * pointer-query.h (build_printable_array_type): Declared. gcc/testsuite/ChangeLog: PR tree-optimization/102759 * gcc.dg/Warray-parameter-10.c: New test. * gcc.dg/Wstringop-overflow-82.c: New test. diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc index a3535598998..ddb99d263d1 100644 --- a/gcc/gimple-array-bounds.cc +++ b/gcc/gimple-array-bounds.cc @@ -372,31 +372,6 @@ array_bounds_checker::check_array_ref (location_t location, tree ref, return warned; } -/* Wrapper around build_array_type_nelts that makes sure the array - can be created at all and handles zero sized arrays specially. */ - -static tree -build_printable_array_type (tree eltype, unsigned HOST_WIDE_INT nelts) -{ - if (TYPE_SIZE_UNIT (eltype) - && TREE_CODE (TYPE_SIZE_UNIT (eltype)) == INTEGER_CST - && !integer_zerop (TYPE_SIZE_UNIT (eltype)) - && TYPE_ALIGN_UNIT (eltype) > 1 - && wi::zext (wi::to_wide (TYPE_SIZE_UNIT (eltype)), - ffs_hwi (TYPE_ALIGN_UNIT (eltype)) - 1) != 0) - eltype = TYPE_MAIN_VARIANT (eltype); - - if (nelts) - return build_array_type_nelts (eltype, nelts); - - tree idxtype = build_range_type (sizetype, size_zero_node, NULL_TREE); - tree arrtype = build_array_type (eltype, idxtype); - arrtype = build_distinct_type_copy (TYPE_MAIN_VARIANT (arrtype)); - TYPE_SIZE (arrtype) = bitsize_zero_node; - TYPE_SIZE_UNIT (arrtype) = size_zero_node; - return arrtype; -} - /* Checks one MEM_REF in REF, located at LOCATION, for out-of-bounds references to string constants. If VRP can determine that the array subscript is a constant, check if it is outside valid range. diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc index 073f122af31..8248a5b38a1 100644 --- a/gcc/gimple-ssa-warn-access.cc +++ b/gcc/gimple-ssa-warn-access.cc @@ -2976,10 +2976,16 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype, continue; tree ptrtype = fntype_argno_type (fntype, ptridx); + if (!ptrtype) + /* A function with a prototype was redeclared without one and + the protype has been lost. See pr102759. Avoid dealing + with this pathological case. */ + return; + tree argtype = TREE_TYPE (ptrtype); - /* The size of the access by the call. */ - tree access_size; + /* The size of the access by the call in elements. */ + tree access_nelts; if (sizidx == -1) { /* If only the pointer attribute operand was specified and @@ -2989,17 +2995,17 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype, if the pointer is also declared with attribute nonnull. */ if (access.second.minsize && access.second.minsize != HOST_WIDE_INT_M1U) - access_size = build_int_cstu (sizetype, access.second.minsize); + access_nelts = build_int_cstu (sizetype, access.second.minsize); else - access_size = size_one_node; + access_nelts = size_one_node; } else - access_size = rwm->get (sizidx)->size; + access_nelts = rwm->get (sizidx)->size; /* Format the value or range to avoid an explosion of messages. */ char sizstr[80]; tree sizrng[2] = { size_zero_node, build_all_ones_cst (sizetype) }; - if (get_size_range (m_ptr_qry.rvals, access_size, stmt, sizrng, 1)) + if (get_size_range (m_ptr_qry.rvals, access_nelts, stmt, sizrng, 1)) { char *s0 = print_generic_expr_to_str (sizrng[0]); if (tree_int_cst_equal (sizrng[0], sizrng[1])) @@ -3057,6 +3063,8 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype, } } + /* The size of the access by the call in bytes. */ + tree access_size = NULL_TREE; if (tree_int_cst_sgn (sizrng[0]) >= 0) { if (COMPLETE_TYPE_P (argtype)) @@ -3073,9 +3081,9 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype, access_size = wide_int_to_tree (sizetype, minsize); } } + else + access_size = access_nelts; } - else - access_size = NULL_TREE; if (integer_zerop (ptr)) { @@ -3170,8 +3178,13 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype, if (opt_warned != no_warning) { if (access.second.internal_p) - inform (loc, "referencing argument %u of type %qT", - ptridx + 1, ptrtype); + { + unsigned HOST_WIDE_INT nelts = + access_nelts ? access.second.minsize : HOST_WIDE_INT_M1U; + tree arrtype = build_printable_array_type (argtype, nelts); + inform (loc, "referencing argument %u of type %qT", + ptridx + 1, arrtype); + } else /* If check_access issued a warning above, append the relevant attribute to the string. */ diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc index a0e4543d8a3..2ead0271617 100644 --- a/gcc/pointer-query.cc +++ b/gcc/pointer-query.cc @@ -2358,3 +2358,33 @@ array_elt_at_offset (tree artype, HOST_WIDE_INT off, return NULL_TREE; } + +/* Wrapper around build_array_type_nelts that makes sure the array + can be created at all and handles zero sized arrays specially. */ + +tree +build_printable_array_type (tree eltype, unsigned HOST_WIDE_INT nelts) +{ + if (TYPE_SIZE_UNIT (eltype) + && TREE_CODE (TYPE_SIZE_UNIT (eltype)) == INTEGER_CST + && !integer_zerop (TYPE_SIZE_UNIT (eltype)) + && TYPE_ALIGN_UNIT (eltype) > 1 + && wi::zext (wi::to_wide (TYPE_SIZE_UNIT (eltype)), + ffs_hwi (TYPE_ALIGN_UNIT (eltype)) - 1) != 0) + eltype = TYPE_MAIN_VARIANT (eltype); + + /* Consider excessive NELTS an array of unknown bound. */ + tree idxtype = NULL_TREE; + if (nelts < HOST_WIDE_INT_MAX) + { + if (nelts) + return build_array_type_nelts (eltype, nelts); + idxtype = build_range_type (sizetype, size_zero_node, NULL_TREE); + } + + tree arrtype = build_array_type (eltype, idxtype); + arrtype = build_distinct_type_copy (TYPE_MAIN_VARIANT (arrtype)); + TYPE_SIZE (arrtype) = bitsize_zero_node; + TYPE_SIZE_UNIT (arrtype) = size_zero_node; + return arrtype; +} diff --git a/gcc/pointer-query.h b/gcc/pointer-query.h index c8215b681ef..fbea3316f14 100644 --- a/gcc/pointer-query.h +++ b/gcc/pointer-query.h @@ -275,4 +275,7 @@ extern tree array_elt_at_offset (tree, HOST_WIDE_INT, HOST_WIDE_INT * = nullptr, HOST_WIDE_INT * = nullptr); +/* Helper to build an array type that can be printed. */ +extern tree build_printable_array_type (tree, unsigned HOST_WIDE_INT); + #endif // GCC_POINTER_QUERY_H diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-10.c b/gcc/testsuite/gcc.dg/Warray-parameter-10.c new file mode 100644 index 00000000000..378f8afbd34 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-parameter-10.c @@ -0,0 +1,20 @@ +/* PR c/102759 - ICE calling a function taking an argument redeclared + without a prototype. + { dg-do compile } + { dg-options "-Wall" } */ + +void f (void) +{ + void gia (int[2]); + void g (); +} + +/* Redeclaring the g(int[]) above without a prototype loses it. */ +void gia (); +void g (int[2]); + +void h (void ) +{ + gia (gia); + gia (g); +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-82.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-82.c new file mode 100644 index 00000000000..ee2693dcea9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-82.c @@ -0,0 +1,29 @@ +/* Verify that notes after warnings for array and VLA parameters show + the array form. + { dg-do compile } + { dg-options "-Wall" } */ + +void fia5 (int[5]); + +void gia3_fia5 (void) +{ + int a[3]; + fia5 (a); // { dg-warning "-Wstringop-overflow" } + // { dg-message "argument 1 of type 'int\\\[5]'" "note" { target *-*-* } .-1 } +} + + +/* The type of the argument would ideall be 'int[n]' but the variable + bound is lost/cleared by free-lang-data and never makes it into + the middle end. An (inferior) alternative would be 'int[*]' but + the pretty printer doesn't know how to format the star. A better + solution might be to introduce a new notation, like 'int[$1]', + where the $1 refers to the VLA argument bound. */ +void fvla (int n, int[n]); + +void gia3_fvla (void) +{ + int a[3]; + fvla (sizeof a, a); // { dg-warning "-Wstringop-overflow" } + // { dg-message "argument 2 of type 'int\\\[]'" "note" { target *-*-* } .-1 } +}