From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM10-BN7-obe.outbound.protection.outlook.com (mail-bn7nam10olkn2069.outbound.protection.outlook.com [40.92.40.69]) by sourceware.org (Postfix) with ESMTPS id 711553858C50 for ; Tue, 12 Jul 2022 17:32:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 711553858C50 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=mu3gSJ1Sr8opxtzLtwySdzSCDmraPhE8UJLGI7HqEQbB3ALwWD6DWY65/0huQ8rSejx6lVw8QqLYmRqyuk1B4QL+A0HAtUFszwNm/ZrWY2iugJLxvgLTWiMhFhS4+B8CR5uA7eQdZSrlzNHgH+35zpwa4DtrVOsnuP7lpp5puVwUairMjQCW2DyQmKLWICm8N4J3gxcLfAmWy0dT+or7WFqArOW7CBS2q54x8xzRKQT6IoDFnP4Y+CJBaxwpxvg5R6c8u2yNyTsRkdfKoAkO3D2TPHWsRh7tjeCbWFsgKUwa3s5icKuFy+NwYYHKI8XlYT77n+ASoieJoKqVJx0liQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=UDiEvX6k4o3lo8zp6esrlsY1FPrKxVD8ym4rWqzbAC0=; b=Iqy4IEqYV5NjDTC0/9w1cLaSqMbQaz6QmwkCX/y/jAOxq2aac7TSLhP6L+EJ9gbW9bbCxVvEeLpOfbCMGje5fL9areU0+QQnHm/G6nlZwQD81FlxG0e+MuTOlVNJlLn1YzT+koPQNPa+M6ihmVrRtCYVe7/DLfPYlp5zPop1jCo1dbnXpJRjcXmjCY3ZSOlDArSjvOYmGBrSwCEiqoGc91MMzn4zRQPaKCmcEnjCItUyeKwG+ya2HWZZXv2si/7QEzSbMkZGw/1NF0iAqvVefpKitbN3sUDuFAzF6nFK1sX0DeZCR9fDM3fNfr0o2jiKlbxabpPdW9abo2JdQmb4wQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none Received: from CY4PR1801MB1910.namprd18.prod.outlook.com (2603:10b6:910:79::14) by MN2PR18MB2895.namprd18.prod.outlook.com (2603:10b6:208:3b::28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5417.26; Tue, 12 Jul 2022 17:32:07 +0000 Received: from CY4PR1801MB1910.namprd18.prod.outlook.com ([fe80::4d74:63e5:d5ee:3647]) by CY4PR1801MB1910.namprd18.prod.outlook.com ([fe80::4d74:63e5:d5ee:3647%2]) with mapi id 15.20.5417.026; Tue, 12 Jul 2022 17:32:07 +0000 From: Immad Mir To: gcc@gcc.gnu.org Cc: dmalcolm@redhat.com, mirimnan017@gmail.com, Immad Mir Subject: [PATCH] filedescriptor attribute Date: Tue, 12 Jul 2022 23:01:36 +0530 Message-ID: X-Mailer: git-send-email 2.25.1 Reply-To: mirimnan017@gmail.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain X-TMN: [9cDD2VZwBwyGimE1wTZfamo+Iq3atY8nUgkmVcz1jGwUKYzLMkD3yr4IDHYcGwhi] X-ClientProxiedBy: PN0PR01CA0008.INDPRD01.PROD.OUTLOOK.COM (2603:1096:c01:4f::13) To CY4PR1801MB1910.namprd18.prod.outlook.com (2603:10b6:910:79::14) X-Microsoft-Original-Message-ID: <20220712173136.23299-1-mirimmad@outlook.com> MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: f00bc7fd-01d3-4602-0e43-08da642c70fe X-MS-Exchange-SLBlob-MailProps: DJLbvgWm8MaK4XxBpiPVk1gNvgG8m2qmpGg/57CHQNXye7/nc/8xw0A+sYWjW2Mc/3xvyElgUJEXx+nVEQy1XZDxxeYZefh91L6NUEUHo0xglU1d8hp6SRo5BTRHK1msJX7OV8d77vFPotkH2hlEolC0r7e8QpQSat+1so3AFtq32Ey/7p2+qpFV+rPAEJq2WmHYea81Z5pHTxJphM4O2uhF/2tjJnDExKSgnUyXSknE4uPzJH71hAf2a9wSBga+83n4DNKUxVIb5spPJOqukptofZe1GxNQiJwKeCuBuswiZthcNTCiTwl7yWlmESROxhBXfeU1RcjEuiEm9nUcVnFRSXbewi2sjKdzcYdXi7XBW4v44oGf1bm0a5uFh+zWWE00h2EDxSOCbHICFnvlET6iL8x/3UjXfipdUUAF86BvvujJLJcBMjVb8r0u18MrtwadE6JN1YhykesjEU1yF58xvf0YWtwCdpmDaxJniuMlcS3dZIOxAjJXN7YGAmP2O2SoqLCqMZIgve0OecS5oZMQ3Ify7ZgKtGgwoVt09mf4y7skANy2nBur3dbcYr4w+iR1u3+8anGzqubSI1UxC1h4Mj54KyEMX791IIfUUOjXUnEsC4o/4PDKBcHk6Ory5PHb2btWKAFUimPq6QihOeCbnf+heAYHozikTXIABpZOaZr8FeH7Vip7CBlTkONUEDrYpIrt1wjS249NdMIO3g== X-MS-TrafficTypeDiagnostic: MN2PR18MB2895:EE_ X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 6QsVCotQlwk/ANSoD/DDfLbmqakwOGTIyOvtqMTUiiEIEpe7XfLeO+hBMqowgEmj+9NpalPaNQqhcXoVhS8bFuLt513AcIVF1EY8yDk8NocxOXDQBUDxaESjyRsY9yQSRIvXQ3TbfZntq/D63H5aGyQoLzS5x1eJu0qzMF3gJshQLhVGApw7cR/LjdtLdlHBoQKjxzTepOSjeOsm0wI/lKnRK8megt1R9Be669/BhvFWG85S3jlWJSMizvEJicRy/C100C6DozAB2XARV53bnOKVLvncS2n3dqWeI6nBmruSyEcAHTVIkDebNIq9kI7DGdcORhS4Xu6mdcr43Q8zNQblBoUw2xbtGN6LLMgMRGlEgeOerXkckFyNh1TUxRIJN+nVncDVPb/M1JWFXvinLnrii15lBGzr7njhCKtrUmQsIwIZoulCCThiSwlK9835HoDOIxarlI6IStKcqZzMkNGx3+K7XWAePcRiLs3lm3BE2rFSaYlYIgwhns1CFSHWAGfusxfpvi42mKjlcNm875S37ndjHbvcYKqNhoaZ2u6wKoBDvXDP+1bLZ5aqnx3G2WdoiGOU1YRyMFl1LeTdd3MQVX1/M3Y2sCFnpI5c4OWjPFRwhszhSdgYG1qGY26AMlW99QSF4cIfMHkiDewNZNcho3p409eMjzIc+4VN0PCUmhVuszJASUMmj3ka1xO1G+oyTC6dV7RxXHvP/xNPWw== X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?R0uLcJpi0owGpQt/TLWuq/dAnOzpiOOUnvVARZzTm2kwDoA9KrmOLZ8+kOUw?= =?us-ascii?Q?MlqVagyUUox/4hgv1OPyNSWWDpX09HNYCWdbQu07ErmDVbHydyYKk9LxHPZY?= =?us-ascii?Q?HWy6GrmNaEGa1qppZx6rs8ygCfVi/GKr3s50wm42yLq1f4zfZKJWE5u69p5Y?= =?us-ascii?Q?TFYtQ2iGN98ohhNLjwVx90VixfMEjYssXQM/1eKn+qLMyWnWzjl0ooRZrbMV?= =?us-ascii?Q?Dg2XDIGg7135gQKP9LOlwYt+xwFISEma5EsmlPSVHCoVAtIKogndsENV/sqn?= =?us-ascii?Q?93R+5WV+eEkiUFtv9Vgmt0bqC7jwJTlSvTW/UAYvGdQf739+D0MdmeFXuw0i?= =?us-ascii?Q?8eX9exeusJSLg4Onc3etmyuH+AiimAK84lFo3CrxP2FVkapN1xqByqtuhrV0?= =?us-ascii?Q?/K7YTUs3deki9YtKU4B6eE+iRQw159N+y1BS6ESPBx3u2OXVtdSYcxcAIXZO?= =?us-ascii?Q?enGMqifsWgJUy5hVxBVGRTgOHytTGJ07ra8+hWaqwBjsBrpS2nASPU3aIgxX?= =?us-ascii?Q?HLOHzY6RnOKcjGckCEbaYu+UuD/WbajVpKQfB2/qBF9xrZr0t9buX7XzREVJ?= =?us-ascii?Q?1VSfVocqEDM1b/A3tt1nhOaRkA0ln3beBusjM1SKXv8FeELCL0O+Yg7Q7iP6?= =?us-ascii?Q?erc4n9IJsm6etzNob3VPqEfnCrFsPVtiva4slBjI+IgtAzLOKVBnB+YuWxSP?= =?us-ascii?Q?Y1rXEkryxUiUFjKOzvVFFR3OhPDwIqw/OUJ6l0IkfacswpUJkKjYnSdhFaJ6?= =?us-ascii?Q?6bM7Z/l4rYvQ/+RzxRvINJQa+35wWSccVIyHJBc6XdN9JUzZPN85ocQ9LFFd?= =?us-ascii?Q?Drs/SBZE4uxWSjZvS0FmfLRUttogYaDJRfZELWLLiwPvS/Ybzqb8JNBmgaft?= =?us-ascii?Q?lwprZnLa5NntQBp+bK7t0wXFMMrSMwK1QAFGAhoCWRjbcPW8ywKJAKcZCJ28?= =?us-ascii?Q?sKfY8lS8XOcfZyWpWaelGIspU8+jw8Z89LLoKuItl4e3P05LwITzRS0nyhp5?= =?us-ascii?Q?8YNVqL0e7Gl7ZpeL/ygtMNINR6bBxanZJNXpUl6MhQh3ZpzplC3XW31I5Eap?= =?us-ascii?Q?7y71KM0ExjVchPz3l66f6a95f9rGwuBtO+Y6IwI+LLWyQ+N5RRLfJc2hndOo?= =?us-ascii?Q?GWy+WyNOH3dG4CRgCHL13YI6rtiWcYG3Ybwy4ZIfxBbF6BRgXoDJsgQHEOIG?= =?us-ascii?Q?lKzNG3Fuq26hwpWimrAnmgZa0wdVn3VM7+WjZ+HoWS25MozsSTzcE06bVlGk?= =?us-ascii?Q?UkXrI/h5/l3aib5Cgpt0S7jx1ofi6CHnWICPfNPrpMQnbMhYwbAky+Osyl/x?= =?us-ascii?Q?+5ctVjNQzXWdnUnQgqZApZSIRdRimWrGfVlxNOkWgpgqbg=3D=3D?= X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: f00bc7fd-01d3-4602-0e43-08da642c70fe X-MS-Exchange-CrossTenant-AuthSource: CY4PR1801MB1910.namprd18.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Jul 2022 17:32:07.5882 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR18MB2895 X-Spam-Status: No, score=-11.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, FREEMAIL_REPLYTO, FREEMAIL_REPLYTO_END_DIGIT, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS, TXREP, T_FILL_THIS_FORM_SHORT, 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@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 Jul 2022 17:32:12 -0000 --- gcc/analyzer/sm-fd.cc | 231 ++++++++++++++++++++++++--- gcc/c-family/c-attribs.cc | 63 ++++++++ gcc/testsuite/gcc.dg/analyzer/fd-5.c | 44 +++++ gcc/testsuite/gcc.dg/analyzer/fd-6.c | 4 + 4 files changed, 322 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/analyzer/fd-5.c create mode 100644 gcc/testsuite/gcc.dg/analyzer/fd-6.c diff --git a/gcc/analyzer/sm-fd.cc b/gcc/analyzer/sm-fd.cc index 8e4300b06e2..bdc807160cc 100644 --- a/gcc/analyzer/sm-fd.cc +++ b/gcc/analyzer/sm-fd.cc @@ -39,10 +39,13 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/analyzer-selftests.h"=0D #include "tristate.h"=0D #include "selftest.h"=0D +#include "stringpool.h"=0D +#include "attribs.h"=0D #include "analyzer/call-string.h"=0D #include "analyzer/program-point.h"=0D #include "analyzer/store.h"=0D #include "analyzer/region-model.h"=0D +#include "bitmap.h"=0D =0D #if ENABLE_ANALYZER=0D =0D @@ -59,6 +62,13 @@ enum access_mode WRITE_ONLY=0D };=0D =0D +enum fd_access_direction=0D +{=0D + DIR_READ_WRITE,=0D + DIR_READ,=0D + DIR_WRITE=0D +};=0D +=0D class fd_state_machine : public state_machine=0D {=0D public:=0D @@ -104,6 +114,8 @@ public: bool is_readonly_fd_p (state_t s) const;=0D bool is_writeonly_fd_p (state_t s) const;=0D enum access_mode get_access_mode_from_flag (int flag) const;=0D + void inform_filedescriptor_attribute (tree callee_fndecl, int arg,=0D + fd_access_direction fd_dir) const;= =0D =0D /* State for a constant file descriptor (>=3D 0) */=0D state_t m_constant_fd;=0D @@ -146,7 +158,7 @@ private: void check_for_open_fd (sm_context *sm_ctxt, const supernode *node,=0D const gimple *stmt, const gcall *call,=0D const tree callee_fndecl,=0D - enum access_direction access_fn) const;=0D + enum fd_access_direction access_fn) const;=0D =0D void make_valid_transitions_on_condition (sm_context *sm_ctxt,=0D const supernode *node,=0D @@ -156,6 +168,12 @@ private: const supernode *node,=0D const gimple *stmt,=0D const svalue *lhs) const;=0D + bitmap get_fd_attrs (const char *attr_name, tree callee_fndecl) const;=0D + void check_for_fd_attrs (sm_context *sm_ctxt, const supernode *node,=0D + const gimple *stmt, const gcall *call,=0D + const tree callee_fndecl, bitmap argmap,=0D + fd_access_direction fd_attr_access_dir) const;=0D +=0D };=0D =0D /* Base diagnostic class relative to fd_state_machine. */=0D @@ -294,10 +312,10 @@ class fd_access_mode_mismatch : public fd_diagnostic {=0D public:=0D fd_access_mode_mismatch (const fd_state_machine &sm, tree arg,=0D - enum access_direction fd_dir,=0D - const tree callee_fndecl)=0D + enum fd_access_direction fd_dir,=0D + const tree callee_fndecl, bool attr, int arg_id= x)=0D : fd_diagnostic (sm, arg), m_fd_dir (fd_dir),=0D - m_callee_fndecl (callee_fndecl)=0D + m_callee_fndecl (callee_fndecl), m_attr (attr), m_arg_idx (arg_idx= )=0D =0D {=0D }=0D @@ -317,19 +335,27 @@ public: bool=0D emit (rich_location *rich_loc) final override=0D {=0D + bool warned;=0D switch (m_fd_dir)=0D {=0D case DIR_READ:=0D - return warning_at (rich_loc, get_controlling_option (),=0D + warned =3D warning_at (rich_loc, get_controlling_option (),=0D "%qE on % file descriptor %qE",=0D m_callee_fndecl, m_arg);=0D + break;=0D case DIR_WRITE:=0D - return warning_at (rich_loc, get_controlling_option (),=0D + warned =3D warning_at (rich_loc, get_controlling_option (),=0D "%qE on % file descriptor %qE",=0D m_callee_fndecl, m_arg);=0D + break;=0D default:=0D gcc_unreachable ();=0D }=0D + if (warned && m_attr)=0D + {=0D + m_sm.inform_filedescriptor_attribute (m_callee_fndecl, m_arg_idx, = m_fd_dir);=0D + }=0D + return warned;=0D }=0D =0D bool=0D @@ -359,8 +385,10 @@ public: }=0D =0D private:=0D - enum access_direction m_fd_dir;=0D + enum fd_access_direction m_fd_dir;=0D const tree m_callee_fndecl;=0D + bool m_attr;=0D + int m_arg_idx;=0D };=0D =0D class double_close : public fd_diagnostic=0D @@ -422,8 +450,9 @@ class fd_use_after_close : public fd_diagnostic {=0D public:=0D fd_use_after_close (const fd_state_machine &sm, tree arg,=0D - const tree callee_fndecl)=0D - : fd_diagnostic (sm, arg), m_callee_fndecl (callee_fndecl)=0D + const tree callee_fndecl, bool attr, int arg_idx)=0D + : fd_diagnostic (sm, arg), m_callee_fndecl (callee_fndecl), m_attr (= attr),=0D + m_arg_idx (arg_idx)=0D {=0D }=0D =0D @@ -439,12 +468,27 @@ public: return OPT_Wanalyzer_fd_use_after_close;=0D }=0D =0D + bool=0D + subclass_equal_p (const pending_diagnostic &base_other) const override=0D + {=0D + const fd_use_after_close &sub_other=0D + =3D (const fd_use_after_close &)base_other;=0D + return (same_tree_p (m_arg, sub_other.m_arg)=0D + && m_callee_fndecl =3D=3D sub_other.m_callee_fndecl=0D + && m_attr =3D=3D sub_other.m_attr=0D + && m_arg_idx =3D=3D sub_other.m_arg_idx);=0D + }=0D +=0D bool=0D emit (rich_location *rich_loc) final override=0D {=0D - return warning_at (rich_loc, get_controlling_option (),=0D + bool warned;=0D + warned =3D warning_at (rich_loc, get_controlling_option (),=0D "%qE on closed file descriptor %qE", m_callee_fndec= l,=0D m_arg);=0D + if (warned && m_attr)=0D + m_sm.inform_filedescriptor_attribute (m_callee_fndecl, m_arg_idx, DI= R_READ_WRITE);=0D + return warned;=0D }=0D =0D label_text=0D @@ -466,17 +510,19 @@ public: describe_final_event (const evdesc::final_event &ev) final override=0D {=0D if (m_first_close_event.known_p ())=0D - return ev.formatted_print (=0D - "%qE on closed file descriptor %qE; %qs was at %@", m_callee_fnd= ecl,=0D - m_arg, "close", &m_first_close_event);=0D - else=0D - return ev.formatted_print ("%qE on closed file descriptor %qE",=0D - m_callee_fndecl, m_arg);=0D + return ev.formatted_print (=0D + "%qE on closed file descriptor %qE; %qs was at %@", m_callee_f= ndecl,=0D + m_arg, "close", &m_first_close_event);=0D + else=0D + return ev.formatted_print ("%qE on closed file descriptor %qE",=0D + m_callee_fndecl, m_arg);=0D }=0D =0D private:=0D diagnostic_event_id_t m_first_close_event;=0D const tree m_callee_fndecl;=0D + bool m_attr;=0D + int m_arg_idx;=0D };=0D =0D class unchecked_use_of_fd : public fd_diagnostic=0D @@ -543,8 +589,38 @@ public: private:=0D diagnostic_event_id_t m_first_open_event;=0D const tree m_callee_fndecl;=0D + =0D };=0D =0D +/* Issue a note regarding misuse of a file descriptor.=0D + ARG_IDX here is 0-based.=0D + */=0D +void=0D +fd_state_machine::inform_filedescriptor_attribute (=0D + tree callee_fndecl, int arg_idx, fd_access_direction fd_dir) const=0D +{=0D + switch (fd_dir)=0D + {=0D + case READ_WRITE:=0D + inform (DECL_SOURCE_LOCATION (callee_fndecl),=0D + "argument %d of %qD must be an open file descriptor", arg_id= x + 1,=0D + callee_fndecl);=0D + break;=0D + case DIR_WRITE:=0D + inform (DECL_SOURCE_LOCATION (callee_fndecl),=0D + "argument %d of %qD must be a read-only file descriptor",=0D + arg_idx + 1, callee_fndecl);=0D + break;=0D + case DIR_READ:=0D + inform (DECL_SOURCE_LOCATION (callee_fndecl),=0D + "argument %d of %qD must be a write-only file descriptor",=0D + arg_idx + 1, callee_fndecl);=0D + break;=0D + }=0D +}=0D +=0D +=0D +=0D fd_state_machine::fd_state_machine (logger *logger)=0D : state_machine ("file-descriptor", logger),=0D m_constant_fd (add_state ("fd-constant")),=0D @@ -647,11 +723,124 @@ fd_state_machine::on_stmt (sm_context *sm_ctxt, cons= t supernode *node, on_read (sm_ctxt, node, stmt, call, callee_fndecl);=0D return true;=0D } // "read"=0D +=0D + // Handle __attribute__((filedescriptor))=0D + {=0D + bitmap argmap =3D get_fd_attrs ("accesses_fd", callee_fndecl);= =0D + if (argmap)=0D + check_for_fd_attrs (sm_ctxt, node, stmt, call, callee_fndecl= , argmap, DIR_READ_WRITE);=0D + =0D + bitmap read_argmap =3D get_fd_attrs ("reads_from_fd", callee_f= ndecl);=0D + if(read_argmap)=0D + check_for_fd_attrs (sm_ctxt, node, stmt, call, callee_fndecl= , read_argmap, DIR_READ);=0D + =0D + bitmap write_argmap =3D get_fd_attrs ("writes_to_fd", callee_f= ndecl);=0D + if (write_argmap)=0D + check_for_fd_attrs (sm_ctxt, node, stmt, call, callee_fndecl= , write_argmap, DIR_WRITE);=0D + =0D + return true;=0D + }=0D + =0D }=0D =0D return false;=0D }=0D =0D +void=0D +fd_state_machine::check_for_fd_attrs (sm_context *sm_ctxt,=0D + const supernode *node, const gimple = *stmt,=0D + const gcall *call,=0D + const tree callee_fndecl, bitmap arg= map,=0D + fd_access_direction fd_attr_access_d= ir) const=0D +{=0D + for (unsigned i =3D 0; i < gimple_call_num_args (stmt); i++)=0D + {=0D + unsigned int arg_idx =3D i;=0D + tree arg =3D gimple_call_arg (stmt, i);=0D + tree diag_arg =3D sm_ctxt->get_diagnostic_tree (arg);=0D + state_t state =3D sm_ctxt->get_state (stmt, arg);=0D + if (TREE_CODE (TREE_TYPE (arg)) !=3D INTEGER_TYPE)=0D + continue;=0D + if (bitmap_bit_p (argmap, arg_idx)) // check if the arg is any of th= e file=0D + // descriptor attributes=0D + {=0D +=0D + if (is_closed_fd_p (state))=0D + {=0D +=0D + sm_ctxt->warn (node, stmt, arg,=0D + new fd_use_after_close (*this, diag_arg,=0D + callee_fndecl, true,= =0D + arg_idx));=0D + continue;=0D + }=0D + else=0D + {=0D + if (!(is_valid_fd_p (state) || (state =3D=3D m_stop)))=0D + {=0D + if (!is_constant_fd_p (state))=0D + sm_ctxt->warn (node, stmt, arg,=0D + new unchecked_use_of_fd (*this, diag_ar= g,=0D + callee_fndecl)= );=0D + }=0D + }=0D + }=0D + switch (fd_attr_access_dir)=0D + {=0D + case DIR_READ:=0D + if (bitmap_bit_p (argmap, arg_idx)) // check if the arg is marke= d by=0D + // reads_from_fd attribute=0D + {=0D + if (is_writeonly_fd_p (state))=0D + {=0D + sm_ctxt->warn (node, stmt, arg,=0D + new fd_access_mode_mismatch (*this, diag_= arg,=0D + DIR_WRITE,=0D + callee_fndec= l, true, i));=0D + }=0D + }=0D + break;=0D + case DIR_WRITE:=0D + if (bitmap_bit_p (argmap, arg_idx)) // check if the arg is marke= d by=0D + // writes_to_fd attribute=0D + {=0D + if (is_readonly_fd_p (state))=0D + {=0D + sm_ctxt->warn (node, stmt, arg,=0D + new fd_access_mode_mismatch (=0D + *this, diag_arg, DIR_READ, callee_fnd= ecl, true, i));=0D + }=0D + }=0D + break;=0D + default:=0D + gcc_unreachable ();=0D + }=0D + }=0D +}=0D +=0D +bitmap=0D +fd_state_machine::get_fd_attrs (const char *attr_name, tree callee_fndecl)= const=0D +{=0D + bitmap argmap =3D NULL;=0D + tree attrs =3D TYPE_ATTRIBUTES (TREE_TYPE (callee_fndecl));=0D + attrs =3D lookup_attribute (attr_name, attrs);=0D + if (!attrs)=0D + return argmap;=0D +=0D + if (!TREE_VALUE (attrs))=0D + return argmap;=0D +=0D + argmap =3D BITMAP_ALLOC (NULL);=0D +=0D + for (tree idx =3D TREE_VALUE (attrs); idx; idx =3D TREE_CHAIN (idx))=0D + {=0D + unsigned int val =3D TREE_INT_CST_LOW (TREE_VALUE (idx)) - 1;=0D + bitmap_set_bit (argmap, val);=0D + }=0D + return argmap;=0D +}=0D +=0D +=0D void=0D fd_state_machine::on_open (sm_context *sm_ctxt, const supernode *node,=0D const gimple *stmt, const gcall *call) const=0D @@ -729,7 +918,7 @@ void fd_state_machine::check_for_open_fd (=0D sm_context *sm_ctxt, const supernode *node, const gimple *stmt,=0D const gcall *call, const tree callee_fndecl,=0D - enum access_direction callee_fndecl_dir) const=0D + enum fd_access_direction callee_fndecl_dir) const=0D {=0D tree arg =3D gimple_call_arg (call, 0);=0D tree diag_arg =3D sm_ctxt->get_diagnostic_tree (arg);=0D @@ -738,7 +927,7 @@ fd_state_machine::check_for_open_fd ( if (is_closed_fd_p (state))=0D {=0D sm_ctxt->warn (node, stmt, arg,=0D - new fd_use_after_close (*this, diag_arg, callee_fndec= l));=0D + new fd_use_after_close (*this, diag_arg, callee_fndec= l, false, -1));=0D }=0D =0D else=0D @@ -758,7 +947,7 @@ fd_state_machine::check_for_open_fd ( tree diag_arg =3D sm_ctxt->get_diagnostic_tree (arg);=0D sm_ctxt->warn (node, stmt, arg,=0D new fd_access_mode_mismatch (=0D - *this, diag_arg, DIR_WRITE, callee_fndecl= ));=0D + *this, diag_arg, DIR_WRITE, callee_fndecl= , false, -1));=0D }=0D =0D break;=0D @@ -769,9 +958,11 @@ fd_state_machine::check_for_open_fd ( tree diag_arg =3D sm_ctxt->get_diagnostic_tree (arg);=0D sm_ctxt->warn (node, stmt, arg,=0D new fd_access_mode_mismatch (=0D - *this, diag_arg, DIR_READ, callee_fndecl)= );=0D + *this, diag_arg, DIR_READ, callee_fndecl,= false, -1));=0D }=0D break;=0D + default:=0D + gcc_unreachable ();=0D }=0D }=0D }=0D diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index c8d96723f4c..84f29987bc6 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -173,6 +173,10 @@ static tree handle_objc_nullability_attribute (tree *,= tree, tree, int, bool *); static tree handle_signed_bool_precision_attribute (tree *, tree, tree, in= t, bool *); static tree handle_retain_attribute (tree *, tree, tree, int, bool *); +static tree handle_accesses_fd_attribute (tree *, tree, tree, int, bool *); +static tree handle_reads_from_fd_attribute (tree *, tree, tree, int, bool = *); +static tree handle_writes_to_fd_attribute (tree *, tree, tree, int, bool *= ); + =20 /* Helper to define attribute exclusions. */ #define ATTR_EXCL(name, function, type, variable) \ @@ -427,6 +431,12 @@ const struct attribute_spec c_common_attribute_table[]= =3D handle_tls_model_attribute, NULL }, { "nonnull", 0, -1, false, true, true, false, handle_nonnull_attribute, NULL }, + { "accesses_fd", 0, -1, false, true, true, false, + handle_accesses_fd_attribute, NULL},=20=20=20=20=20=20 + { "reads_from_fd", 0, -1, false, true, true, false, + handle_reads_from_fd_attribute, NULL}, + { "writes_to_fd", 0, -1, false, true, true, false, + handle_writes_to_fd_attribute, NULL},=20=20=20=20=20=20=20=20= =20 { "nonstring", 0, 0, true, false, false, false, handle_nonstring_attribute, NULL }, { "nothrow", 0, 0, true, false, false, false, @@ -4521,6 +4531,59 @@ handle_nonnull_attribute (tree *node, tree name, return NULL_TREE; } =20 +/* Handle the "accesses_fd" attribute */ +static tree +handle_accesses_fd_attribute (tree *node, tree name, tree args, + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + tree type =3D *node; + if (!args) + { + if (!prototype_p (type)) + { + error ("%qE attribute without arguments on a non-prototype", nam= e); + *no_add_attrs =3D true; + } + return NULL_TREE; + } + + for (int i =3D 1; args; ++i) + { + tree pos =3D TREE_VALUE (args); + tree next =3D TREE_CHAIN (args); + if (tree val =3D positional_argument (type, name, pos, INTEGER_TYPE, + next || i > 1 ? i : 0)) + TREE_VALUE (args) =3D val; + else + { + *no_add_attrs =3D true; + break; + } + args =3D next; + } +} +=20=20 + + +static tree +handle_reads_from_fd_attribute (tree *node, tree name, tree ARG_UNUSED (ar= gs), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + // TODO: valiadate usage of this attribute + return NULL_TREE; +} + +static tree +handle_writes_to_fd_attribute (tree *node, tree name, tree ARG_UNUSED (arg= s), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + // TODO: validate usage of this attribute + return NULL_TREE; +} + + + + /* Handle the "nonstring" variable attribute. */ =20 static tree diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-5.c b/gcc/testsuite/gcc.dg/an= alyzer/fd-5.c new file mode 100644 index 00000000000..e597ba2367a --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/fd-5.c @@ -0,0 +1,44 @@ +int open(const char *, int mode);=0D +void close(int fd);=0D +int write (int fd, void *buf, int nbytes);=0D +int read (int fd, void *buf, int nbytes);=0D +=0D +#define O_RDONLY 0=0D +#define O_WRONLY 1=0D +#define O_RDWR 2=0D +=0D +void f (int fd) __attribute__((accesses_fd(1))); /* { dg-message "argument= 1 of 'f' must be an open file descriptor" } */=0D +=0D +void=0D +test_1 (const char *path)=0D +{=0D + int fd =3D open (path, O_RDWR);=0D + close(fd);=0D + f(fd); /* { dg-warning "'f' on closed file descriptor 'fd'" } */=0D + /* { dg-message "\\(3\\) 'f' on closed file descriptor 'fd'; 'close'= was at \\(2\\)" "" { target *-*-* } .-1 } */=0D +}=0D +=0D +void g (int fd) __attribute__((reads_from_fd(1))); /* { dg-message "argume= nt 1 of 'g' must be a read-only file descriptor" } */=0D +=0D +void=0D +test_2 (const char *path)=0D +{=0D + int fd =3D open (path, O_WRONLY);=0D + if (fd !=3D -1)=0D + {=0D + g (fd); /* { dg-warning "'g' on 'write-only' file descriptor 'fd'" } *= /=0D + }=0D + close (fd);=0D +}=0D +=0D +void h (int fd) __attribute__((writes_to_fd(1))); /* { dg-message "argumen= t 1 of 'h' must be a write-only file descriptor" } */=0D +void=0D +test_3 (const char *path)=0D +{=0D + int fd =3D open (path, O_RDONLY);=0D + if (fd !=3D -1)=0D + {=0D + h (fd); /* { dg-warning "'h' on 'read-only' file descriptor 'fd'" } */= =0D + }=0D + close(fd);=0D +} \ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-6.c b/gcc/testsuite/gcc.dg/an= alyzer/fd-6.c new file mode 100644 index 00000000000..9c0b55086a9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/fd-6.c @@ -0,0 +1,4 @@ +=0D +int not_a_fn __attribute__ ((accesses_fd(1))); /* { dg-warning "'accesses_= fd' attribute only applies to function types" } */=0D +=0D +void f (char *p) __attribute__ ((accesses_fd(1))); /* { dg-warning "'acces= ses_fd' attribute argument value '1' refers to parameter type 'char \\\*'" = } */ \ No newline at end of file --=20 2.25.1