From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM10-MW2-obe.outbound.protection.outlook.com (mail-mw2nam10olkn2014.outbound.protection.outlook.com [40.92.42.14]) by sourceware.org (Postfix) with ESMTPS id 8E686385781B for ; Tue, 2 Aug 2022 16:34:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8E686385781B ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=V5tFM3fEeR2tjlUvut09XSZv5ZP385MwR8uh7uvYTb10YAoePdCldooZp2VJ4K9ZTmsnUyv0ADPmZE6F6r8S0YpK0o64t0weq28vMEPNQnvbuRvy9fv5aAZUFAcl2VZPPY9bVyF1Gp3/8UbvrmTGnYieqErALxB5Cl+W0mad9FlAlFkm89xR5sCSPaGVm3NViStCba+gTexd8g5MSypx/zGFHmwYulRdPYoSAvchFPazSpgHlTqceyg7Ks335gN4WYhhM2oUfXTcFhGxXbk+R19xo4JvQ4T4Oxi1WLZFM52G9vMTsbyYnZV+rybW08ugagfg1lqw25eqhCOG4ltOJA== 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=cM5GmDet1ut1Fl33RJ1X4crSSkwcDDl5tcsBz1otFi8=; b=H311JFFo+qWn40+mRNxcOpHoGA/hCXW4I73oVWB7K2I0kQQqburZuJo9g0/9X/GE9EoanJPzPSOfnZ3PeKttLeyvuxRjv8ZYCUpHxdsmLxXmBhenozZZ46K41HHhKUiL7jpaHtaT7oPewhuKf/UEBFT/XnVsoNGxfLx04Y24xZGOEsF+EkTwUqzfcibtZtAdeL0ZBTwZ8dJixmxZVknukhQyyOencDT1CG8d3rP0QEhvsfD3x337wKmxX67nn3qDfA/qYb32JSxjSnoB842OCLwHj3AsV3qyG7xHrol9/GrtPtGlbl5pzhxKVnGgaqPG3Vr0cdo7bExTv3HpQF9uJw== 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 BYAPR18MB2744.namprd18.prod.outlook.com (2603:10b6:a03:105::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5482.16; Tue, 2 Aug 2022 16:34:23 +0000 Received: from CY4PR1801MB1910.namprd18.prod.outlook.com ([fe80::c5c4:ae52:8e5f:e5c5]) by CY4PR1801MB1910.namprd18.prod.outlook.com ([fe80::c5c4:ae52:8e5f:e5c5%6]) with mapi id 15.20.5482.016; Tue, 2 Aug 2022 16:34:23 +0000 From: Immad Mir To: gcc-patches@gcc.gnu.org Cc: dmalcolm@redhat.com, mirimnan017@gmail.com, Immad Mir Subject: [PATCH] analyzer: support for creat, dup, dup2 and dup3 [PR106298] Date: Tue, 2 Aug 2022 22:04:00 +0530 Message-ID: X-Mailer: git-send-email 2.25.1 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-TMN: [P29347d4RtlycGmBBvYQAgV3r2KcUbkoyn8kRh2gLqW5WLDUtFQFTbJmoEWVMHud] X-ClientProxiedBy: PN0PR01CA0017.INDPRD01.PROD.OUTLOOK.COM (2603:1096:c01:4f::22) To CY4PR1801MB1910.namprd18.prod.outlook.com (2603:10b6:910:79::14) X-Microsoft-Original-Message-ID: <20220802163400.787-1-mirimmad@outlook.com> MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 2ca41268-17e9-43ff-69e4-08da74a4db78 X-MS-Exchange-SLBlob-MailProps: aa/WAlXx4eQ+Tn0oMqJO9QOwcQrbPxmt0zplisTr7n42X/51q4Hm3smdPJcGYzneIUAULQaNV+0t4fZPJh1EV7HxDNKySiiln3uyWw0FTcmEiv6aYKdR743VS1euwT+yRbUWKx4ZDCinvIUpE9wCNQ62Nax4pb0UeejaQB+Xm33UeL6eCfNWUXxluZrAlGL/CRSpFo1UCs/GIkLq8wODU/8xCIL9ggo7NHaI3bbEAexe8tWSuTTpoEBIBT2KGvwHtk2+T4asy0d0K2rEDdPWopOl54vJMiuTwrBmYB5EF3ADZyuxNeEGNn+At9hrYb8hPZ6iAi9Wsira++yDpcGSm9JKtROByJPs2d+QQZpeFImAYoVzeoeOUQPwn2SmwcI9nbLX2ygqvPOT0VnzDh4rZ7pwg/CRkjN48abmDoAj76NHAHmMMBRyEjDuL8aEPG7C95JR7p0KJUtsIwiMTpuStB7jePRIEVYRVl3oG7i6/U23KOZUFOQlP6H4IzTGLAOmJ6TESmqGoaRdHOCKD7qGEoxWj5TX636BdVnVGJk4f5NNkhAz8CrkUBbtl3Z1tkpLo9Ol+MhLeB2j2MuPsakC+zelxaJCbsNyXtwGXuzB3CljPPJk2Ha/oqfXHBU5ke40Lb+oWgeiDQhjBkH5t6nLgdbaMUTacNQdMZqZu5xgDuKsD44+w53RIGWB+ybddUpXeiHw3EmT3vsXZyd5y1LWikErJiGahiGKuhUryUV2uH6dyUi9sqKFtCdkFs95HZjJ7yV+roemjOY75Y4wNBR6QzhqiXm6Fyg8 X-MS-TrafficTypeDiagnostic: BYAPR18MB2744:EE_ X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 4lSottRIvAP/X3iA/hoZx5sR2NADdOclxvWlbhOKSA5qQooMHcalKQGSB88mDufkaVHqfnfzONg0xTCWWJfNN+YTuDB0b47UbpnB6WP42FJJYKbgyk65sPmclu8rvS2NCBSsRgSKX0i8NYEPG4HhQBQaUx1tZDXs9AdH5jCSu9kRoSaSDqxUFFqDmrcXZsnECo+KKZN+ZaM7GmIwvJ6ohtR/+stxkN2Ke34jaZogrWo3aZC8UDqq8yvIiO+OejxRNzpbD7TX8vBTG8U2QmpetecpqBlRcNsZJ2rE1jWQMiXTk3ON+OiICeYV7LDCfVhJEGD3Ql9RqlN12eX9datR5ydp5weDSh7iXwved3ui53Rrn0QGwq+g9jCdnMyCQTAQ/GVmwhpy8KLf/N5Y8m7laMFhyfRB8QlUG2CXlb+gVDdpcma2NSo9//oFvkYYDVOS9KBLvzawnL6tvtjbg+phgSEzkPWWoQRr42EjuQ8gfi41kJW6cjZWAPowJPCLhwCBHhN/v7tRhWDEvQDhYAN+lOHDsMq16rGWZzNLX9D7aKYovW02lgsXDe4wpJ7qVsW5Z2/j2hlYgfXE5KVllR+Lzn1Ksq3Ow1Trj6KkA9J7asMNTnqFvINZxDAS8522zNPk X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?OqMrRumrCjUMsA4+IJQ5ftHWH65ZbzkLscM9Z55LXizXzOj9BoPorVlPfpm1?= =?us-ascii?Q?3AGDSS9mpeFORVgDr3X9lny8ZBOwzgjQ0AeP055GY34bcAJtfuMkLcZqpyjl?= =?us-ascii?Q?CF95nS7mKvdOCSyNsw0D46cFN10YsfOOdqcCxw9yebn2ZiNcSwTUVnxBA2S/?= =?us-ascii?Q?5QcfvXoCrq/nDdctWw55zQJRsosfKwGSpeSFTcXtBZuXcNwtXD6LemkIOGAN?= =?us-ascii?Q?1b6YJufYwg/6yKrLK1ehWLsa3+cxKDl6ho8GSiPH+A2+Z+C7wzJ/1ToRpxF1?= =?us-ascii?Q?W6Vsd4SHEn++44/MlxybMkL/l3McNkP9aUIUWPWaaBx5QZVHUdGreaTwKUtb?= =?us-ascii?Q?8S45Qf2CrZIhtXT2QIaJN8inISmDFcpM55apqNj2rS0NG669BiXaHDGO1RB5?= =?us-ascii?Q?Zdxs0K7CIz4B/LsyfRXDBeqwMR8V6pTBFMlMJIsMwZEulA0LaVroImEtBYYS?= =?us-ascii?Q?ufa1T1uzK0JkrU88knaTwmnYc3dso8CZDLGyyLQynfBemFjU6N2B41lrZOnf?= =?us-ascii?Q?bp+/MiiDjM/pITeftf72crnEvteCr9fmpjfmmMuRIVKXa7g0DErndW4qR5Nz?= =?us-ascii?Q?h9IyX36X81DnfPHpdWQu2zJX8O50FyO3d3nWQ+EY3W426XssFUOW74iKQssV?= =?us-ascii?Q?ozAyVe1At1zwk7FTQDgd+tgaJHWzMMvXm0eksWrTnmON/2898mLiSWVA5WB3?= =?us-ascii?Q?GmogwboO8LOiMb5IS7I8xZ/aDg9IAEoe0lfYy+/C5zXsct+qYpTqyZ0ypJmw?= =?us-ascii?Q?YtX6N+Uq2LMhrwyqMP4th7jmnRZWvLq1r1uF3uPkUqwTVNegu8kZZxex2A5B?= =?us-ascii?Q?itseeZ/Qe2iR4MhlAnVZGORf6GhGgDPz5KM/kSQeGplruDEzkgta9M7e860L?= =?us-ascii?Q?SFIabk6wdo7mT6pvsyMMy1HGwBw+8aYIctlXEF0EAD1lKW56KjLYHH1Wceua?= =?us-ascii?Q?2n8/XY/5WklfazKFJqyx4usqCtfoXWXJY2reMcm5rTQFwDLSxSFfGsiQl5rb?= =?us-ascii?Q?MuSC52xvjVWw0HYiUuAUjRPis9cqx9ICJs+4/KYfEjSdc1SmU8q6Rw5GdlRw?= =?us-ascii?Q?eclHKtD7pdKGrufHqlzfxlVOGkWKkfZ09ykgauCuw0qTrWbStYbcBzxM0rUm?= =?us-ascii?Q?JORPQulPRJ1YynyVYhKa0AM/8blnFaGgFzDbGC+HVMV4rJAcREvqFV6ijCCv?= =?us-ascii?Q?CaG6vHwsviSJUXBD3ecjIjeB/Nq0xmwmFdhs9wgMd8VsujheOMYDjRoUdxMr?= =?us-ascii?Q?9RJkzkAv8QfwnMnImb9RMDQFuE6EP4alh1Gz+C8KkNgWVsb43MpayRX19ju2?= =?us-ascii?Q?hZfy3go2KSJEHEf/Csn3jyqixGY34l4h29erG4AVK10yYQ=3D=3D?= X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 2ca41268-17e9-43ff-69e4-08da74a4db78 X-MS-Exchange-CrossTenant-AuthSource: CY4PR1801MB1910.namprd18.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 02 Aug 2022 16:34:23.8781 (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: BYAPR18MB2744 X-Spam-Status: No, score=-12.5 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_PASS, SPF_PASS, TXREP 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-List-Received-Date: Tue, 02 Aug 2022 16:34:29 -0000 This patch extends the state machine in sm-fd.cc to support creat, dup, dup2 and dup3 functions. Lightly tested on x86_64 Linux. gcc/analyzer/ChangeLog: PR analyzer/106298 * sm-fd.cc (fd_state_machine::on_open): Add creat, dup, dup2 and dup3 functions. (enum dup): New. (fd_state_machine::valid_to_unchecked_state): New. (fd_state_machine::on_creat): New. (fd_state_machine::on_dup): New. gcc/testsuite/ChangeLog: PR analyzer/106298 * gcc.dg/analyzer/fd-1.c: Add tests for 'creat'. * gcc.dg/analyzer/fd-2.c: Likewise. * gcc.dg/analyzer/fd-4.c: Likewise. * gcc.dg/analyzer/fd-dup-1.c: New tests. Signed-off-by: Immad Mir --- gcc/analyzer/sm-fd.cc | 129 ++++++++++++- gcc/testsuite/gcc.dg/analyzer/fd-1.c | 21 +++ gcc/testsuite/gcc.dg/analyzer/fd-2.c | 15 ++ gcc/testsuite/gcc.dg/analyzer/fd-4.c | 31 +++- gcc/testsuite/gcc.dg/analyzer/fd-dup-1.c | 223 +++++++++++++++++++++++ 5 files changed, 415 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/analyzer/fd-dup-1.c diff --git a/gcc/analyzer/sm-fd.cc b/gcc/analyzer/sm-fd.cc index ed923ade100..8bb76d72b05 100644 --- a/gcc/analyzer/sm-fd.cc +++ b/gcc/analyzer/sm-fd.cc @@ -69,6 +69,14 @@ enum access_directions DIRS_WRITE }; +/* An enum for distinguishing between dup, dup2 and dup3. */ +enum dup +{ + DUP_1, + DUP_2, + DUP_3 +}; + class fd_state_machine : public state_machine { public: @@ -114,7 +122,9 @@ public: bool is_readonly_fd_p (state_t s) const; bool is_writeonly_fd_p (state_t s) const; enum access_mode get_access_mode_from_flag (int flag) const; - + /* Function for one-to-one correspondence between valid + and unchecked states. */ + state_t valid_to_unchecked_state (state_t state) const; /* State for a constant file descriptor (>= 0) */ state_t m_constant_fd; @@ -147,6 +157,8 @@ public: private: void on_open (sm_context *sm_ctxt, const supernode *node, const gimple *stmt, const gcall *call) const; + void on_creat (sm_context *sm_ctxt, const supernode *node, const gimple *stmt, + const gcall *call) const; void on_close (sm_context *sm_ctxt, const supernode *node, const gimple *stmt, const gcall *call) const; void on_read (sm_context *sm_ctxt, const supernode *node, const gimple *stmt, @@ -170,6 +182,9 @@ private: const gimple *stmt, const gcall *call, const tree callee_fndecl, const char *attr_name, access_directions fd_attr_access_dir) const; + void check_for_dup (sm_context *sm_ctxt, const supernode *node, + const gimple *stmt, const gcall *call, const tree callee_fndecl, + enum dup kind) const; }; /* Base diagnostic class relative to fd_state_machine. */ @@ -723,6 +738,20 @@ fd_state_machine::is_constant_fd_p (state_t state) const return (state == m_constant_fd); } +fd_state_machine::state_t +fd_state_machine::valid_to_unchecked_state (state_t state) const +{ + if (state == m_valid_read_write) + return m_unchecked_read_write; + else if (state == m_valid_write_only) + return m_unchecked_write_only; + else if (state == m_valid_read_only) + return m_unchecked_read_only; + else + gcc_unreachable (); + return NULL; +} + bool fd_state_machine::on_stmt (sm_context *sm_ctxt, const supernode *node, const gimple *stmt) const @@ -736,6 +765,11 @@ fd_state_machine::on_stmt (sm_context *sm_ctxt, const supernode *node, return true; } // "open" + if (is_named_call_p (callee_fndecl, "creat", call, 2)) + { + on_creat (sm_ctxt, node, stmt, call); + } // "creat" + if (is_named_call_p (callee_fndecl, "close", call, 1)) { on_close (sm_ctxt, node, stmt, call); @@ -754,6 +788,23 @@ fd_state_machine::on_stmt (sm_context *sm_ctxt, const supernode *node, return true; } // "read" + if (is_named_call_p (callee_fndecl, "dup", call, 1)) + { + check_for_dup (sm_ctxt, node, stmt, call, callee_fndecl, DUP_1); + return true; + } + + if (is_named_call_p (callee_fndecl, "dup2", call, 2)) + { + check_for_dup (sm_ctxt, node, stmt, call, callee_fndecl, DUP_2); + return true; + } + + if (is_named_call_p (callee_fndecl, "dup3", call, 3)) + { + check_for_dup (sm_ctxt, node, stmt, call, callee_fndecl, DUP_3); + return true; + } { // Handle __attribute__((fd_arg)) @@ -899,6 +950,78 @@ fd_state_machine::on_open (sm_context *sm_ctxt, const supernode *node, } } +void +fd_state_machine::on_creat (sm_context *sm_ctxt, const supernode *node, + const gimple *stmt, const gcall *call) const +{ + tree lhs = gimple_call_lhs (call); + if (lhs) + sm_ctxt->on_transition (node, stmt, lhs, m_start, m_unchecked_write_only); + else + sm_ctxt->warn (node, stmt, NULL_TREE, new fd_leak (*this, NULL_TREE)); +} + +void +fd_state_machine::check_for_dup (sm_context *sm_ctxt, const supernode *node, + const gimple *stmt, const gcall *call, + const tree callee_fndecl, enum dup kind) const +{ + tree lhs = gimple_call_lhs (call); + tree arg_1 = gimple_call_arg (call, 0); + state_t state_arg_1 = sm_ctxt->get_state (stmt, arg_1); + if (state_arg_1 == m_stop) + return; + if (!(is_constant_fd_p (state_arg_1) || is_valid_fd_p (state_arg_1))) + { + check_for_open_fd (sm_ctxt, node, stmt, call, callee_fndecl, + DIRS_READ_WRITE); + if (kind == DUP_1) + return; + } + switch (kind) + { + case DUP_1: + if (lhs) + { + if (is_constant_fd_p (state_arg_1)) + sm_ctxt->set_next_state (stmt, lhs, m_unchecked_read_write); + else + sm_ctxt->set_next_state (stmt, lhs, + valid_to_unchecked_state (state_arg_1)); + } + break; + + case DUP_2: + case DUP_3: + tree arg_2 = gimple_call_arg (call, 1); + state_t state_arg_2 = sm_ctxt->get_state (stmt, arg_2); + tree diag_arg_2 = sm_ctxt->get_diagnostic_tree (arg_2); + if (state_arg_2 == m_stop) + return; + /* Check if -1 was passed as second argument to dup2. */ + if (!(is_constant_fd_p (state_arg_2) || is_valid_fd_p (state_arg_2))) + { + sm_ctxt->warn ( + node, stmt, arg_2, + new fd_use_without_check (*this, diag_arg_2, callee_fndecl)); + return; + } + /* dup2 returns value of its second argument on success.But, the + access mode of the returned file descriptor depends on the duplicated + file descriptor i.e the first argument. */ + if (lhs) + { + if (is_constant_fd_p (state_arg_1)) + sm_ctxt->set_next_state (stmt, lhs, m_unchecked_read_write); + else + sm_ctxt->set_next_state (stmt, lhs, + valid_to_unchecked_state (state_arg_1)); + } + + break; + } +} + void fd_state_machine::on_close (sm_context *sm_ctxt, const supernode *node, const gimple *stmt, const gcall *call) const @@ -964,6 +1087,8 @@ fd_state_machine::check_for_open_fd ( } switch (callee_fndecl_dir) { + case DIRS_READ_WRITE: + break; case DIRS_READ: if (is_writeonly_fd_p (state)) { @@ -984,8 +1109,6 @@ fd_state_machine::check_for_open_fd ( *this, diag_arg, DIRS_READ, callee_fndecl)); } break; - default: - gcc_unreachable (); } } } diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-1.c b/gcc/testsuite/gcc.dg/analyzer/fd-1.c index 8a72e63833c..5b85a3316e8 100644 --- a/gcc/testsuite/gcc.dg/analyzer/fd-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/fd-1.c @@ -3,6 +3,13 @@ int open(const char *, int mode); #define O_WRONLY 1 #define O_RDWR 2 +typedef enum { + S_IRWXU + // etc +} mode_t; + +int creat (const char *, mode_t mode); + void test_1 (const char *path) { @@ -37,3 +44,17 @@ void test_4 (const char *path) /* { dg-message "\\(1\\) leaks here" "" { target *-*-* } .-1 } */ } +void +test_5 (const char *path, mode_t mode) +{ + creat (path, mode); /* { dg-warning "leak of file descriptor \\\[CWE-775\\\]" } */ +} + +void +test_6 (const char *path, mode_t mode) +{ + int fd = creat (path, mode); + return; /* { dg-warning "leak of file descriptor 'fd' \\\[CWE-775\\\]" } */ +} + + diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-2.c b/gcc/testsuite/gcc.dg/analyzer/fd-2.c index d794b460a2e..10c9ecdb09d 100644 --- a/gcc/testsuite/gcc.dg/analyzer/fd-2.c +++ b/gcc/testsuite/gcc.dg/analyzer/fd-2.c @@ -5,6 +5,13 @@ void close(int fd); #define O_RDWR 2 #define STDIN 0 +typedef enum { + S_IRWXU + // etc +} mode_t; + +int creat (const char *, mode_t mode); + void test_1 (const char *path) { @@ -46,4 +53,12 @@ test_4 () int fd = -1; close(fd); close(fd); +} + +void +test_5 (const char *path, mode_t mode) +{ + int fd = creat (path, mode); + close(fd); + close(fd); /* { dg-warning "double 'close' of file descriptor 'fd' \\\[CWE-1341\\\]" "warning" } */ } \ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-4.c b/gcc/testsuite/gcc.dg/analyzer/fd-4.c index ecd787caff7..6b8fca5408f 100644 --- a/gcc/testsuite/gcc.dg/analyzer/fd-4.c +++ b/gcc/testsuite/gcc.dg/analyzer/fd-4.c @@ -9,6 +9,12 @@ int read (int fd, void *buf, int nbytes); #define O_WRONLY 1 #define O_RDWR 2 +typedef enum { + S_IRWXU + // etc +} mode_t; + +int creat (const char *, mode_t mode); void test_1 (const char *path, void *buf) @@ -69,4 +75,27 @@ test_5 (const char *path) int fd = open (path, O_RDWR); close(fd); printf("%d", fd); /* { dg-bogus "'printf' on a closed file descriptor 'fd'" } */ -} \ No newline at end of file +} + + +void +test_6 (const char *path, mode_t mode, void *buf) +{ + int fd = creat (path, mode); + if (fd != -1) + { + read (fd, buf, 1); /* { dg-warning "'read' on write-only file descriptor 'fd'" } */ + close(fd); + } +} + +void +test_7 (const char *path, mode_t mode, void *buf) +{ + int fd = creat (path, mode); + if (fd != -1) + { + write (fd, buf, 1); + close(fd); + } +} diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-dup-1.c b/gcc/testsuite/gcc.dg/analyzer/fd-dup-1.c new file mode 100644 index 00000000000..eba2570568f --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/fd-dup-1.c @@ -0,0 +1,223 @@ +int open(const char *, int mode); +void close(int fd); +int dup (int old_fd); +int dup2 (int old_fd, int new_fd); +int dup3 (int old_fd, int new_fd, int flags); +int write (int fd, void *buf, int nbytes); +int read (int fd, void *buf, int nbytes); +#define O_RDONLY 0 +#define O_WRONLY 1 +#define O_RDWR 2 + +void test_1 (const char *path) +{ + int old_fd = open (path, O_RDWR); + int new_fd = dup (old_fd); /* { dg-warning "'dup' on possibly invalid file descriptor 'old_fd'" } */ + close(old_fd); + close(new_fd); +} + +void test_2 (const char *path) +{ + int old_fd = open (path, O_RDWR); + if (old_fd != -1) + { + int new_fd = dup (old_fd); + close(old_fd); + return; /* { dg-warning "leak of file descriptor 'new_fd' \\\[CWE-775\\\]" } */ + } +} + +void test_3 (const char *path, void *buf) +{ + int old_fd = open (path, O_RDWR); + if (old_fd != -1) + { + int new_fd = dup (old_fd); + write (new_fd, buf, 1); /* { dg-warning "'write' on possibly invalid file descriptor 'new_fd'" } */ + close (new_fd); + close(old_fd); + } +} + + +void test_5 (const char *path, void *buf) +{ + int old_fd = open (path, O_RDWR); + if (old_fd != -1) + { + int new_fd = dup (old_fd); + if (new_fd != -1) + { + write (new_fd, buf, 1); + close (new_fd); + + } + close(old_fd); + } +} + + +void test_7 (const char *path) +{ + int old_fd = open (path, O_RDWR); + dup2 (old_fd, 4); /* { dg-warning "'dup2' on possibly invalid file descriptor 'old_fd'" } */ + close(old_fd); +} + +void test_8 (const char *path) +{ + int old_fd = open (path, O_RDWR); + int new_fd = open (path, O_RDWR); + if (old_fd != -1) + { + dup2 (old_fd, new_fd); /* { dg-warning "'dup2' on possibly invalid file descriptor 'new_fd'" } */ + close (old_fd); + } + close (new_fd); +} + +void test_9 (const char *path, void *buf) +{ + int old_fd = open (path, O_RDWR); + + if (old_fd != -1) + { + int new_fd = open (path, O_RDWR); + if (new_fd != -1) + { + int lhs = dup2 (old_fd, new_fd); + write (lhs, buf, 1); /* { dg-warning "'write' on possibly invalid file descriptor 'lhs'" } */ + close(new_fd); + close(lhs); + } + close(old_fd); + } +} + +void test_10 (const char *path, int flags) +{ + int old_fd = open (path, O_RDWR); + int new_fd = open (path, O_RDWR); + if (old_fd != -1) + { + dup3 (old_fd, new_fd, flags); /* { dg-warning "'dup3' on possibly invalid file descriptor 'new_fd'" } */ + close(old_fd); + + } + close(new_fd); +} + +void test_11 (const char *path, int flags) +{ + int old_fd = open (path, O_RDWR); + int new_fd = open (path, O_RDWR); + if (new_fd != -1) + { + dup3 (old_fd, new_fd, flags); /* { dg-warning "'dup3' on possibly invalid file descriptor 'old_fd'" } */ + close(new_fd); + + } + close(old_fd); +} + +void test_12 (const char *path, void *buf) +{ + int old_fd = open (path, O_RDONLY); + if (old_fd != -1) + { + int new_fd = dup (old_fd); + if (new_fd != -1) + { + write (new_fd, buf, 1); /* { dg-warning "'write' on read-only file descriptor 'new_fd'" } */ + close(new_fd); + } + close(old_fd); + } +} + +void test_13 (const char *path, void *buf) +{ + int old_fd = open (path, O_WRONLY); + if (old_fd != -1) + { + int new_fd = dup (old_fd); + if (new_fd != -1) + { + read (new_fd, buf, 1); /* { dg-warning "'read' on write-only file descriptor 'new_fd'" } */ + close(new_fd); + } + close(old_fd); + } +} + +void test_14 (const char *path, void *buf) +{ + int old_fd = open (path, O_RDWR); + if (old_fd != -1) + { + int new_fd = dup (old_fd); + if (new_fd != -1) + { + write (new_fd, buf, 1); + read (new_fd, buf, 1); + close(new_fd); + } + close(old_fd); + } +} + +void test_15 (void *buf) +{ + int fd = dup(0); + read (fd, buf, 1); /* { dg-warning "'read' on possibly invalid file descriptor 'fd'" } */ + close(fd); +} + +void test_16 (void *buf) +{ + int fd = dup(1); + if (fd != -1) + { + write (fd, buf, 1); + close (fd); + } +} + +void test_17 (const char *path) +{ + int fd = open (path, O_RDWR); + close(fd); + dup (fd); /* { dg-warning "'dup' on closed file descriptor 'fd'" } */ + dup2 (fd, 4); /* { dg-warning "'dup2' on closed file descriptor 'fd'" } */ +} + +void +test_18 (const char *path, void *buf) +{ + int fd = open (path, O_RDWR); + if (fd != -1) + { + int fd2 = dup2 (fd, 3); + read (fd2, buf, 1); /* { dg-warning "'read' on possibly invalid file descriptor 'fd2'" } */ + close(fd); + close(fd2); + } +} + +void +test_19 (const char *path, void *buf) +{ + int fd = open (path, O_WRONLY); + if (fd != -1) + { + int fd2 = dup2 (fd, 4); + if (fd2 != -1) + { + read (fd2, buf, 1); /* { dg-warning "'read' on write-only file descriptor 'fd2'" } */ + close(fd2); + } + close (fd); + } + +} \ No newline at end of file -- 2.25.1