From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mailrelay.tugraz.at (mailrelay.tugraz.at [129.27.2.202]) by sourceware.org (Postfix) with ESMTPS id 959713858D35 for ; Fri, 21 Jul 2023 11:22:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 959713858D35 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=tugraz.at Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tugraz.at Received: from vra-173-226.tugraz.at (vra-173-226.tugraz.at [129.27.173.226]) by mailrelay.tugraz.at (Postfix) with ESMTPSA id 4R6nFf1vpRz1LMXv; Fri, 21 Jul 2023 13:21:58 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 mailrelay.tugraz.at 4R6nFf1vpRz1LMXv DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tugraz.at; s=mailrelay; t=1689938518; bh=aQ6ZaMnHPJ1Bi9otazOS6rbDx+vdt/sROqDLA8JT8+Y=; h=Subject:From:To:Cc:Date:From; b=eaIQPx+RryUTC8louEUF585JV5MGsQVmE5XUDzWp5W7zjjMSq6/0C3ExhW2nUyqO7 merAq2N2drnlYUgaUh+UIMpXHbBg1WBCzDpoJ1st3ZEnK1Z4c2q4CSGzJGQrsaBu2k 6FsEgAqlS5Xqq8xFBHRS+6o5Sb8C1IRO0dSVBSPI= Message-ID: Subject: [C PATCH]: Add Walloc-type to warn about insufficient size in allocations From: Martin Uecker To: gcc-patches@gcc.gnu.org Cc: Joseph Myers Date: Fri, 21 Jul 2023 13:21:57 +0200 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable User-Agent: Evolution 3.46.4-2 MIME-Version: 1.0 X-TUG-Backscatter-control: G/VXY7/6zeyuAY/PU2/0qw X-Spam-Scanner: SpamAssassin 3.003001 X-Spam-Score-relay: -1.9 X-Scanned-By: MIMEDefang 2.74 on 129.27.10.117 X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,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 List-Id: This patch adds a warning for allocations with insufficient size based on the "alloc_size" attribute and the type of the pointer=C2=A0 the result is assigned to. While it is theoretically legal to assign to the wrong pointer type and cast it to the right type later, this almost always indicates an error. Since this catches common mistakes and is simple to diagnose, it is suggested to add this warning. =20 Bootstrapped and regression tested on x86.=20 Martin Add option Walloc-type that warns about allocations that have insufficient storage for the target type of the pointer the storage is assigned to. gcc: * doc/invoke.texi: Document -Wstrict-flex-arrays option. gcc/c-family: * c.opt (Walloc-type): New option. gcc/c: * c-typeck.cc (convert_for_assignment): Add Walloc-type warning. gcc/testsuite: * gcc.dg/Walloc-type-1.c: New test. diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 4abdc8d0e77..8b9d148582b 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -319,6 +319,10 @@ Walloca C ObjC C++ ObjC++ Var(warn_alloca) Warning Warn on any use of alloca. =20 +Walloc-type +C ObjC Var(warn_alloc_type) Warning +Warn when allocating insufficient storage for the target type of the assigned pointer. + Walloc-size-larger-than=3D C ObjC C++ LTO ObjC++ Var(warn_alloc_size_limit) Joined Host_Wide_Int ByteSize Warning Init(HOST_WIDE_INT_MAX) -Walloc-size-larger-than=3D Warn for calls to allocation functions that diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 7cf411155c6..2e392f9c952 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -7343,6 +7343,32 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, "request for implicit conversion " "from %qT to %qT not permitted in C++", rhstype, type); =20 + /* Warn of new allocations are not big enough for the target type. */ + tree fndecl; + if (warn_alloc_type + && TREE_CODE (rhs) =3D=3D CALL_EXPR + && (fndecl =3D get_callee_fndecl (rhs)) !=3D NULL_TREE + && DECL_IS_MALLOC (fndecl)) + { + tree fntype =3D TREE_TYPE (fndecl); + tree fntypeattrs =3D TYPE_ATTRIBUTES (fntype); + tree alloc_size =3D lookup_attribute ("alloc_size", fntypeattrs); + if (alloc_size) + { + tree args =3D TREE_VALUE (alloc_size); + int idx =3D TREE_INT_CST_LOW (TREE_VALUE (args)) - 1; + /* For calloc only use the second argument. */ + if (TREE_CHAIN (args)) + idx =3D TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (args))) - 1; + tree arg =3D CALL_EXPR_ARG (rhs, idx); + if (TREE_CODE (arg) =3D=3D INTEGER_CST + && tree_int_cst_lt (arg, TYPE_SIZE_UNIT (ttl))) + warning_at (location, OPT_Walloc_type, "allocation of " + "insufficient size %qE for type %qT with " + "size %qE", arg, ttl, TYPE_SIZE_UNIT (ttl)); + } + } + /* See if the pointers point to incompatible address spaces. */ asl =3D TYPE_ADDR_SPACE (ttl); asr =3D TYPE_ADDR_SPACE (ttr); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 88e3c625030..6869bed64c3 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -8076,6 +8076,15 @@ always leads to a call to another @code{cold} function such as wrappers of C++ @code{throw} or fatal error reporting functions leading to @code{abort}. @end table =20 +@opindex Wno-alloc-type +@opindex Walloc-type +@item -Walloc-type +Warn about calls to allocation functions decorated with attribute +@code{alloc_size} that specify insufficient size for the target type of +the pointer the result is assigned to, including those to the built-in +forms of the functions @code{aligned_alloc}, @code{alloca}, @code{calloc}, +@code{malloc}, and @code{realloc}. + @opindex Wno-alloc-zero @opindex Walloc-zero @item -Walloc-zero diff --git a/gcc/testsuite/gcc.dg/Walloc-type-1.c b/gcc/testsuite/gcc.dg/Walloc-type-1.c new file mode 100644 index 00000000000..bc62e5e9aa3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Walloc-type-1.c @@ -0,0 +1,37 @@ +/* Tests the warnings for insufficient allocation size.=20 + { dg-do compile } + * { dg-options "-Walloc-type" }=20 + * */ +#include +#include + +struct b { int x[10]; }; + +void fo0(void) +{ + struct b *p =3D malloc(sizeof *p); +} + +void fo1(void) +{ + struct b *p =3D malloc(sizeof p); /* { dg- warning "allocation of insufficient size" } */ +} + +void fo2(void) +{ + struct b *p =3D alloca(sizeof p); /* { dg- warning "allocation of insufficient size" } */ +} + +void fo3(void) +{ + struct b *p =3D calloc(1, sizeof p); /* { dg-warning "allocation of insufficient size" } */ +} + +void g(struct b* p); + +void fo4(void) +{ + g(malloc(4)); /* { dg-warning "allocation of insufficient size" } */ +} + +