From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from www523.your-server.de (www523.your-server.de [159.69.224.22]) by sourceware.org (Postfix) with ESMTPS id 3FC833858280 for ; Tue, 5 Jul 2022 19:50:23 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 3FC833858280 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=O6DqeT9/cQyzhBGwqffjJZRln6hkqmXRgg6TyrJoTDw=; b=carsEgcU5cKHqSrGh8BJ9sdm3I ca1yJ5AYGkEG2aBX1OcIyYmbl6yimuZhCv5MQmSljudF1GaN6wO2qIhi0cU6LbaIU5FegrEct/U9L taVa+8JOq3XmfjB+ZFAWBVHQYEr9jBSh/fNHNY+rdxrs7At+ssyIbQ9pbzL0zlL7j8TgGtea0aO0f 76olR1r2i18S2qxsyNiL3yHTQ5Rp3ZqPt1fIYUgM5Ke1VCwpVMmR9gu83RggO2RieApFG6DnDz/az R4ppSwv6laEz/KcQcsprjV16gNSFhZSmYVB7g4gDKYNzCA82GP6E+LjgWrV/z3gjIXauCSZ+EqjJC KWLIUKPA==; Received: from sslproxy05.your-server.de ([78.46.172.2]) by www523.your-server.de with esmtpsa (TLSv1.3:TLS_AES_256_GCM_SHA384:256) (Exim 4.92.3) (envelope-from ) id 1o8oYv-000FX4-9w; Tue, 05 Jul 2022 21:50:21 +0200 Received: from [2a02:908:1861:d6a0::b718] (helo=fedora..) by sslproxy05.your-server.de with esmtpsa (TLSv1.3:TLS_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1o8oYv-000JEC-4A; Tue, 05 Jul 2022 21:50:21 +0200 From: Tim Lange To: gcc-patches@gcc.gnu.org, dmalcolm@redhat.com Cc: Tim Lange Subject: [PATCH] analyzer: Fix handling of non-ints inside allocation size checker [PR106181] Date: Tue, 5 Jul 2022 21:49:09 +0200 Message-Id: <20220705194909.13675-1-mail@tim-lange.me> X-Mailer: git-send-email 2.36.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Authenticated-Sender: mail@tim-lange.me X-Virus-Scanned: Clear (ClamAV 0.103.6/26594/Tue Jul 5 09:24:14 2022) X-Spam-Status: No, score=-11.9 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: , X-List-Received-Date: Tue, 05 Jul 2022 19:50:25 -0000 This patch fixes the ICE reported in PR106181 by Arseny Solokha. With this patch, the allocation size checker tries to handle floating-point operands of allocation size arguments. Constant sizes get implicitly converted and symbolic sizes are handled as long as the floating-point operand could also be represented as a positive integer. In all other cases and on unhandled constants, the checker falls back to not emitting a warning. Also, I unified the logic on zero byte allocations. Regression-tested on x86_64 linux. 2022-07-05 Tim Lange gcc/analyzer/ChangeLog: PR analyzer/106181 * region-model.cc (capacity_compatible_with_type): Can handle non-integer constants now. (region_model::check_region_size): Adapted to the new signature of capacity_compatible_with_type. gcc/testsuite/ChangeLog: PR analyzer/106181 * gcc.dg/analyzer/allocation-size-1.c: New tests. * gcc.dg/analyzer/allocation-size-2.c: New tests. * gcc.dg/analyzer/pr106181.c: New test. --- gcc/analyzer/region-model.cc | 44 ++++++++++++++++--- .../gcc.dg/analyzer/allocation-size-1.c | 29 +++++++++++- .../gcc.dg/analyzer/allocation-size-2.c | 22 ++++++++++ gcc/testsuite/gcc.dg/analyzer/pr106181.c | 7 +++ 4 files changed, 95 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr106181.c diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index 5d939327e01..e097ecb3c07 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -2904,13 +2904,45 @@ private: static bool capacity_compatible_with_type (tree cst, tree pointee_size_tree, - bool is_struct) + bool is_struct, bool floor_real) { - gcc_assert (TREE_CODE (cst) == INTEGER_CST); gcc_assert (TREE_CODE (pointee_size_tree) == INTEGER_CST); - unsigned HOST_WIDE_INT pointee_size = TREE_INT_CST_LOW (pointee_size_tree); - unsigned HOST_WIDE_INT alloc_size = TREE_INT_CST_LOW (cst); + + unsigned HOST_WIDE_INT alloc_size; + switch (TREE_CODE (cst)) + { + default: + /* Assume all unhandled operands are compatible. */ + return true; + case INTEGER_CST: + alloc_size = TREE_INT_CST_LOW (cst); + break; + case REAL_CST: + { + const REAL_VALUE_TYPE *rv = TREE_REAL_CST_PTR (cst); + if (floor_real) + { + /* If the size is constant real at compile-time, + we can model the conversion. */ + alloc_size = real_to_integer (rv); + } + else + { + /* On expressions where the value of one operator isn't + representable as an integer or is negative, we give up and + just assume that the programmer knows what they are doing. */ + HOST_WIDE_INT i; + if (real_isneg (rv) || !real_isinteger (rv, &i)) + return true; + alloc_size = i; + } + } + break; + } + + if (alloc_size == 0) + return true; if (is_struct) return alloc_size >= pointee_size; @@ -2920,7 +2952,7 @@ capacity_compatible_with_type (tree cst, tree pointee_size_tree, static bool capacity_compatible_with_type (tree cst, tree pointee_size_tree) { - return capacity_compatible_with_type (cst, pointee_size_tree, false); + return capacity_compatible_with_type (cst, pointee_size_tree, false, false); } /* Checks whether SVAL could be a multiple of SIZE_CST. @@ -3145,7 +3177,7 @@ region_model::check_region_size (const region *lhs_reg, const svalue *rhs_sval, = as_a (capacity); tree cst_cap = cst_cap_sval->get_constant (); if (!capacity_compatible_with_type (cst_cap, pointee_size_tree, - is_struct)) + is_struct, true)) ctxt->warn (new dubious_allocation_size (lhs_reg, rhs_reg, cst_cap)); } diff --git a/gcc/testsuite/gcc.dg/analyzer/allocation-size-1.c b/gcc/testsuite/gcc.dg/analyzer/allocation-size-1.c index 4a78a81d054..1a1c8e75c98 100644 --- a/gcc/testsuite/gcc.dg/analyzer/allocation-size-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/allocation-size-1.c @@ -114,4 +114,31 @@ void test_10 (int32_t n) { char *ptr = malloc (7 * n); free (ptr); -} \ No newline at end of file +} + +void test_11 () +{ + int32_t *ptr = malloc (3.0); /* { dg-line malloc11 } */ + free (ptr); + /* { dg-warning "allocated buffer size is not a multiple of the pointee's size \\\[CWE-131\\\]" "warning" { target *-*-* } malloc11 } */ + /* { dg-message "'int32_t \\*' (\\\{aka '(long )?int \\*'\\\})? here; 'sizeof \\(int32_t (\\\{aka (long )?int\\\})?\\)' is '4'" "note" { target *-*-* } malloc11 } */ +} + +void test_12 () +{ + int32_t *ptr = malloc (4.0); + free (ptr); +} + +void test_13 () +{ + int32_t *ptr = malloc (4.7); + free (ptr); +} + +void test_14 () +{ + /* Test round towards zero. */ + int32_t *ptr = malloc (-0.9); + free (ptr); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/allocation-size-2.c b/gcc/testsuite/gcc.dg/analyzer/allocation-size-2.c index d541d5ef8db..babf9ae668d 100644 --- a/gcc/testsuite/gcc.dg/analyzer/allocation-size-2.c +++ b/gcc/testsuite/gcc.dg/analyzer/allocation-size-2.c @@ -154,3 +154,25 @@ void test_13 (void) else free (ptr); } + +void test_14 (int32_t n) +{ + int32_t *ptr = malloc (n * 3.0); /* { dg-line malloc14 } */ + free (ptr); + /* { dg-warning "allocated buffer size is not a multiple of the pointee's size \\\[CWE-131\\\]" "warning" { target *-*-* } malloc14 } */ + /* { dg-message "'int32_t \\*' (\\\{aka '(long )?int \\*'\\\})? here; 'sizeof \\(int32_t (\\\{aka (long )?int\\\})?\\)' is '4'" "note" { target *-*-* } malloc14 } */ +} + +void test_15 (int32_t n) +{ + int32_t *ptr = malloc (n * 4.0); + free (ptr); +} + +void test_16 (int32_t n) +{ + /* Should not emit a warning because we can not reason whether the result + of the floating-point arithmetic actually is a valid size or not. */ + int32_t *ptr = malloc (n * 3.1); + free (ptr); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr106181.c b/gcc/testsuite/gcc.dg/analyzer/pr106181.c new file mode 100644 index 00000000000..6df4e4538c0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr106181.c @@ -0,0 +1,7 @@ +#include + +int32_t * +foo (int32_t x) +{ + return __builtin_calloc (x * 1.1, 1); +} -- 2.36.1