From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 83499 invoked by alias); 6 Aug 2017 20:07:20 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 83400 invoked by uid 89); 6 Aug 2017 20:07:19 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.6 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.2 spammy=936 X-HELO: mail-qt0-f174.google.com Received: from mail-qt0-f174.google.com (HELO mail-qt0-f174.google.com) (209.85.216.174) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 06 Aug 2017 20:07:16 +0000 Received: by mail-qt0-f174.google.com with SMTP id p3so31406441qtg.2 for ; Sun, 06 Aug 2017 13:07:16 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:references:from:message-id:date :user-agent:mime-version:in-reply-to; bh=Upp+Ed4yPBObSkEiQkb3LCFltnGtf1aVId09PHBJPco=; b=rz0Io8CxyhipF9Ep+kVZWkvPdjTDppzdUmhN2yjRWUiMxJ7FqaAITpdSB+CcuSGz7N OVYBJgJsarEmSTlmIItS6lSuuZbyMglmG08Iaoz+9h4KkFsnZvZyWKoss0ofgWkfueYl qT92rBTF26LbjfmlBowpRvDzB6s7CWVixPKW4ydSQ7ybn2CFNe3KyrGf5V6xIfslcib7 a6qhmi+i1uS1ueytA2LhnLTXkXxnD9sIXqpKGuDg3AA0SAauSyKymIyE/8hdmYcqMgVc g7Crq+cEMtbSuidhDvcqyV5bPtGHxpPbNz0X5eSQas9M8c+5qFrwLRBVFhp6/3yC71pm VPRQ== X-Gm-Message-State: AHYfb5hyTNW+vmDes4YA+5l20Q7s3rMc/Svky9OhqVq2WMtmMPtlv953 hlUcv3QW0LBek0XK X-Received: by 10.200.44.13 with SMTP id d13mr11947170qta.192.1502050034854; Sun, 06 Aug 2017 13:07:14 -0700 (PDT) Received: from localhost.localdomain (174-16-105-12.hlrn.qwest.net. [174.16.105.12]) by smtp.gmail.com with ESMTPSA id v64sm4035251qkd.96.2017.08.06.13.07.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 06 Aug 2017 13:07:14 -0700 (PDT) Subject: [PATCH 2/4] enhance overflow and truncation detection in strncpy and strncat (PR 81117) To: Jeff Law , Gcc Patch List References: <13944863-99a8-4144-1703-c6e1a2f36425@gmail.com> <0bbc91cd-fcdb-be61-e1d0-4b230f23b1a9@redhat.com> <4f4fbd4c-cb46-b80d-5749-ebb6bb050bc4@gmail.com> From: Martin Sebor Message-ID: <164d8b08-ced6-f2b2-ae6e-ee96afebb52e@gmail.com> Date: Sun, 06 Aug 2017 20:07:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0 MIME-Version: 1.0 In-Reply-To: Content-Type: multipart/mixed; boundary="------------62ECC7B1B40B9D8147BBAF73" X-IsSubscribed: yes X-SW-Source: 2017-08/txt/msg00469.txt.bz2 This is a multi-part message in MIME format. --------------62ECC7B1B40B9D8147BBAF73 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Content-length: 534 Part 2 of the series adds attribute nostring to annotate arrays of and pointers to char with that are intended to store sequences of characters that aren't necessarily valid (nul-terminated) strings. In the subsequent patch the attribute is relied on to avoid diagnosing strcncpy calls that truncate strings and create such copies. In the future I'd like to also use the attribute to diagnose when arrays or pointers with the attribute are passed to functions that expect nul-terminated strings (such as strlen or strcpy). Martin --------------62ECC7B1B40B9D8147BBAF73 Content-Type: text/x-patch; name="gcc-81117-2.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="gcc-81117-2.diff" Content-length: 6837 PR c/81117 - Improve buffer overflow checking in strncpy gcc/ChangeLog: PR c/81117 * builtin-attrs.def (attribute nonstring): New. * doc/extend.texi (attribute nonstring): Document new attribute. gcc/c-family/ChangeLog: PR c/81117 * c-attribs.c (c_common_attribute_table): Add nonstring entry. (handle_nonstring_attribute): New function. gcc/testsuite/ChangeLog: PR c/81117 * c-c++-common/attr-nonstring-1.c: New test. --- a/gcc/builtin-attrs.def +++ b/gcc/builtin-attrs.def @@ -93,6 +93,7 @@ DEF_ATTR_IDENT (ATTR_FORMAT, "format") DEF_ATTR_IDENT (ATTR_FORMAT_ARG, "format_arg") DEF_ATTR_IDENT (ATTR_MALLOC, "malloc") DEF_ATTR_IDENT (ATTR_NONNULL, "nonnull") +DEF_ATTR_IDENT (ATTR_NONSTRING, "nonstring") DEF_ATTR_IDENT (ATTR_NORETURN, "noreturn") DEF_ATTR_IDENT (ATTR_NOTHROW, "nothrow") DEF_ATTR_IDENT (ATTR_LEAF, "leaf") diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 0d9ab2d..69d020c 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -116,6 +116,7 @@ static tree handle_deprecated_attribute (tree *, tree, tree, int, static tree handle_vector_size_attribute (tree *, tree, tree, int, bool *); static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *); +static tree handle_nonstring_attribute (tree *, tree, tree, int, bool *); static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *); static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *); static tree handle_warn_unused_result_attribute (tree *, tree, tree, int, @@ -270,6 +271,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_tls_model_attribute, false }, { "nonnull", 0, -1, false, true, true, handle_nonnull_attribute, false }, + { "nonstring", 0, 0, true, false, false, + handle_nonstring_attribute, false }, { "nothrow", 0, 0, true, false, false, handle_nothrow_attribute, false }, { "may_alias", 0, 0, false, true, false, NULL, false }, @@ -2970,6 +2973,48 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name), return NULL_TREE; } +/* Handle the "nonstring" variable attribute. */ + +static tree +handle_nonstring_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + gcc_assert (!args); + tree_code code = TREE_CODE (*node); + + if (VAR_P (*node) + || code == FIELD_DECL + || code == PARM_DECL) + { + tree type = TREE_TYPE (*node); + + if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE) + { + tree eltype = TREE_TYPE (type); + if (eltype == char_type_node) + return NULL_TREE; + } + + warning (OPT_Wattributes, + "%qE attribute ignored on objects of type %qT", + name, type); + *no_add_attrs = true; + return NULL_TREE; + } + + if (code == FUNCTION_DECL) + warning (OPT_Wattributes, + "%qE attribute does not apply to functions", name); + else if (code == TYPE_DECL) + warning (OPT_Wattributes, + "%qE attribute does not apply to types", name); + else + warning (OPT_Wattributes, "%qE attribute ignored", name); + + *no_add_attrs = true; + return NULL_TREE; +} + /* Handle a "nothrow" attribute; arguments as in struct attribute_spec.handler. */ diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index b253ccc..1954ca5 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -5835,6 +5835,30 @@ The @code{deprecated} attribute can also be used for functions and types (@pxref{Common Function Attributes}, @pxref{Common Type Attributes}). +@item nonstring (@var{nonstring}) +@cindex @code{nonstring} variable attribute +The @code{nonstring} variable attribute specifies that an object or member +declaration with type array of @code{char} or pointer to @code{char} is +intended to store character arrays that do not necessarily contain +a terminating @code{NUL} character. This is useful to avoid warnings +when such an array or pointer is used as an argument to a bounded string +manipulation function such as @code{strncpy}. For example, without the +attribute, GCC will issue a warning for the call below because it may +truncate the copy without appending the terminating NUL character. Using +the attribute makes it possible to suppress the warning. + +@smallexample +struct Data +@{ + char name [32] __attribute__ ((nonstring)); +@}; +void f (struct Data *pd, const char *s) +@{ + strncpy (pd->name, s, sizeof pd->name); + @dots{} +@} +@end smallexample + @item mode (@var{mode}) @cindex @code{mode} variable attribute This attribute specifies the data type for the declaration---whichever diff --git a/gcc/testsuite/c-c++-common/attr-nonstring-1.c b/gcc/testsuite/c-c++-common/attr-nonstring-1.c new file mode 100644 index 0000000..10a6688 --- /dev/null +++ b/gcc/testsuite/c-c++-common/attr-nonstring-1.c @@ -0,0 +1,60 @@ +/* Test to exercise attribute "nonstring" syntax. + { dg-do compile } + { dg-options "-Wattributes" } */ + +#define ATTR(list) __attribute__ (list) +#define NONSTR ATTR ((nonstring)) + +/* Verify it's accepted on char arrays. */ +extern NONSTR char nsx_1[]; +extern char NONSTR nsx_2[]; +extern char nsx_3[] NONSTR; + +extern NONSTR char ns1[1]; +extern char NONSTR ns3[3]; +extern char ns5[5] NONSTR; + +/* Verify it's accepted on char pointers. */ +extern NONSTR char* pns_1; +extern char NONSTR* pns_2; +extern char* NONSTR pns_3; + +struct S +{ +/* Verify it's accepted on char member pointers. */ + NONSTR char* mpns_1; + char NONSTR* mpns_2; + char* NONSTR mpns_3; + +/* Verify it's accepted on char member arrays. */ + NONSTR char mns1[1]; + char NONSTR mns3[3]; + char mns5[5] NONSTR; + +/* Verify it's accepted on char flexible array members. */ + char mnsx[] NONSTR; +}; + +/* Verify it's rejected on non-array and non-pointer objects. */ +extern NONSTR char c1; /* { dg-warning ".nonstring. attribute ignored on objects of type .char." } */ + +extern NONSTR int i1; /* { dg-warning ".nonstring. attribute ignored on objects of type .int." } */ + +extern NONSTR int ia1[]; /* { dg-warning ".nonstring. attribute ignored on objects of type .int *\\\[\\\]." } */ + +extern NONSTR int* pi1; /* { dg-warning ".nonstring. attribute ignored on objects of type .int *\\*." } */ + +extern NONSTR +void f (void); /* { dg-warning ".nonstring. attribute does not apply to functions" } */ + +struct NONSTR +NonStrType { int i; }; /* { dg-warning ".nonstring. attribute does not apply to types" } */ + +typedef char NONSTR nschar_t; /* { dg-warning ".nonstring. attribute does not apply to types" } */ + +void func (NONSTR char *pns1, char NONSTR *pns2, char* NONSTR pns3) +{ + (void)pns1; + (void)pns2; + (void)pns3; +} --------------62ECC7B1B40B9D8147BBAF73--