From patchwork Sat Sep 10 22:19:52 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tim Lange X-Patchwork-Id: 1129 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5044:0:0:0:0:0 with SMTP id h4csp1297302wrt; Sat, 10 Sep 2022 15:21:43 -0700 (PDT) X-Google-Smtp-Source: AA6agR5WMAXevJ6sr+LGpxXgsQW2A0f0X1UKlFHEOKVMslkkWU6Olmjt1L/yXZkx4vRt0/bK7S7h X-Received: by 2002:a17:907:72c3:b0:770:8086:78ab with SMTP id du3-20020a17090772c300b00770808678abmr14092122ejc.229.1662848503218; Sat, 10 Sep 2022 15:21:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1662848503; cv=none; d=google.com; s=arc-20160816; b=cpJtzLCEJ2D9jeenDmN2WRMNqngbaqylpgz/LlJsTFsROGByoqe/N71kWIh8HWMr4V Ety128+ESAX1O/66dbK7mBcyvCrx41ZkFR1W7IuBfp9c9cpYHZVfSOcS6theH1QHvWHM 083DSa+XSBVpc4YRsvJJ7mRc6ft6Aa63y6m2W43LFgqLHVXjAK9un5kOqBkO5/rDvXkb qSG2lgKoaPOkl4CdX9IoGU4pI5UnidHXWyvOKo0VCoBEV+ps717OARjQDjLAxCLD9I6K ozsTPkDRhaP2xAHoIIJJjJH5de3OkDWo1TRizpi3AikxUpvBEA6GAMc3KrjPWSeZpbKB kZtg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:to:from:dkim-signature :dmarc-filter:delivered-to; bh=FIDKn8WJCs2iGa/GMJjVnaqI/FCkT8CJv8Ot91zxNec=; b=B9zcCstNyQ9Ge+9iFw5kR0WzRQ1gxEXaXNpaPXcJ5rJSkGOBjg/nI4WckR8dkcXoQX RIuVPnoGsHnzlTMDFQLvyKyas1UpZmGp2xZ1Auc1bENsWNJ80z3FCJxGCL8V7Vsty7Qy wzX2TWbEvrPPQWUtSYREvILnsfgaV/vMYKFpCzyF8WZLuDqEmFMHAOAVRWWg3bltJUwx 4hH/WaDaUcxOhReKuaUd0QlUgANGBbQbM/CcLvszmZdlOYsDLZLbhyp//AJ0ulpi6sz5 b2T16iRSOrCeS8XOQ3RcuUXEP9hkqhjgdhwhi9mizFpzv6pAXMbDnP7ozEmar2pZomLf dGVQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@tim-lange.me header.s=default2108 header.b=WQtiyG4x; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org" Received: from sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id d19-20020a056402401300b0044756d7defdsi3971011eda.613.2022.09.10.15.21.42 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 10 Sep 2022 15:21:43 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=fail header.i=@tim-lange.me header.s=default2108 header.b=WQtiyG4x; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org" Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 49D42385AE76 for ; Sat, 10 Sep 2022 22:21:33 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from www523.your-server.de (www523.your-server.de [159.69.224.22]) by sourceware.org (Postfix) with ESMTPS id 955C73858D32 for ; Sat, 10 Sep 2022 22:21:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 955C73858D32 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=tim-lange.me Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tim-lange.me DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tim-lange.me; s=default2108; h=Content-Transfer-Encoding:MIME-Version: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References; bh=FIDKn8WJCs2iGa/GMJjVnaqI/FCkT8CJv8Ot91zxNec=; b=WQtiyG4xWEjdE7raU9EIXqNOqp htNk/cC69pPLQdvOD1rLfRBEkGqeTQLpvFMz1blKtqozdMigmStRXCG+VLQRW+gtnH3CCrMKQYFlo sfLxfWUpr5O2LaoG+wlAqgF0dIIaunGHVmy+DAmLbRjfSlAoLXtfq0usPHueY0I4jSBJyqXM9oqMC 4tldIw3FHuSbdEfGjImFc78l9eEqmaT61fXOOVEY1aZRjgFr5WTNvxJyJs7GWr3MzYD+BoqLMqr+r it4W1FXwDZPUwRUuZL5BYgaoIAI/WmNvDAsV+XXneOOyJUdAABZwb7lLILY6NLSKv4sMtRQjq33ZE qR/izKpQ==; Received: from sslproxy01.your-server.de ([78.46.139.224]) by www523.your-server.de with esmtpsa (TLSv1.3:TLS_AES_256_GCM_SHA384:256) (Exim 4.92.3) (envelope-from ) id 1oX8qS-000FYr-5l; Sun, 11 Sep 2022 00:21:00 +0200 Received: from [2a02:908:1861:d6a0::6b5] (helo=fedora..) by sslproxy01.your-server.de with esmtpsa (TLSv1.3:TLS_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oX8qS-0006Se-06; Sun, 11 Sep 2022 00:21:00 +0200 From: Tim Lange To: gcc-patches@gcc.gnu.org Subject: [PATCH] analyzer: consider empty ranges and zero byte accesses [PR106845] Date: Sun, 11 Sep 2022 00:19:52 +0200 Message-Id: <20220910221952.99541-1-mail@tim-lange.me> X-Mailer: git-send-email 2.37.3 MIME-Version: 1.0 X-Authenticated-Sender: mail@tim-lange.me X-Virus-Scanned: Clear (ClamAV 0.103.6/26654/Sat Sep 10 09:55:46 2022) X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_INFOUSMEBIZ, SPF_HELO_NONE, SPF_PASS, 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: , Cc: Tim Lange Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1743623032140337170?= X-GMAIL-MSGID: =?utf-8?q?1743623032140337170?= Hi, see my patch below for a fix of pr106845. I decided to allow bit_ranges and byte_ranges to have a size of zero and rather only add an assertion to the functions that assume a non-zero size. That way is more elegant in the caller than restricting byte_range to only represent non-empty ranges. - Tim This patch adds handling of empty ranges in bit_range and byte_range and adds an assertion to member functions that assume a positive size. Further, the patch fixes an ICE caused by an empty byte_range passed to byte_range::exceeds_p. Regression-tested on Linux x86_64. 2022-09-10 Tim Lange gcc/analyzer/ChangeLog: PR analyzer/106845 * region-model.cc (region_model::check_region_bounds): Bail out if 0 bytes were accessed. * store.cc (byte_range::dump_to_pp): Add special case for empty ranges. (byte_range::exceeds_p): Restrict to non-empty ranges. (byte_range::falls_short_of_p): Restrict to non-empty ranges. * store.h (bit_range::empty_p): New function. (bit_range::get_last_byte_offset): Restrict to non-empty ranges. (byte_range::empty_p): New function. (byte_range::get_last_byte_offset): Restrict to non-empty ranges. gcc/testsuite/ChangeLog: PR analyzer/106845 * gcc.dg/analyzer/out-of-bounds-zero.c: New test. * gcc.dg/analyzer/pr106845.c: New test. --- gcc/analyzer/region-model.cc | 3 + gcc/analyzer/store.cc | 12 +++- gcc/analyzer/store.h | 12 ++++ .../gcc.dg/analyzer/out-of-bounds-zero.c | 67 +++++++++++++++++++ gcc/testsuite/gcc.dg/analyzer/pr106845.c | 11 +++ 5 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/analyzer/out-of-bounds-zero.c create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr106845.c diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index d321e5b6479..82006405373 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -1826,6 +1826,9 @@ region_model::check_region_bounds (const region *reg, /* Find out how many bytes were accessed. */ const svalue *num_bytes_sval = reg->get_byte_size_sval (m_mgr); tree num_bytes_tree = maybe_get_integer_cst_tree (num_bytes_sval); + /* Bail out if 0 bytes are accessed. */ + if (num_bytes_tree && zerop (num_bytes_tree)) + return; /* Get the capacity of the buffer. */ const svalue *capacity = get_capacity (base_reg); diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc index ec5232cb055..1857d95f0b6 100644 --- a/gcc/analyzer/store.cc +++ b/gcc/analyzer/store.cc @@ -380,7 +380,11 @@ bit_range::as_byte_range (byte_range *out) const void byte_range::dump_to_pp (pretty_printer *pp) const { - if (m_size_in_bytes == 1) + if (m_size_in_bytes == 0) + { + pp_string (pp, "empty"); + } + else if (m_size_in_bytes == 1) { pp_string (pp, "byte "); pp_wide_int (pp, m_start_byte_offset, SIGNED); @@ -455,7 +459,9 @@ bool byte_range::exceeds_p (const byte_range &other, byte_range *out_overhanging_byte_range) const { - if (other.get_last_byte_offset () < get_last_byte_offset ()) + gcc_assert (!empty_p ()); + + if (other.get_next_byte_offset () < get_next_byte_offset ()) { /* THIS definitely exceeds OTHER. */ byte_offset_t start = MAX (get_start_byte_offset (), @@ -477,6 +483,8 @@ bool byte_range::falls_short_of_p (byte_offset_t offset, byte_range *out_fall_short_bytes) const { + gcc_assert (!empty_p ()); + if (get_start_byte_offset () < offset) { /* THIS falls short of OFFSET. */ diff --git a/gcc/analyzer/store.h b/gcc/analyzer/store.h index ac8b6853f4b..d172ee756c8 100644 --- a/gcc/analyzer/store.h +++ b/gcc/analyzer/store.h @@ -237,6 +237,11 @@ struct bit_range void dump_to_pp (pretty_printer *pp) const; void dump () const; + bool empty_p () const + { + return m_size_in_bits == 0; + } + bit_offset_t get_start_bit_offset () const { return m_start_bit_offset; @@ -247,6 +252,7 @@ struct bit_range } bit_offset_t get_last_bit_offset () const { + gcc_assert (!empty_p ()); return get_next_bit_offset () - 1; } @@ -297,6 +303,11 @@ struct byte_range void dump_to_pp (pretty_printer *pp) const; void dump () const; + bool empty_p () const + { + return m_size_in_bytes == 0; + } + bool contains_p (byte_offset_t offset) const { return (offset >= get_start_byte_offset () @@ -329,6 +340,7 @@ struct byte_range } byte_offset_t get_last_byte_offset () const { + gcc_assert (!empty_p ()); return m_start_byte_offset + m_size_in_bytes - 1; } diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-zero.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-zero.c new file mode 100644 index 00000000000..201ca00ebdb --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-zero.c @@ -0,0 +1,67 @@ +/* { dg-additional-options "-Wno-stringop-overflow"} */ +/* -Wstringop-overflow= triggers on test5. */ + +#include +#include + +void test1 (void) +{ + int32_t buf[1]; + /* Zero bytes written on non-zero allocation. */ + __builtin_memset (buf, 0, 0); +} + +void test2 (void) +{ + /* ISO C forbids zero-size arrays but GCC compiles this to an + zero-sized array without -Wpedantic. */ + int32_t buf[0]; + /* Write on zero capacity. */ + __builtin_memset (buf, 0, sizeof (int32_t)); /* { dg-line test2 } */ + + /* { dg-warning "overflow" "warning" { target *-*-* } test2 } */ + /* { dg-message "from byte 0 till byte 3" "final event" { target *-*-* } test2 } */ +} + +void test3 (void) +{ + int32_t buf[0]; + /* Zero bytes written on zero capacity. */ + __builtin_memset (buf, 0, 0); +} + +void test4 (void) +{ + int32_t *buf = malloc (sizeof (int32_t)); + if (!buf) + return; + + /* Zero bytes written on non-zero allocation. */ + __builtin_memset (buf, 0, 0); + free (buf); +} + +void test5 (void) +{ + int32_t *buf = malloc (0); + if (!buf) + return; + + /* Write on zero capacity. */ + __builtin_memset (buf, 0, sizeof (int32_t)); /* { dg-line test5 } */ + free (buf); + + /* { dg-warning "overflow" "warning" { target *-*-* } test5 } */ + /* { dg-message "from byte 0 till byte 3" "final event" { target *-*-* } test5 } */ +} + +void test6 (void) +{ + int32_t *buf = malloc (0); + if (!buf) + return; + + /* Zero bytes written on zero capacity. */ + __builtin_memset (buf, 0, 0); + free (buf); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr106845.c b/gcc/testsuite/gcc.dg/analyzer/pr106845.c new file mode 100644 index 00000000000..528c7b3ea9a --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr106845.c @@ -0,0 +1,11 @@ +int buf_size; + +int +main (void) +{ + char buf[buf_size]; + + __builtin_memset (&buf[1], 0, buf_size); + + return 0; +}