From patchwork Fri Aug 25 15:24:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qing Zhao X-Patchwork-Id: 136923 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:a7d1:0:b0:3f2:4152:657d with SMTP id p17csp1874359vqm; Fri, 25 Aug 2023 08:26:23 -0700 (PDT) X-Google-Smtp-Source: AGHT+IE00V139E5cAX3XHV/auxIs8xwlAiTvs9SyE/4h6FL4ApUqTtTBFCGLyfqRq5QLsmx/7PNS X-Received: by 2002:a17:906:310d:b0:991:c9da:70da with SMTP id 13-20020a170906310d00b00991c9da70damr15092137ejx.61.1692977183624; Fri, 25 Aug 2023 08:26:23 -0700 (PDT) Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id h8-20020a17090619c800b0098e1627c0e4si1038678ejd.777.2023.08.25.08.26.23 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 25 Aug 2023 08:26:23 -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=pass header.i=@gcc.gnu.org header.s=default header.b=bkFKN31y; arc=fail (signature failed); 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"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E3240387689A for ; Fri, 25 Aug 2023 15:25:32 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E3240387689A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1692977132; bh=qmynIL921v6MRVlRb7wQhY0MnEAFAvHYNX/qGFd/h7k=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=bkFKN31yC3q+RjhfLaBl0GzgkM2rHDxZrNu9HMQmxPKnf2n8G1BfxSS4LcSHLuqUb zxaoUwH3uyir/ZxNOTO9w7ok49V6O21jRODz60KR+Wyp8XCIVmlkfpSi9mJNn/E1vq aYrIahHHcaTDj6WApfdaBHfuNPFuCcTfJCPrMN5E= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mx0b-00069f02.pphosted.com (mx0b-00069f02.pphosted.com [205.220.177.32]) by sourceware.org (Postfix) with ESMTPS id 129B43858C53 for ; Fri, 25 Aug 2023 15:24:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 129B43858C53 Received: from pps.filterd (m0246632.ppops.net [127.0.0.1]) by mx0b-00069f02.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 37PDOEPC021135; Fri, 25 Aug 2023 15:24:39 GMT Received: from phxpaimrmta02.imrmtpd1.prodappphxaev1.oraclevcn.com (phxpaimrmta02.appoci.oracle.com [147.154.114.232]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 3sn1yvxnfw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 25 Aug 2023 15:24:39 +0000 Received: from pps.filterd (phxpaimrmta02.imrmtpd1.prodappphxaev1.oraclevcn.com [127.0.0.1]) by phxpaimrmta02.imrmtpd1.prodappphxaev1.oraclevcn.com (8.17.1.19/8.17.1.19) with ESMTP id 37PFHBa9036065; Fri, 25 Aug 2023 15:24:38 GMT Received: from nam02-sn1-obe.outbound.protection.outlook.com (mail-sn1nam02lp2049.outbound.protection.outlook.com [104.47.57.49]) by phxpaimrmta02.imrmtpd1.prodappphxaev1.oraclevcn.com (PPS) with ESMTPS id 3sn1yqybt3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 25 Aug 2023 15:24:38 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=QGbTDgSWPOerk/7Ch6rQp3HJanJ0doIB1O0ZXbxojURkaq3tGA/WpcMtj2rUF2ZqLM0JbWA0FVoujz39AHsUaKcR5SMdHGHD0BA8CqMt2vVdS9htTD9cSaGQCo+n78MVoNwVsb+x7RXckx3rI67AcGINGHQvzWIhUc7szobSl8ZoAWKQSTdweCwY/JQyafEOocjJKdQScsJRTjrv/khRJX8aApPaWbcbOW3a0NQO/KQzSxsDE0foPyyO64VODRKb0NKKrMY8cW4RWpSaf1sVOnDTXjcFVjrVMeAAXSxDCKPDovjxerbbJNcZzj4hc7xBeQTcNCof5MywMG8XXQFrLw== 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=qmynIL921v6MRVlRb7wQhY0MnEAFAvHYNX/qGFd/h7k=; b=Hhnjqz6C2RWu/dDt6B940W2Uk5EMiMzYEdmZTb3uFSJPpbVOCiyeikghDFTmlCS5L2PHp8J2S7I4PmRtDxHv2ljH43e8zkw4IJgP7jnvu7eF7jvYXovbofjMZq/qMUpXbTvN90Zkes+D2jKbz+Wfk6bhNgbSOcMd1Mg99ycSQ0UyOXWOmVZpGABsgSdKsqtJbxkoF/B6IUJuJNwvPVEDnt02HUuAV6OVibf0Ij+3SKbuvadDuzOm9UHbmxKpAsNBijFuBA4wrg4qmBO0OSMzpJ+KIYTuu/6wLKS3IfyJUM4uG72m5ORqwHi/R5UNWWtbA7/hPMCYTx4RwTRrzn/FBw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oracle.com; dmarc=pass action=none header.from=oracle.com; dkim=pass header.d=oracle.com; arc=none Received: from CH2PR10MB4344.namprd10.prod.outlook.com (2603:10b6:610:af::19) by BY5PR10MB4241.namprd10.prod.outlook.com (2603:10b6:a03:208::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.27; Fri, 25 Aug 2023 15:24:35 +0000 Received: from CH2PR10MB4344.namprd10.prod.outlook.com ([fe80::5afd:d02a:38ef:94ba]) by CH2PR10MB4344.namprd10.prod.outlook.com ([fe80::5afd:d02a:38ef:94ba%7]) with mapi id 15.20.6699.028; Fri, 25 Aug 2023 15:24:35 +0000 To: joseph@codesourcery.com, richard.guenther@gmail.com, jakub@redhat.com, gcc-patches@gcc.gnu.org Cc: keescook@chromium.org, siddhesh@gotplt.org, uecker@tugraz.at, isanbard@gmail.com, Qing Zhao Subject: [V3][PATCH 1/3] Provide counted_by attribute to flexible array member field (PR108896) Date: Fri, 25 Aug 2023 15:24:23 +0000 Message-Id: <20230825152425.2417656-2-qing.zhao@oracle.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20230825152425.2417656-1-qing.zhao@oracle.com> References: <20230825152425.2417656-1-qing.zhao@oracle.com> X-ClientProxiedBy: BYAPR05CA0092.namprd05.prod.outlook.com (2603:10b6:a03:e0::33) To CH2PR10MB4344.namprd10.prod.outlook.com (2603:10b6:610:af::19) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PR10MB4344:EE_|BY5PR10MB4241:EE_ X-MS-Office365-Filtering-Correlation-Id: 8c3e29c5-a1eb-4e48-64f8-08dba57f636e X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 2UxkwpliaSZiInwoB/oscugKo28FqsNyNLIkBHNPJHdpWG9MVRqjw13KusjpXtKbIlJMoewFO+FJMLgdSJCcnVnCCILazEqbQsr+4cXnay3EKSTS0/GxyBpUPmsouR+8irLxwNbiiLUdLqiE7gav8v6A6z7shGaJxk1qQrztfB+UGg+HFX5m9FxC/RkpiP4VZMZOoAinHWuBAWtb3OsqmIqw83L4A3q/sgkSYH7wWPi/Pqh+a7yx2URqfeFeLeVsjUcNlfNNUFX3+OrTp1oXYfHvu6D9hDXu4vQFLWtqS/nHN3igsS+FY2KCosWE06LmQNEo5if7lYSauZqisS64Crlrhm7DfLqdGMjb/3k4eiCz2Ue76aGrNBuUfLZjewJ4Vub2LRJYEWdbXOKOmLX1cBv3snbOCnotIJp56rYY6Mvh1xseVWcgGcVoOI/8qAh13qO8lO9EeD9p4n9Ics7grJQKief6Q7fNHBydLrhc5/QxumwHZDoDnStk1Ji2Ulg1ToWQDVsoAUgPISUll1eLaRZ0I/SIJlIchEwcQzuOpxU= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:CH2PR10MB4344.namprd10.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230031)(346002)(136003)(396003)(39860400002)(366004)(376002)(451199024)(186009)(1800799009)(66946007)(66476007)(66556008)(316002)(478600001)(26005)(44832011)(6666004)(38100700002)(84970400001)(41300700001)(86362001)(6486002)(6512007)(6506007)(2906002)(8676002)(4326008)(8936002)(1076003)(2616005)(5660300002)(107886003)(83380400001)(36756003)(30864003); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: HvkEWxfKTBjRqirNl6Q7wbnkwxc4mpctxl951ikL3gK2u5xXKkCVhqN1Ag6tAyKEspOpDUA+/DRfMaw906OSzMh7Qt8SQy97kDplDs9zohYMkuV/jb1jEsz49YWlhRPcCzZv5zjX6EUXtng4GOFWudoyRdNzr2XMT20dusooCPXLuFRbj7FJFrTV9abY9XwL7ocsNmvkr07pvmBQp/DlILwnDGxAALQkPemr/0RyVbEOhVqxySrklbvyWhWwMQb4CokptCcisV1Jb9gi/NHHE2nG/h9ez6N+yoggv5UAYF2QcdtxRssqRmL+AFgdvI0vETfpq4kOdPxY0zmvSsZYy1zbCCqfULE1t2WOiq+fr0+jc+oFQ+KrqFvAKLB+cd3q1g+SSbeVgdnuR7ADFj6dDT0KZC8Tlp4LwpFJpOUFf34l5C2+KK/WJSE7qv+OYY03r+z/B8+QBACKBaHgWcMNjHdSSuXHfDPgC4LGb6cYUfFDle1JwmA09kkWq/NGVzRLLEd4sap5K5P8ilMzec1jS/mQuiTMtXaaOp9ROOAXdLERBU7sNRxPJBBosJuALPyu7A9y1elZeALWeuQrbsv0lngvx0xHMv1YTT52sPkxGLQom9cby2CuZHZLkkvUEGt1mZYNMF0uECCnhUGkxVuBYLZBoCs2Un0ZpZ+VbYGusb5Di9yvqWlZzqVXDPpg1U1SBHdGCyJcsX3Ss0pkvRKA7VwWprBcTKKUeDFyEK4NTyHnfSKoUR8gyClu+b2S6kmfCCGd6cDN2UZvRk2emSxZBQ7Uq002czszKVzxPX284oJE5/FCTHaHhI2nLoS0+vKNtLgkQXpgOezOcliYrfZi8GOqgf40D2BwYC8sU/6QzTCJR4dkixPB7R37A7X5MSA+Wfn2E/Kwpo5hcieR+juRfLy81HAzxlCKZB6sRZXxi9M4WbZh5dXWwQZqiuNDfW46J3Gb2jZwnnKyWiWoAjQxKnnIS4MOgYfPkIiW93A0eEc00KZIq78YL+yvrU9CJ+hrmWD4oMQsKn6U8/4IhUM0Is95Z1vNRKjheIhvdmE5gQ3s9n2qRXqeaSUFZAWmrD891rfL2x2PbMWkkRk1ZXMrgBiZ78VAxLGor7NM6ikZSojuhZw9I0UTCMdi9OrU1zV5Ktxehi5Wa5YMxMgrAUaoJ74KmuJIOcqRl8gzNObLCAq3xA4xlUtlJvVwN+3mIKFHasJ10btNHZMBzEZwUV++ylbjKv/73soytVbRyni80h695sHCZGzyVUpWmI+U1wskvj37CB8VWfNdShsJWQNdfuVENPNpC7EJQmxy8JmiJ6EdRJoLIsfpKInqlbkpzX3UWxgKPyBloO2vgXCqplvbPsjXt+i86I4pp96fOXFaTdu59dR5lDh3tjDg6bMFe90b+Sl7V1PWmHnYTGZkMWlP5b7s120dT3ffmGvYMoYrhSA7jIbBpk5f2QoA8JeEDg4O1YL9mQx8+fr8r+nNrA5IaE8pEzk4BniowQDSRBZiZ+/fMcrq7MpuT0ppSUdyUmqPP9ol0lD5QBdpqUal6RX+Kc358UNL59XRCQxxmPgMr+OQ4cXw2r8pQWwEYdgIlyW5 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: jg8Xw7/i3jZqqQ7Drh25len1Ww3U9/rsJ6aiHMXzUxE6GwUCOCT8C/r3m+V8kgsggUbTmRgUz30Bw5cMl0BzHb9eGuh9A2X4MjaPLZ1/0hxQNekkXoMJC9NkySNqGE82zrO1kuHPKioxWxoTdw+UkZeeNw8KUq4D9MSmbNmIVZ4nnd5p9FcyZOL2W2QM9wol396iRimQ4EOkKul6cdVltYfRpdPX9/Em3CnQjwPp0+61ZREBiUVI8ZecPykYKjHdI2nGK9FyFTgKM4vMWsASeqo9Vem4D0kDnh0qaYNdZU8g453E6gqdost4/TF/daelqrDd3cKXhyCjgs7E7JVLzRL5RZ5W8obDbeXRkAwSoJX0hmSXb9Prxg8h7rKHTIPZwUsSn/KL94lsaNM6Fa38T5pHO6h2/scT5dMHH2G8lhdRF4ueB0nHVUNjNKNXckGsegAsm+PXem0QEvQZwi8vWHalZV5+LJ05zErLUkR+lO08t6Fx6QC1fbR77Qr/tpV8yZ+1YdVgXazq9F8ZFUrBKfvEDZK6ActS5Q2nCDgSvMYLV9Naik9M3WbOAzXG+2Aqn6C+ENNIOlzacnZV5l/2a2Uc8OGeblK8lCgSYX/lgkeV/6/gaULfJyx6dKf3NROeuLC3dGnaEgdI56KXf7stmZqW0FWyqiK+8v9gwoccmUVNnfXRt3h6QKXqewoat4RLW+K6vvC7HIG7rGgg5jP+706ZzsuzigLoUxRKzjVZlzP3tQMIEogiTAryHECEh1NxbT3cqaP2nn5xAFVZd/J0GLtlYl9V6OcpWbesSCoGhNb7DwAYndNf+mPJqhEXGpyTBiZ6rPoVKl/1ukoHlpS0Fia7G23HyvxM1jizDidq2vMBLllXgtDaL8qpPRKz75Irx+Huy2nCE1H6wzoyTGGX+m1uPx7Mhevp1m8B8LzkDrCntvqJ1Xvo5iRwlqOaSi+J X-OriginatorOrg: oracle.com X-MS-Exchange-CrossTenant-Network-Message-Id: 8c3e29c5-a1eb-4e48-64f8-08dba57f636e X-MS-Exchange-CrossTenant-AuthSource: CH2PR10MB4344.namprd10.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 25 Aug 2023 15:24:35.2576 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 4e2c6054-71cb-48f1-bd6c-3a9705aca71b X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: RM7DorTpDO1Xd76bgAFlelUmo8p+W2atceCSrmrB1dc0K2+Sq2tIwHo8VZt+GzLzelxxzgRGQw7OV1VavTs06Q== X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY5PR10MB4241 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.957,Hydra:6.0.601,FMLib:17.11.176.26 definitions=2023-08-25_13,2023-08-25_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 mlxlogscore=970 malwarescore=0 adultscore=0 suspectscore=0 mlxscore=0 spamscore=0 phishscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2308100000 definitions=main-2308250137 X-Proofpoint-GUID: X5ChAv0rfKzKria2RiCTeGvTmxs8qhzb X-Proofpoint-ORIG-GUID: X5ChAv0rfKzKria2RiCTeGvTmxs8qhzb X-Spam-Status: No, score=-11.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, 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-Patchwork-Original-From: Qing Zhao via Gcc-patches From: Qing Zhao Reply-To: Qing Zhao Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1775215243321285211 X-GMAIL-MSGID: 1775215243321285211 Provide a new counted_by attribute to flexible array member field. 'counted_by (COUNT)' The 'counted_by' attribute may be attached to the flexible array member of a structure. It indicates that the number of the elements of the array is given by the field named "COUNT" in the same structure as the flexible array member. GCC uses this information to improve the results of the array bound sanitizer and the '__builtin_dynamic_object_size'. For instance, the following code: struct P { size_t count; char other; char array[] __attribute__ ((counted_by (count))); } *p; specifies that the 'array' is a flexible array member whose number of elements is given by the field 'count' in the same structure. The field that represents the number of the elements should have an integer type. An explicit 'counted_by' annotation defines a relationship between two objects, 'p->array' and 'p->count', that 'p->array' has _at least_ 'p->count' number of elements available. This relationship must hold even after any of these related objects are updated. It's the user's responsibility to make sure this relationship to be kept all the time. Otherwise the results of the array bound sanitizer and the '__builtin_dynamic_object_size' might be incorrect. For instance, in the following example, the allocated array has less elements than what's specified by the 'sbuf->count', this is an user error. As a result, out-of-bounds access to the array might not be detected. #define SIZE_BUMP 10 struct P *sbuf; void alloc_buf (size_t nelems) { sbuf = (struct P *) malloc (MAX (sizeof (struct P), (offsetof (struct P, array[0]) + nelems * sizeof (char)))); sbuf->count = nelems + SIZE_BUMP; /* This is invalid when the sbuf->array has less than sbuf->count elements. */ } In the following example, the 2nd update to the field 'sbuf->count' of the above structure will permit out-of-bounds access to the array 'sbuf>array' as well. #define SIZE_BUMP 10 struct P *sbuf; void alloc_buf (size_t nelems) { sbuf = (struct P *) malloc (MAX (sizeof (struct P), (offsetof (struct P, array[0]) + (nelems + SIZE_BUMP) * sizeof (char)))); sbuf->count = nelems; /* This is valid when the sbuf->array has at least sbuf->count elements. */ } void use_buf (int index) { sbuf->count = sbuf->count + SIZE_BUMP + 1; /* Now the value of sbuf->count is larger than the number of elements of sbuf->array. */ sbuf->array[index] = 0; /* then the out-of-bound access to this array might not be detected. */ } gcc/c-family/ChangeLog: PR C/108896 * c-attribs.cc (handle_counted_by_attribute): New function. (attribute_takes_identifier_p): Add counted_by attribute to the list. * c-common.cc (c_flexible_array_member_type_p): ...To this. * c-common.h (c_flexible_array_member_type_p): New prototype. gcc/c/ChangeLog: PR C/108896 * c-decl.cc (flexible_array_member_type_p): Renamed and moved to... (add_flexible_array_elts_to_size): Use renamed function. (is_flexible_array_member_p): Use renamed function. (verify_counted_by_attribute): New function. (finish_struct): Use renamed function and verify counted_by attribute. gcc/ChangeLog: PR C/108896 * doc/extend.texi: Document attribute counted_by. * tree.cc (get_named_field): New function. * tree.h (get_named_field): New prototype. gcc/testsuite/ChangeLog: PR C/108896 * gcc.dg/flex-array-counted-by.c: New test. --- gcc/c-family/c-attribs.cc | 54 ++++++++++++- gcc/c-family/c-common.cc | 13 ++++ gcc/c-family/c-common.h | 1 + gcc/c/c-decl.cc | 79 +++++++++++++++----- gcc/doc/extend.texi | 77 +++++++++++++++++++ gcc/testsuite/gcc.dg/flex-array-counted-by.c | 40 ++++++++++ gcc/tree.cc | 40 ++++++++++ gcc/tree.h | 5 ++ 8 files changed, 291 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/flex-array-counted-by.c diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index e2792ca6898b..65e4f6639109 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -103,6 +103,8 @@ static tree handle_warn_if_not_aligned_attribute (tree *, tree, tree, int, bool *); static tree handle_strict_flex_array_attribute (tree *, tree, tree, int, bool *); +static tree handle_counted_by_attribute (tree *, tree, tree, + int, bool *); static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ; static tree handle_noplt_attribute (tree *, tree, tree, int, bool *) ; static tree handle_alias_ifunc_attribute (bool, tree *, tree, tree, bool *); @@ -373,6 +375,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_warn_if_not_aligned_attribute, NULL }, { "strict_flex_array", 1, 1, true, false, false, false, handle_strict_flex_array_attribute, NULL }, + { "counted_by", 1, 1, true, false, false, false, + handle_counted_by_attribute, NULL }, { "weak", 0, 0, true, false, false, false, handle_weak_attribute, NULL }, { "noplt", 0, 0, true, false, false, false, @@ -601,7 +605,8 @@ attribute_takes_identifier_p (const_tree attr_id) else if (!strcmp ("mode", spec->name) || !strcmp ("format", spec->name) || !strcmp ("cleanup", spec->name) - || !strcmp ("access", spec->name)) + || !strcmp ("access", spec->name) + || !strcmp ("counted_by", spec->name)) return true; else return targetm.attribute_takes_identifier_p (attr_id); @@ -2555,6 +2560,53 @@ handle_strict_flex_array_attribute (tree *node, tree name, return NULL_TREE; } +/* Handle a "counted_by" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_counted_by_attribute (tree *node, tree name, + tree args, int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + tree decl = *node; + tree argval = TREE_VALUE (args); + + /* This attribute only applies to field decls of a structure. */ + if (TREE_CODE (decl) != FIELD_DECL) + { + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute may not be specified for non-field" + " declaration %q+D", name, decl); + *no_add_attrs = true; + } + /* This attribute only applies to field with array type. */ + else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE) + { + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute may not be specified for a non-array field", + name); + *no_add_attrs = true; + } + /* This attribute only applies to a C99 flexible array member type. */ + else if (! c_flexible_array_member_type_p (TREE_TYPE (decl))) + { + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute may not be specified for a non" + " flexible array member field", + name); + *no_add_attrs = true; + } + /* The argument should be an identifier. */ + else if (TREE_CODE (argval) != IDENTIFIER_NODE) + { + error_at (DECL_SOURCE_LOCATION (decl), + "% argument not an identifier"); + *no_add_attrs = true; + } + + return NULL_TREE; +} + /* Handle a "weak" attribute; arguments as in struct attribute_spec.handler. */ diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index 9fbaeb437a12..a18937245c2a 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -9521,6 +9521,19 @@ c_common_finalize_early_debug (void) (*debug_hooks->early_global_decl) (cnode->decl); } +/* Determine whether TYPE is a ISO C99 flexible array memeber type "[]". */ +bool +c_flexible_array_member_type_p (const_tree type) +{ + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_SIZE (type) == NULL_TREE + && TYPE_DOMAIN (type) != NULL_TREE + && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE) + return true; + + return false; +} + /* Get the LEVEL of the strict_flex_array for the ARRAY_FIELD based on the values of attribute strict_flex_array and the flag_strict_flex_arrays. */ unsigned int diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 78fc5248ba68..c29bb429062b 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -909,6 +909,7 @@ extern tree fold_for_warn (tree); extern tree c_common_get_narrower (tree, int *); extern bool get_attribute_operand (tree, unsigned HOST_WIDE_INT *); extern void c_common_finalize_early_debug (void); +extern bool c_flexible_array_member_type_p (const_tree); extern unsigned int c_strict_flex_array_level_of (tree); extern bool c_option_is_from_cpp_diagnostics (int); diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 1f9eb44dbaa2..e943b49b5230 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -5173,19 +5173,6 @@ set_array_declarator_inner (struct c_declarator *decl, return decl; } -/* Determine whether TYPE is a ISO C99 flexible array memeber type "[]". */ -static bool -flexible_array_member_type_p (const_tree type) -{ - if (TREE_CODE (type) == ARRAY_TYPE - && TYPE_SIZE (type) == NULL_TREE - && TYPE_DOMAIN (type) != NULL_TREE - && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE) - return true; - - return false; -} - /* Determine whether TYPE is a one-element array type "[1]". */ static bool one_element_array_type_p (const_tree type) @@ -5222,7 +5209,7 @@ add_flexible_array_elts_to_size (tree decl, tree init) elt = CONSTRUCTOR_ELTS (init)->last ().value; type = TREE_TYPE (elt); - if (flexible_array_member_type_p (type)) + if (c_flexible_array_member_type_p (type)) { complete_array_type (&type, elt, false); DECL_SIZE (decl) @@ -9094,7 +9081,7 @@ is_flexible_array_member_p (bool is_last_field, bool is_zero_length_array = zero_length_array_type_p (TREE_TYPE (x)); bool is_one_element_array = one_element_array_type_p (TREE_TYPE (x)); - bool is_flexible_array = flexible_array_member_type_p (TREE_TYPE (x)); + bool is_flexible_array = c_flexible_array_member_type_p (TREE_TYPE (x)); unsigned int strict_flex_array_level = c_strict_flex_array_level_of (x); @@ -9124,6 +9111,61 @@ is_flexible_array_member_p (bool is_last_field, return false; } +/* Verify the argument of the counted_by attribute of the flexible array + member FIELD_DECL is a valid field of the containing structure's fieldlist, + FIELDLIST, Report error and remove this attribute when it's not. */ +static void +verify_counted_by_attribute (tree fieldlist, tree field_decl) +{ + tree attr_counted_by = lookup_attribute ("counted_by", + DECL_ATTRIBUTES (field_decl)); + + if (!attr_counted_by) + return; + + /* If there is an counted_by attribute attached to the field, + verify it. */ + + const char *fieldname + = IDENTIFIER_POINTER (TREE_VALUE (TREE_VALUE (attr_counted_by))); + + /* Verify the argument of the attrbute is a valid field of the + containing structure. */ + + tree counted_by_field = get_named_field (fieldlist, fieldname); + + /* Error when the field is not found in the containing structure. */ + if (!counted_by_field) + { + error_at (DECL_SOURCE_LOCATION (field_decl), + "%qE attribute argument not a field declaration" + " in the same structure, ignore it", + (get_attribute_name (attr_counted_by))); + + DECL_ATTRIBUTES (field_decl) + = remove_attribute ("counted_by", DECL_ATTRIBUTES (field_decl)); + } + else + /* Error when the field is not with an integer type. */ + { + while (TREE_CHAIN (counted_by_field)) + counted_by_field = TREE_CHAIN (counted_by_field); + tree real_field = TREE_VALUE (counted_by_field); + + if (TREE_CODE (TREE_TYPE (real_field)) != INTEGER_TYPE) + { + error_at (DECL_SOURCE_LOCATION (field_decl), + "%qE attribute argument not a field declaration" + " with integer type, ignore it", + (get_attribute_name (attr_counted_by))); + + DECL_ATTRIBUTES (field_decl) + = remove_attribute ("counted_by", DECL_ATTRIBUTES (field_decl)); + } + } + + return; +} /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T. LOC is the location of the RECORD_TYPE or UNION_TYPE's definition. @@ -9244,7 +9286,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, DECL_PACKED (x) = 1; /* Detect flexible array member in an invalid context. */ - if (flexible_array_member_type_p (TREE_TYPE (x))) + if (c_flexible_array_member_type_p (TREE_TYPE (x))) { if (TREE_CODE (t) == UNION_TYPE) { @@ -9265,6 +9307,9 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, "members"); TREE_TYPE (x) = error_mark_node; } + /* if there is a counted_by attribute attached to this field, + verify it. */ + verify_counted_by_attribute (fieldlist, x); } if (pedantic && TREE_CODE (t) == RECORD_TYPE @@ -9279,7 +9324,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, when x is an array and is the last field. */ if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE) TYPE_INCLUDES_FLEXARRAY (t) - = is_last_field && flexible_array_member_type_p (TREE_TYPE (x)); + = is_last_field && c_flexible_array_member_type_p (TREE_TYPE (x)); /* Recursively set TYPE_INCLUDES_FLEXARRAY for the context of x, t when x is an union or record and is the last field. */ else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (x))) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 97eaacf8a7ec..ea6240646936 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -7617,6 +7617,83 @@ When both the attribute and the option present at the same time, the level of the strictness for the specific trailing array field is determined by the attribute. +@cindex @code{counted_by} variable attribute +@item counted_by (@var{count}) +The @code{counted_by} attribute may be attached to the flexible array +member of a structure. It indicates that the number of the elements of the +array is given by the field named "@var{count}" in the same structure as the +flexible array member. GCC uses this information to improve the results of +the array bound sanitizer and the @code{__builtin_dynamic_object_size}. + +For instance, the following code: + +@smallexample +struct P @{ + size_t count; + char other; + char array[] __attribute__ ((counted_by (count))); +@} *p; +@end smallexample + +@noindent +specifies that the @code{array} is a flexible array member whose number of +elements is given by the field @code{count} in the same structure. + +The field that represents the number of the elements should have an integer +type. An explicit @code{counted_by} annotation defines a relationship between +two objects, @code{p->array} and @code{p->count}, that @code{p->array} has +@emph{at least} @code{p->count} number of elements available. This relationship +must hold even after any of these related objects are updated. It's the user's +responsibility to make sure this relationship to be kept all the time. +Otherwise the results of the array bound sanitizer and the +@code{__builtin_dynamic_object_size} might be incorrect. + +For instance, in the following example, the allocated array has less elements +than what's specified by the @code{sbuf->count}, this is an user error. As a +result, out-of-bounds access to the array might not be detected. + +@smallexample +#define SIZE_BUMP 10 +struct P *sbuf; +void alloc_buf (size_t nelems) +@{ + sbuf = (struct P *) malloc (MAX (sizeof (struct P), + (offsetof (struct P, array[0]) + + nelems * sizeof (char)))); + sbuf->count = nelems + SIZE_BUMP; + /* This is invalid when the sbuf->array has less than sbuf->count + elements. */ +@} +@end smallexample + +In the following example, the 2nd update to the field @code{sbuf->count} of +the above structure will permit out-of-bounds access to the array +@code{sbuf>array} as well. + +@smallexample +#define SIZE_BUMP 10 +struct P *sbuf; +void alloc_buf (size_t nelems) +@{ + sbuf = (struct P *) malloc (MAX (sizeof (struct P), + (offsetof (struct P, array[0]) + + (nelems + SIZE_BUMP) * sizeof (char)))); + sbuf->count = nelems; + /* This is valid when the sbuf->array has at least sbuf->count + elements. */ +@} +void use_buf (int index) +@{ + sbuf->count = sbuf->count + SIZE_BUMP + 1; + /* Now the value of sbuf->count is larger than the number + of elements of sbuf->array. */ + sbuf->array[index] = 0; + /* then the out-of-bound access to this array + might not be detected. */ +@} +@end smallexample + + @cindex @code{alloc_size} variable attribute @item alloc_size (@var{position}) @itemx alloc_size (@var{position-1}, @var{position-2}) diff --git a/gcc/testsuite/gcc.dg/flex-array-counted-by.c b/gcc/testsuite/gcc.dg/flex-array-counted-by.c new file mode 100644 index 000000000000..f8ce9776bf86 --- /dev/null +++ b/gcc/testsuite/gcc.dg/flex-array-counted-by.c @@ -0,0 +1,40 @@ +/* testing the correct usage of attribute counted_by. */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +#include + +int size; +int x __attribute ((counted_by (size))); /* { dg-error "attribute may not be specified for non-field declaration" } */ + +struct trailing { + int count; + int field __attribute ((counted_by (count))); /* { dg-error "attribute may not be specified for a non-array field" } */ +}; + +struct trailing_1 { + int count; + int array_1[0] __attribute ((counted_by (count))); /* { dg-error "attribute may not be specified for a non flexible array member field" } */ +}; + +int count; +struct trailing_array_2 { + int count; + int array_2[] __attribute ((counted_by ("count"))); /* { dg-error "argument not an identifier" } */ +}; + +struct trailing_array_3 { + int other; + int array_3[] __attribute ((counted_by (L"count"))); /* { dg-error "argument not an identifier" } */ +}; + +struct trailing_array_4 { + int other; + int array_4[] __attribute ((counted_by (count))); /* { dg-error "attribute argument not a field declaration in the same structure, ignore it" } */ +}; + +int count; +struct trailing_array_5 { + float count; + int array_5[] __attribute ((counted_by (count))); /* { dg-error "attribute argument not a field declaration with integer type, ignore it" } */ +}; diff --git a/gcc/tree.cc b/gcc/tree.cc index 420857b110c4..fcd36ae0cd74 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -12745,6 +12745,46 @@ array_ref_element_size (tree exp) return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (elmt_type), exp); } +/* Given a field list, FIELDLIST, of a structure/union, return a TREE_LIST, + with each TREE_VALUE a FIELD_DECL stepping down the chain to the FIELD + whose name is FIELDNAME, which is the last TREE_VALUE of the list. + return NULL_TREE if such field is not found. Normally this list is of + length one, but if the field is embedded with (nested) anonymous structures + or unions, this list steps down the chain to the field. */ +tree +get_named_field (tree fieldlist, const char *fieldname) +{ + tree named_field = NULL_TREE; + for (tree field = fieldlist; field; field = DECL_CHAIN (field)) + { + if (TREE_CODE (field) != FIELD_DECL) + continue; + if (DECL_NAME (field) != NULL) + if (strcmp (IDENTIFIER_POINTER (DECL_NAME (field)), fieldname) == 0) + { + named_field = tree_cons (NULL_TREE, field, named_field); + break; + } + else + continue; + /* if the field is an anonymous struct/union, we will check the nested + fields inside it recursively. */ + else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))) + if ((named_field = get_named_field (TYPE_FIELDS (TREE_TYPE (field)), + fieldname)) != NULL_TREE) + { + named_field = tree_cons (NULL_TREE, field, named_field); + break; + } + else + continue; + else + continue; + } + return named_field; +} + + /* Return a tree representing the lower bound of the array mentioned in EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */ diff --git a/gcc/tree.h b/gcc/tree.h index 4c04245e2b1b..4859becaa1e7 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -5619,6 +5619,11 @@ extern tree get_base_address (tree t); of EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */ extern tree array_ref_element_size (tree); +/* Given a field list, FIELDLIST, of a structure/union, return the FIELD whose + name is FIELDNAME, return NULL_TREE if such field is not found. + searching nested anonymous structure/union recursively. */ +extern tree get_named_field (tree, const char *); + /* Return a typenode for the "standard" C type with a given name. */ extern tree get_typenode_from_name (const char *); From patchwork Fri Aug 25 15:24:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qing Zhao X-Patchwork-Id: 136924 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:a7d1:0:b0:3f2:4152:657d with SMTP id p17csp1874620vqm; Fri, 25 Aug 2023 08:26:52 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGzVLcZPSfDJrU05kna67Y/Z6K+328Z+H27geGcMsDev9V3VyXwILLJu4iwARhtl30hZ5Ms X-Received: by 2002:a2e:9e17:0:b0:2b5:9778:7ce2 with SMTP id e23-20020a2e9e17000000b002b597787ce2mr13327941ljk.15.1692977211890; Fri, 25 Aug 2023 08:26:51 -0700 (PDT) Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id m6-20020a17090679c600b009930c925bd9si962163ejo.945.2023.08.25.08.26.51 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 25 Aug 2023 08:26:51 -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=pass header.i=@gcc.gnu.org header.s=default header.b=hiKh1I9q; arc=fail (signature failed); 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"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 450AA3851C00 for ; Fri, 25 Aug 2023 15:25:43 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 450AA3851C00 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1692977143; bh=POcN9KzdUPo9n2oyKAfS9kEFITrqjYKcSrpS3rWpc2o=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=hiKh1I9qT/ci7qYebe0bu4hQ6zzwVKSarl510LPuIq5ECJNDhhKlGuvmCbkPJQz9w i+5fhEWERKWZnesRRJ7yPIuuQ6YgTVYJ9q89zasNZZfb4DS5g/uL+BFKoZHrKGyNnp jMMxaF+JNVDcbXqRyyKDn0nn/sbBCloPl6SCfYiE= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mx0b-00069f02.pphosted.com (mx0b-00069f02.pphosted.com [205.220.177.32]) by sourceware.org (Postfix) with ESMTPS id 600B03858C31 for ; Fri, 25 Aug 2023 15:24:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 600B03858C31 Received: from pps.filterd (m0246632.ppops.net [127.0.0.1]) by mx0b-00069f02.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 37PDOC6L021100; Fri, 25 Aug 2023 15:24:44 GMT Received: from iadpaimrmta01.imrmtpd1.prodappiadaev1.oraclevcn.com (iadpaimrmta01.appoci.oracle.com [130.35.100.223]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 3sn1yvxng8-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 25 Aug 2023 15:24:43 +0000 Received: from pps.filterd (iadpaimrmta01.imrmtpd1.prodappiadaev1.oraclevcn.com [127.0.0.1]) by iadpaimrmta01.imrmtpd1.prodappiadaev1.oraclevcn.com (8.17.1.19/8.17.1.19) with ESMTP id 37PDmvH4036051; Fri, 25 Aug 2023 15:24:43 GMT Received: from nam02-sn1-obe.outbound.protection.outlook.com (mail-sn1nam02lp2041.outbound.protection.outlook.com [104.47.57.41]) by iadpaimrmta01.imrmtpd1.prodappiadaev1.oraclevcn.com (PPS) with ESMTPS id 3sn1yxfvcp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 25 Aug 2023 15:24:43 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=GBc49Kq4/p/rlnBMfCmAMxetbV+P81cTEWlzCFsoiKEY/cTsmDvA0csyzSN5a4zYsHBNK/H8eVuTuMYcRukiJyXgIr51Qb4ALeaWeMOyjl9yeA9exM6P0RgG0bbAyRbLIWYfjLMwcInVCQwBbPvUiidr3+aKwzgB6YAwK1ZE/gKVhmVRIuPCerOdT9QXbFgjbOw9UfF1sZOUfvWG6XoM/SF4auLT887Va1Nx8Nwr6/cIQS5GfM4gFoMe4mJwgJtO6TyjI4NIZZEM0zKaVMFvm+X9LfVKtmKc5RdNeL4fvZQuYVNRz97n75+pWzZmGtl6Nv9R66LkAi7umE8a4gOBWA== 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=POcN9KzdUPo9n2oyKAfS9kEFITrqjYKcSrpS3rWpc2o=; b=ixVDKdA0uDOGLSmZsByvfep02GTicKO3TO8DgtX9mtjWn/GCfexKNOl6F7Da5iL94Aq/+BKT55bX3UwEF3UrU5asjOTXDhHmy6aYVI7iGO13M0BDcW5NkFM3HmKQW2Wg7yvt8pVq53kd2PwlWjL0XeQnVPBHKOFgGVX23zrPq3p4Lz/SqDgUupI022GDTsxIoqb9Aq8QgXjwIV7Y563d/iOZrwROPEteOaCEZYVlKm/rPwyQGzqClg1DazDy1LMozxJL63X1yYOMWIlpY9sc7A/2babfXm4liiar2twP89EVDicHj121/ZhUV2mfsnLpO8g68dKboibSfoROL0AoBw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oracle.com; dmarc=pass action=none header.from=oracle.com; dkim=pass header.d=oracle.com; arc=none Received: from CH2PR10MB4344.namprd10.prod.outlook.com (2603:10b6:610:af::19) by BY5PR10MB4241.namprd10.prod.outlook.com (2603:10b6:a03:208::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.27; Fri, 25 Aug 2023 15:24:40 +0000 Received: from CH2PR10MB4344.namprd10.prod.outlook.com ([fe80::5afd:d02a:38ef:94ba]) by CH2PR10MB4344.namprd10.prod.outlook.com ([fe80::5afd:d02a:38ef:94ba%7]) with mapi id 15.20.6699.028; Fri, 25 Aug 2023 15:24:40 +0000 To: joseph@codesourcery.com, richard.guenther@gmail.com, jakub@redhat.com, gcc-patches@gcc.gnu.org Cc: keescook@chromium.org, siddhesh@gotplt.org, uecker@tugraz.at, isanbard@gmail.com, Qing Zhao Subject: [V3][PATCH 2/3] Use the counted_by atribute info in builtin object size [PR108896] Date: Fri, 25 Aug 2023 15:24:24 +0000 Message-Id: <20230825152425.2417656-3-qing.zhao@oracle.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20230825152425.2417656-1-qing.zhao@oracle.com> References: <20230825152425.2417656-1-qing.zhao@oracle.com> X-ClientProxiedBy: BYAPR05CA0075.namprd05.prod.outlook.com (2603:10b6:a03:e0::16) To CH2PR10MB4344.namprd10.prod.outlook.com (2603:10b6:610:af::19) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PR10MB4344:EE_|BY5PR10MB4241:EE_ X-MS-Office365-Filtering-Correlation-Id: e5c5efca-c000-41cf-5c5e-08dba57f6651 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: mVpEVDTs89Ddly/kkkhhGAjKK6kSk7eV+E4o7NB9HQrggug9Cwpi+92LiwNlRUYDsO8GarOVzpPdMr3E6DXgmFGtXOiIExCBBxi7Y+Bh8V62KPxUe3ZSh2PJ+88tC6sBKVbTF/cEm2Ba4DIZYgVUFPQyiI5z7Bh17rmiUVGJtrsuNUOWWNdVMUJozEf1O9pVvehb8N/NKf3gY2fWEo2C22Y7weDO1XTliZeDjiFMGRVSI4lHWsOiRwMz3t+MXyK8e+2RC0APLl00u5gn8vAESoRDjP6vV7kFFk/mvrxMLXAVyoeGO1+C6AHLu9BJmFYZRUJtKpmHGycq/EaxYs6pkBkLnn7+gANVAA/HHBHrHrf+f+J3TQWKyw6xs11MAhb3qzgxStVQtjt9wioTPwT+ceLULEVZ/yG+GX1U5WJ6nhnomAaI9Vz+DL840NHv6gKWlm9SJUf2L6M8Shf7hCwqdbEO/RsbhDT2qEH5c61eDu4Wg9etux+4rXTPqOvPFmnImbyReCRBrl7H2ZajU6BkhSCK5jx+npuIw6+HNSt9a4DKbGv/9zcDs5DJ/s0FQTnVvKf+R4AeozL+9gv5GCttRQ== X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:CH2PR10MB4344.namprd10.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230031)(346002)(136003)(396003)(39860400002)(366004)(376002)(451199024)(186009)(1800799009)(66946007)(66476007)(66556008)(316002)(478600001)(26005)(44832011)(6666004)(38100700002)(84970400001)(41300700001)(86362001)(6486002)(6512007)(6506007)(2906002)(966005)(8676002)(4326008)(8936002)(1076003)(2616005)(5660300002)(107886003)(83380400001)(36756003)(30864003); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: a3PKKD+9TXX3W32T/bi47vQKMSR52tYmaAxZJYf6fRQ2Sc7JYrPF4TCo6Xne473SPQ0QhwBdNJRUoYo9QbDgMpcHug081ced47c+4Ds0fxwgZxQ8BxKub9YYmzkbujowJmE984CNt1loN3ueX60rG3XFeUrq6JBFNdfS3DoV/8rlm0jiHsOtx/wBr7oOLqeNKXmh6YUc++VYC32U4ZjcNnyP2wVN86GD8ciQbmgXNPrRrmO+Dq7qHOe4uzDGsk+Tsunp9QsTC+7B5fhBS6Qi89CprcU5Yq06EIg7n4iZ/Dn2TArk3is6I37iMn+dTZkoERIfuIFGVgPIyp53Ur8VOalGIbeY7H2N081baZhJ32rJIQC7i0fGWMaRiz3kdWLgnbbemoW+h3OQc+mBLebDGKIoIplSVlf+qLa/4G+kN6K++aa0fL5ZpKV2pQjvKwn/CORzp58aFtwi7AS7zlJoHaTWdVnzpkDBAV//icEGC5G6znRkLcvbDsGmTVltCetRo3Ap4dthhpQhv/++PVBPWLGm9UZkCg5d16QZHpbGEJiHH44bAHFjAY58ehQSX2YGOfwK/UC73k47WfaObKxEuxYOR1wR7o/1AtA+zZML38auUUxU2aR8OPqP/rGU2Qsqr/TtxY/YsoO5X01cASo9lawZMRFmZ2owBuxrb28J1b5hm5SVfoCBySOJ5KMxdIOsGo4e5fjxJC+ioYWXclxGfaBFQF+E0G2i/DVZbUo7EN0VWiKuJ53fcobV2Ccxr6N4G8p087/CxyAOi8CUXf1Kgc/Ahy+kPe8bdJWhH6HrVMwzyc+BkwO5kJJw3FL76jEMJ5Z1r6+d7lWjz5ner6TmSKd14iXNXtu9q+/6WKqfrAd1qDFPwzXA6cEvdM09ejFTzWRm0fPDJIgoSTM2iUjSGfZjgIw7DW3n8FowWcU4tloSITm1jQF++Lu7mmqewsISdeIhou72HRQbi71DELH/eNYKS6jZHp8AZ44oLjD/b5DZXxQ5N0uhEDkRAWGDSjSTrk+sHqgx6lujDnqztmcahUMQ/SmC8nAp68rr96C93wpFk2uZ+gPcsiD6VcGFcB6RNQeB1+6PrHlQj9jdTlynXM9V57JJ80U/0vZVElaIh6cRnVhMpFj6HRDFQ7pRLSOUBoBVVuRKYCRxFSkhISFJ2p7tRSHi2AWELk7pzckDt3DniKxj7UBZUv8jFPL7HSqPCr+BvHlufWLkZuJzsokAw3bFL5dKLlsou1gNF0gjdNTEaRrRgaE9xFxgAzjKrVxtP8HY4O4ZAmBPb9DlkINFYDGfnNHCUpl/HGYVnATJxDWPKQeC8HgH34O6wG/vGsATsvClsWnTKT12vm11SdSGJ/ygxF/yrNrGzjhA5RYz+wZeUifK0LuKO5D45iD7M3hikaTmLUS8FjHpYWMQRErytM0e6SlyxeeDN/nkf+w9X67xS2Mhz8/yR4uLZspVk1LAoIwH0bqGz5lQoF0jLUrhEQHtD88deApYZNC8W8GCELM4Yk3mXpyCZZ562t9tLHNU7Xyz/YxKjd/1yx6UIocsDBP0qZd0ytK2Gp3nFr5dVVzxLTqzwPrwiByinoHt+q4G X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: 7hmfVoidjM0xqjYVXk2aQnLUfZunhpEqWWncXxu+R+Co30476Et1uq8PU+u7cFZlepNMJjd0Ky/AJQ2Az/hx5kRiW0YDqrJMS7eB0qwB1otnpwulwqU3UcjqwfBZSzAd3ZFQAQV+x6SaaB0pRIDi65L87wMB4P6BhQRJpx+HG0uSz4j4qPIgR0k8KYKjqkPaQeRkZz3fEFIvOtLYPkutBvyuUr8YZ6Tl+cYEpHw45H50THo/5U6fpzn0qR5Jnv9vc8IRj38kroPEQP5ktyqV54P1hSguoDvd6vItV0x0TqMq20iOHxz1WkIT5vL3tAduaDoay1DvVg6LZf6DoHoLPv5E2y7iQ5Gh1pyw+G8c3xAy6o9Ki61j2/yKsqu1layYNveDfXQ9LK2nxwsXDGNamSMWhHF35OK3yPbmQSRwY+u1M3kw8ma7aq365uEEr9iyMiPnKR52d1N6jnGLMba565E6c+0i8FpOov5s1XZADS9yUoLl8J5j16Hkql4105sDiplBNZuo2UQyjOyNMgpTX086Y/M5tqcbjMrnVwpix2VX0vim/TpG++VvKZg0pe6pNMUMx0w3jF4ssUahoLfKrXbvuEGgPEmA5xQQPGP+HWDK9MRcsuJfYoF0ZxczH2Mb7lao2YNrAQG1pecLnDS2wNcvWn53lkNmVf5f9HMAJfNKxuKe/1Fh+d0j+ZAn8Ofix4MESOwJKpVS4zNJF9HakgpLRQK+CE+dXbOavtyz2cbRkxpBC/qlwVRPIhcgyab7tX+mmBqvUr4xmeCo1Kd4kGs6ZhR30v+qnPZzOIpVN0e5GZbAjb16FXfY0F0GBFQZdg2PiKSIJp/8ygmyKMhciWZvq1pxU+JSu2PTRkh38E/aS/W6EaLDwwDfAVhGqPH2zFVAp/Q8jHPMEvaWejDfes9V8mCyf4oiIGLLDUt6xAzljSRw9vzOuEW+7azfpBF0 X-OriginatorOrg: oracle.com X-MS-Exchange-CrossTenant-Network-Message-Id: e5c5efca-c000-41cf-5c5e-08dba57f6651 X-MS-Exchange-CrossTenant-AuthSource: CH2PR10MB4344.namprd10.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 25 Aug 2023 15:24:40.1201 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 4e2c6054-71cb-48f1-bd6c-3a9705aca71b X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: sK6B8Fn99E4VHzoSFFJ+KFAE0AGPLS1BtvG+exrkB+YCJSLGLHjHFglrw02lO93JDqdiGvILSjHB9HsaA0NseQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY5PR10MB4241 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.957,Hydra:6.0.601,FMLib:17.11.176.26 definitions=2023-08-25_13,2023-08-25_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 bulkscore=0 suspectscore=0 malwarescore=0 spamscore=0 phishscore=0 mlxlogscore=999 adultscore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2308100000 definitions=main-2308250137 X-Proofpoint-GUID: Q9TFI-A0Fmu-pju_1M_VCKByWIgJ93R6 X-Proofpoint-ORIG-GUID: Q9TFI-A0Fmu-pju_1M_VCKByWIgJ93R6 X-Spam-Status: No, score=-11.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, 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-Patchwork-Original-From: Qing Zhao via Gcc-patches From: Qing Zhao Reply-To: Qing Zhao Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1775215272454401287 X-GMAIL-MSGID: 1775215272454401287 Use the counted_by atribute info in builtin object size to compute the subobject size for flexible array members. gcc/ChangeLog: PR C/108896 * tree-object-size.cc (addr_object_size): Use the counted_by attribute info. * tree.cc (component_ref_has_counted_by_p): New function. (component_ref_get_counted_by): New function. * tree.h (component_ref_has_counted_by_p): New prototype. (component_ref_get_counted_by): New prototype. gcc/testsuite/ChangeLog: PR C/108896 * gcc.dg/flex-array-counted-by-2.c: New test. * gcc.dg/flex-array-counted-by-3.c: New test. --- .../gcc.dg/flex-array-counted-by-2.c | 74 ++++++ .../gcc.dg/flex-array-counted-by-3.c | 210 ++++++++++++++++++ gcc/tree-object-size.cc | 37 ++- gcc/tree.cc | 95 +++++++- gcc/tree.h | 10 + 5 files changed, 418 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/flex-array-counted-by-2.c create mode 100644 gcc/testsuite/gcc.dg/flex-array-counted-by-3.c diff --git a/gcc/testsuite/gcc.dg/flex-array-counted-by-2.c b/gcc/testsuite/gcc.dg/flex-array-counted-by-2.c new file mode 100644 index 000000000000..ec580c1f1f01 --- /dev/null +++ b/gcc/testsuite/gcc.dg/flex-array-counted-by-2.c @@ -0,0 +1,74 @@ +/* test the attribute counted_by and its usage in + * __builtin_dynamic_object_size. */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#include "builtin-object-size-common.h" + +#define expect(p, _v) do { \ + size_t v = _v; \ + if (p == v) \ + __builtin_printf ("ok: %s == %zd\n", #p, p); \ + else \ + { \ + __builtin_printf ("WAT: %s == %zd (expected %zd)\n", #p, p, v); \ + FAIL (); \ + } \ +} while (0); + +struct flex { + int b; + int c[]; +} *array_flex; + +struct annotated { + int b; + int c[] __attribute__ ((counted_by (b))); +} *array_annotated; + +struct nested_annotated { + struct { + union { + int b; + float f; + }; + int n; + }; + int c[] __attribute__ ((counted_by (b))); +} *array_nested_annotated; + +void __attribute__((__noinline__)) setup (int normal_count, int attr_count) +{ + array_flex + = (struct flex *)malloc (sizeof (struct flex) + + normal_count * sizeof (int)); + array_flex->b = normal_count; + + array_annotated + = (struct annotated *)malloc (sizeof (struct annotated) + + attr_count * sizeof (int)); + array_annotated->b = attr_count; + + array_nested_annotated + = (struct nested_annotated *)malloc (sizeof (struct nested_annotated) + + attr_count * sizeof (int)); + array_nested_annotated->b = attr_count; + + return; +} + +void __attribute__((__noinline__)) test () +{ + expect(__builtin_dynamic_object_size(array_flex->c, 1), -1); + expect(__builtin_dynamic_object_size(array_annotated->c, 1), + array_annotated->b * sizeof (int)); + expect(__builtin_dynamic_object_size(array_nested_annotated->c, 1), + array_nested_annotated->b * sizeof (int)); +} + +int main(int argc, char *argv[]) +{ + setup (10,10); + test (); + DONE (); +} diff --git a/gcc/testsuite/gcc.dg/flex-array-counted-by-3.c b/gcc/testsuite/gcc.dg/flex-array-counted-by-3.c new file mode 100644 index 000000000000..a0c3cb88ec71 --- /dev/null +++ b/gcc/testsuite/gcc.dg/flex-array-counted-by-3.c @@ -0,0 +1,210 @@ +/* test the attribute counted_by and its usage in +__builtin_dynamic_object_size: what's the correct behavior when the +allocation size mismatched with the value of counted_by attribute? */ +/* { dg-do run } */ +/* { dg-options "-O -fstrict-flex-arrays=3" } */ + +#include "builtin-object-size-common.h" + +struct annotated { + size_t foo; + char others; + char array[] __attribute__((counted_by (foo))); +}; + +#define expect(p, _v) do { \ + size_t v = _v; \ + if (p == v) \ + __builtin_printf ("ok: %s == %zd\n", #p, p); \ + else \ + { \ + __builtin_printf ("WAT: %s == %zd (expected %zd)\n", #p, p, v); \ + FAIL (); \ + } \ +} while (0); + +#define noinline __attribute__((__noinline__)) +#define SIZE_BUMP 10 +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +/* In general, Due to type casting, the type for the pointee of a pointer + does not say anything about the object it points to, + So, __builtin_object_size can not directly use the type of the pointee + to decide the size of the object the pointer points to. + + there are only two reliable ways: + A. observed allocations (call to the allocation functions in the routine) + B. observed accesses (read or write access to the location of the + pointer points to) + + that provide information about the type/existence of an object at + the corresponding address. + + for A, we use the "alloc_size" attribute for the corresponding allocation + functions to determine the object size; + + For B, we use the SIZE info of the TYPE attached to the corresponding access. + (We treat counted_by attribute as a complement to the SIZE info of the TYPE + for FMA) + + The only other way in C which ensures that a pointer actually points + to an object of the correct type is 'static': + + void foo(struct P *p[static 1]); + + See https://gcc.gnu.org/pipermail/gcc-patches/2023-July/624814.html + for more details. */ + +/* in the following function, malloc allocated more space than the value + of counted_by attribute. Then what's the correct behavior we expect + the __builtin_dynamic_object_size should have for each of the cases? */ + +static struct annotated * noinline alloc_buf_more (size_t index) +{ + struct annotated *p; + size_t allocated_size + = MAX (sizeof (struct annotated), + (__builtin_offsetof (struct annotated, array[0]) + + (index + SIZE_BUMP) * sizeof (char))); + p = (struct annotated *) malloc (allocated_size); + + p->foo = index; + + /*when checking the observed access p->array, we have info on both + observered allocation and observed access, + A. from observed allocation: + allocated_size - offsetof (struct annotated, array[0]) + B. from observed access: p->foo * sizeof (char) + */ + + /* for size in the whole object: always uses A. */ + /* for size in the sub-object: chose the smaller of A and B. + * Please see https://gcc.gnu.org/pipermail/gcc-patches/2023-July/625891.html + * for details on why. */ + + /* for MAXIMUM size in the whole object: use the allocation size + for the whole object. */ + expect(__builtin_dynamic_object_size(p->array, 0), + allocated_size - __builtin_offsetof (struct annotated, array[0])); + + /* for MAXIMUM size in the sub-object. use the smaller of A and B. */ + expect(__builtin_dynamic_object_size(p->array, 1), + MIN (allocated_size - __builtin_offsetof (struct annotated, array[0]), + (p->foo) * sizeof(char))); + + /* for MINIMUM size in the whole object: use the allocation size + for the whole object. */ + expect(__builtin_dynamic_object_size(p->array, 2), + allocated_size - __builtin_offsetof (struct annotated, array[0])); + + /* for MINIMUM size in the sub-object: use the smaller of A and B. */ + expect(__builtin_dynamic_object_size(p->array, 3), + MIN (allocated_size - __builtin_offsetof (struct annotated, array[0]), + (p->foo) * sizeof(char))); + + /*when checking the pointer p, we only have info on the observed allocation. + So, the object size info can only been obtained from the call to malloc. + for both MAXIMUM and MINIMUM: A = (index + SIZE_BUMP) * sizeof (char) */ + expect(__builtin_dynamic_object_size(p, 0), allocated_size); + expect(__builtin_dynamic_object_size(p, 1), allocated_size); + expect(__builtin_dynamic_object_size(p, 2), allocated_size); + expect(__builtin_dynamic_object_size(p, 3), allocated_size); + return p; +} + +/* in the following function, malloc allocated less space than the value + of counted_by attribute. Then what's the correct behavior we expect + the __builtin_dynamic_object_size should have for each of the cases? + NOTE: this is an user error, GCC should issue warnings for such case. + this is a seperate issue we should address later. */ + +static struct annotated * noinline alloc_buf_less (size_t index) +{ + struct annotated *p; + size_t allocated_size + = MAX (sizeof (struct annotated), + (__builtin_offsetof (struct annotated, array[0]) + + (index) * sizeof (char))); + p = (struct annotated *) malloc (allocated_size); + + p->foo = index + SIZE_BUMP; + + /*when checking the observed access p->array, we have info on both + observered allocation and observed access, + A. from observed allocation: + allocated_size - offsetof (struct annotated, array[0]) + B. from observed access: p->foo * sizeof (char) + */ + + /* for size in the whole object: always uses A. */ + /* for size in the sub-object: chose the smaller of A and B. + * Please see https://gcc.gnu.org/pipermail/gcc-patches/2023-July/625891.html + * for details on why. */ + + /* for MAXIMUM size in the whole object: use the allocation size + for the whole object. */ + expect(__builtin_dynamic_object_size(p->array, 0), + allocated_size - __builtin_offsetof (struct annotated, array[0])); + + /* for MAXIMUM size in the sub-object. use the smaller of A and B. */ + expect(__builtin_dynamic_object_size(p->array, 1), + MIN (allocated_size - __builtin_offsetof (struct annotated, array[0]), + (p->foo) * sizeof(char))); + + /* for MINIMUM size in the whole object: use the allocation size + for the whole object. */ + expect(__builtin_dynamic_object_size(p->array, 2), + allocated_size - __builtin_offsetof (struct annotated, array[0])); + + /* for MINIMUM size in the sub-object: use the smaller of A and B. */ + expect(__builtin_dynamic_object_size(p->array, 3), + MIN (allocated_size - __builtin_offsetof (struct annotated, array[0]), + (p->foo) * sizeof(char))); + + /*when checking the pointer p, we only have info on the observed + allocation. So, the object size info can only been obtained from + the call to malloc. */ + expect(__builtin_dynamic_object_size(p, 0), allocated_size); + expect(__builtin_dynamic_object_size(p, 1), allocated_size); + expect(__builtin_dynamic_object_size(p, 2), allocated_size); + expect(__builtin_dynamic_object_size(p, 3), allocated_size); + return p; +} + +int main () +{ + struct annotated *p, *q; + p = alloc_buf_more (10); + q = alloc_buf_less (10); + + /*when checking the observed access p->array, we only have info on the + observed access, i.e, the TYPE_SIZE info from the access. We don't have + info on the whole object. */ + expect(__builtin_dynamic_object_size(p->array, 0), -1); + expect(__builtin_dynamic_object_size(p->array, 1), p->foo * sizeof(char)); + expect(__builtin_dynamic_object_size(p->array, 2), 0); + expect(__builtin_dynamic_object_size(p->array, 3), p->foo * sizeof(char)); + /*when checking the pointer p, we have no observed allocation nor observed + access, therefore, we cannot determine the size info here. */ + expect(__builtin_dynamic_object_size(p, 0), -1); + expect(__builtin_dynamic_object_size(p, 1), -1); + expect(__builtin_dynamic_object_size(p, 2), 0); + expect(__builtin_dynamic_object_size(p, 3), 0); + + /*when checking the observed access p->array, we only have info on the + observed access, i.e, the TYPE_SIZE info from the access. We don't have + info on the whole object. */ + expect(__builtin_dynamic_object_size(q->array, 0), -1); + expect(__builtin_dynamic_object_size(q->array, 1), q->foo * sizeof(char)); + expect(__builtin_dynamic_object_size(q->array, 2), 0); + expect(__builtin_dynamic_object_size(q->array, 3), q->foo * sizeof(char)); + /*when checking the pointer p, we have no observed allocation nor observed + access, therefore, we cannot determine the size info here. */ + expect(__builtin_dynamic_object_size(q, 0), -1); + expect(__builtin_dynamic_object_size(q, 1), -1); + expect(__builtin_dynamic_object_size(q, 2), 0); + expect(__builtin_dynamic_object_size(q, 3), 0); + + DONE (); +} diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc index a62af0500563..cf7843c5684b 100644 --- a/gcc/tree-object-size.cc +++ b/gcc/tree-object-size.cc @@ -585,6 +585,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, if (pt_var != TREE_OPERAND (ptr, 0)) { tree var; + tree counted_by_ref = NULL_TREE; if (object_size_type & OST_SUBOBJECT) { @@ -600,11 +601,12 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, var = TREE_OPERAND (var, 0); if (var != pt_var && TREE_CODE (var) == ARRAY_REF) var = TREE_OPERAND (var, 0); - if (! TYPE_SIZE_UNIT (TREE_TYPE (var)) + if (! component_ref_has_counted_by_p (var) + && ((! TYPE_SIZE_UNIT (TREE_TYPE (var)) || ! tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (var))) || (pt_var_size && TREE_CODE (pt_var_size) == INTEGER_CST && tree_int_cst_lt (pt_var_size, - TYPE_SIZE_UNIT (TREE_TYPE (var))))) + TYPE_SIZE_UNIT (TREE_TYPE (var))))))) var = pt_var; else if (var != pt_var && TREE_CODE (pt_var) == MEM_REF) { @@ -612,6 +614,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, /* For &X->fld, compute object size if fld isn't a flexible array member. */ bool is_flexible_array_mem_ref = false; + while (v && v != pt_var) switch (TREE_CODE (v)) { @@ -660,6 +663,8 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, /* Now the ref is to an array type. */ gcc_assert (TREE_CODE (TREE_TYPE (v)) == ARRAY_TYPE); is_flexible_array_mem_ref = array_ref_flexible_size_p (v); + counted_by_ref = component_ref_get_counted_by (v); + while (v != pt_var && TREE_CODE (v) == COMPONENT_REF) if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) != UNION_TYPE @@ -673,8 +678,11 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, == RECORD_TYPE) { /* compute object size only if v is not a - flexible array member. */ - if (!is_flexible_array_mem_ref) + flexible array member or the flexible array member + has a known element count indicated by the user + through attribute counted_by. */ + if (!is_flexible_array_mem_ref + || counted_by_ref) { v = NULL_TREE; break; @@ -707,9 +715,24 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, if (var != pt_var) { - var_size = TYPE_SIZE_UNIT (TREE_TYPE (var)); - if (!TREE_CONSTANT (var_size)) - var_size = get_or_create_ssa_default_def (cfun, var_size); + if (!counted_by_ref) + { + var_size = TYPE_SIZE_UNIT (TREE_TYPE (var)); + if (!TREE_CONSTANT (var_size)) + var_size = get_or_create_ssa_default_def (cfun, var_size); + } + else + { + gcc_assert (TREE_CODE (var) == COMPONENT_REF + && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE); + tree element_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (var))); + var_size + = size_binop (MULT_EXPR, + fold_convert (sizetype, counted_by_ref), + fold_convert (sizetype, element_size)); + if (!todo) + todo = TODO_update_ssa_only_virtuals; + } if (!var_size) return false; } diff --git a/gcc/tree.cc b/gcc/tree.cc index fcd36ae0cd74..3b6ddcbdcbf8 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -12745,6 +12745,32 @@ array_ref_element_size (tree exp) return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (elmt_type), exp); } +/* For a component_ref that has an array type ARRAY_REF, return TRUE when + an counted_by attribute attached to the corresponding FIELD_DECL. + return FALSE otherwise. */ +bool +component_ref_has_counted_by_p (tree array_ref) +{ + if (TREE_CODE (array_ref) != COMPONENT_REF) + return false; + + if (TREE_CODE (TREE_TYPE (array_ref)) != ARRAY_TYPE) + return false; + + tree struct_object = TREE_OPERAND (array_ref, 0); + tree struct_type = TREE_TYPE (struct_object); + + if (!RECORD_OR_UNION_TYPE_P (struct_type)) + return false; + tree field_decl = TREE_OPERAND (array_ref, 1); + tree attr_counted_by = lookup_attribute ("counted_by", + DECL_ATTRIBUTES (field_decl)); + + if (!attr_counted_by) + return false; + return true; +} + /* Given a field list, FIELDLIST, of a structure/union, return a TREE_LIST, with each TREE_VALUE a FIELD_DECL stepping down the chain to the FIELD whose name is FIELDNAME, which is the last TREE_VALUE of the list. @@ -12771,7 +12797,7 @@ get_named_field (tree fieldlist, const char *fieldname) fields inside it recursively. */ else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))) if ((named_field = get_named_field (TYPE_FIELDS (TREE_TYPE (field)), - fieldname)) != NULL_TREE) + fieldname)) != NULL_TREE) { named_field = tree_cons (NULL_TREE, field, named_field); break; @@ -12784,6 +12810,73 @@ get_named_field (tree fieldlist, const char *fieldname) return named_field; } +/* For a component_ref that has an array type ARRAY_REF, get the object that + represents its counted_by per the attribute counted_by attached to + the corresponding FIELD_DECL. return NULL_TREE when cannot find such + object. + For example, if: + + struct P { + int k; + int x[] __attribute__ ((counted_by (k))); + } *p; + + for the following reference: + + p->x[b] + + the object that represents its element count will be: + + p->k + + So, when component_ref_get_counted_by (p->x[b]) is called, p->k should be + returned. +*/ + +tree +component_ref_get_counted_by (tree array_ref) +{ + if (! component_ref_has_counted_by_p (array_ref)) + return NULL_TREE; + + tree struct_object = TREE_OPERAND (array_ref, 0); + tree struct_type = TREE_TYPE (struct_object); + tree field_decl = TREE_OPERAND (array_ref, 1); + tree attr_counted_by = lookup_attribute ("counted_by", + DECL_ATTRIBUTES (field_decl)); + gcc_assert (attr_counted_by); + + /* If there is an counted_by attribute attached to the field, + get the field that maps to the counted_by. */ + + const char *fieldname + = IDENTIFIER_POINTER (TREE_VALUE (TREE_VALUE (attr_counted_by))); + + tree counted_by_field = get_named_field (TYPE_FIELDS (struct_type), + fieldname); + + gcc_assert (counted_by_field); + + /* generate the tree node that represent the counted_by of this array + ref. This is a (possible nested) COMPONENT_REF to the counted_by_field + of the containing structure. */ + + tree counted_by_ref = NULL_TREE; + tree object = struct_object; + do + { + tree field = TREE_VALUE (counted_by_field); + + counted_by_ref = build3 (COMPONENT_REF, + TREE_TYPE (field), + unshare_expr (object), field, + NULL_TREE); + object = counted_by_ref; + counted_by_field = TREE_CHAIN (counted_by_field); + } + while (counted_by_field); + return counted_by_ref; +} /* Return a tree representing the lower bound of the array mentioned in EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */ diff --git a/gcc/tree.h b/gcc/tree.h index 4859becaa1e7..07eed7219835 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -5619,11 +5619,21 @@ extern tree get_base_address (tree t); of EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */ extern tree array_ref_element_size (tree); +/* Give a component_ref that has an array type, return true when an + attribute counted_by attached to the corresponding FIELD_DECL. */ +extern bool component_ref_has_counted_by_p (tree); + /* Given a field list, FIELDLIST, of a structure/union, return the FIELD whose name is FIELDNAME, return NULL_TREE if such field is not found. searching nested anonymous structure/union recursively. */ extern tree get_named_field (tree, const char *); +/* Give a component_ref that has an array type, return the object that + represents its counted_by per the attribute counted_by attached to + the corresponding FIELD_DECL. return NULL_TREE when cannot find such + object. */ +extern tree component_ref_get_counted_by (tree); + /* Return a typenode for the "standard" C type with a given name. */ extern tree get_typenode_from_name (const char *); From patchwork Fri Aug 25 15:24:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qing Zhao X-Patchwork-Id: 136925 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:a7d1:0:b0:3f2:4152:657d with SMTP id p17csp1875224vqm; Fri, 25 Aug 2023 08:27:48 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEvTPk2Mbvbz/CIcEHWH63vukxivSURggvkXsyfsV8jVHZOYaHbTtAIPLwoBqLcQdR9uqUq X-Received: by 2002:a17:906:5a4f:b0:9a1:c4ba:c04b with SMTP id my15-20020a1709065a4f00b009a1c4bac04bmr10567647ejc.4.1692977268321; Fri, 25 Aug 2023 08:27:48 -0700 (PDT) Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id kl4-20020a170907994400b0099cbd8ab716si1085514ejc.820.2023.08.25.08.27.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 25 Aug 2023 08:27:48 -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=pass header.i=@gcc.gnu.org header.s=default header.b=OCopsUkr; arc=fail (signature failed); 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"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 75F1D3864844 for ; Fri, 25 Aug 2023 15:26:42 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 75F1D3864844 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1692977202; bh=J2ZZj7DJBAapJ3W2Hsq+zazNq3PQ0nuKgjYcmTQezkw=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=OCopsUkraruU1WOeBDHFAk/fr+7eT8RlM7ILu+gVejQmj+zZFX0vmMfgMS5zkP+Lu 74kktxhS6r1ZYIiUZqko0mMcERGprxY7kbno+zYuUC8MHFGq9eRo0T1i8uqacqDBKw 5OI4oFK3HnkChgnzTkq8E/L3YR+G0BDDdCaVaXIY= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mx0a-00069f02.pphosted.com (mx0a-00069f02.pphosted.com [205.220.165.32]) by sourceware.org (Postfix) with ESMTPS id 4DBB538582B7 for ; Fri, 25 Aug 2023 15:24:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 4DBB538582B7 Received: from pps.filterd (m0246627.ppops.net [127.0.0.1]) by mx0b-00069f02.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 37PDOChY018192; Fri, 25 Aug 2023 15:24:47 GMT Received: from phxpaimrmta03.imrmtpd1.prodappphxaev1.oraclevcn.com (phxpaimrmta03.appoci.oracle.com [138.1.37.129]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 3sn1yxphha-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 25 Aug 2023 15:24:47 +0000 Received: from pps.filterd (phxpaimrmta03.imrmtpd1.prodappphxaev1.oraclevcn.com [127.0.0.1]) by phxpaimrmta03.imrmtpd1.prodappphxaev1.oraclevcn.com (8.17.1.19/8.17.1.19) with ESMTP id 37PFGirl001127; Fri, 25 Aug 2023 15:24:46 GMT Received: from nam02-sn1-obe.outbound.protection.outlook.com (mail-sn1nam02lp2043.outbound.protection.outlook.com [104.47.57.43]) by phxpaimrmta03.imrmtpd1.prodappphxaev1.oraclevcn.com (PPS) with ESMTPS id 3sn1yuydrg-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 25 Aug 2023 15:24:46 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Meqi/YPKglTOgzGC8D0Kvbc8RRYwvZRq+hhR+uEGZG+4ISV60QaU/bdFhh1DlPjeiq0SD3/2I9Ngf+RZEzBydcnS6DZBcolp+zfMnlanwc+U7o0mjk/qWFS0YXHD7jSCjrIcPWktN7rut8gGw5caP0AyQszSRxvUlWUC0BTKtBLkHA8wG+7Z+neyHZG2RPm6p8OhrxECvY7hxhcdyM6l7H1NFyZjGaoH+kMh9v3sHHzS4+2smmAAe4ViGcs3BLdEAiD56xXCOiM2Y4yayBt7X2xrJ5f3Qr7bVDbxRAIzz4mSmXYhTVtwejf2ZKs9XyQ6goKdxD0XpNEsyOIjvTe1uA== 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=J2ZZj7DJBAapJ3W2Hsq+zazNq3PQ0nuKgjYcmTQezkw=; b=jgzf13keOtpGUCDr3aepL/9zpioQHhSF3HR6RkCDANrI+0kERobrnWt97Ob0P4GYFz0TONBJ23Ops2/1Eir78IS5amOhldWX/DF2E4TAJzSLvXRCJKaYpbtGCJADGQJu3csWSCxPKeEXAse9BuuqjGdnw7ndiEQL07RexmB4eidfz+bRuWIHSSF3XWXOmsRw0lhgNXAV8z8x8W0D2riGqgTBCTEk7nAflgRTEEJ/sGRT5WMzUKf/sFgQjyYKqLuOL8q7TmbZYwnv6gxLecnb8Kr/waxPZQXL+ZjHyXX+iBC204rJuPmS7H34zUaHr7qnXFVVKnVTSJF8+cRCPXix1Q== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oracle.com; dmarc=pass action=none header.from=oracle.com; dkim=pass header.d=oracle.com; arc=none Received: from CH2PR10MB4344.namprd10.prod.outlook.com (2603:10b6:610:af::19) by BY5PR10MB4241.namprd10.prod.outlook.com (2603:10b6:a03:208::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.27; Fri, 25 Aug 2023 15:24:44 +0000 Received: from CH2PR10MB4344.namprd10.prod.outlook.com ([fe80::5afd:d02a:38ef:94ba]) by CH2PR10MB4344.namprd10.prod.outlook.com ([fe80::5afd:d02a:38ef:94ba%7]) with mapi id 15.20.6699.028; Fri, 25 Aug 2023 15:24:44 +0000 To: joseph@codesourcery.com, richard.guenther@gmail.com, jakub@redhat.com, gcc-patches@gcc.gnu.org Cc: keescook@chromium.org, siddhesh@gotplt.org, uecker@tugraz.at, isanbard@gmail.com, Qing Zhao Subject: [V3][PATCH 3/3] Use the counted_by attribute information in bound sanitizer[PR108896] Date: Fri, 25 Aug 2023 15:24:25 +0000 Message-Id: <20230825152425.2417656-4-qing.zhao@oracle.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20230825152425.2417656-1-qing.zhao@oracle.com> References: <20230825152425.2417656-1-qing.zhao@oracle.com> X-ClientProxiedBy: SJ0PR03CA0068.namprd03.prod.outlook.com (2603:10b6:a03:331::13) To CH2PR10MB4344.namprd10.prod.outlook.com (2603:10b6:610:af::19) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PR10MB4344:EE_|BY5PR10MB4241:EE_ X-MS-Office365-Filtering-Correlation-Id: e1c7ac23-2be3-477b-4774-08dba57f68e3 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: gawLQsUCoZymUDU/qB9Cgd6wNuK/JfNtMIJbrHK7sUEkaqCGVEqQ1JJ5kW/3QktLufeopbEngkIS1ItNco0aVAlY8OBJ/mlhh7ASDeJJvlfcan9KVRRhdYFx/lgIu4PLLfxun1wzwVSlfdahrVQCMQ7WZP52axgJ8CkWNSLg36oQ9nOiNovTqbJSKZduEyeZvTkAYqjdE2KMWKcvdqQ8fxDti4QJDAJZESmwYRk99HL6gXdeB/7mwgV4GyvYe2dHBkBRfysI/MU8nNexYcWyghTrei3/G4sNv9v5PlPfQIZzhchc6eblpVe9HH3YbDg7HPo5wdrmEGexDeW9mwteaqK0K8A7rxYdFDKLBHpu0hon5YLAcvq9s6ykW412IAB45tjGL62nseY6PvgxnoQqDHfAG5q0Md5d0ComrfntCYMGFKX7HS1STfbZhaIJZeFgSCvL+gVQwFaieLuvSi2qdNK0ukdjzdK9SBRGwIMSKrc7x7IThbrDNElVo7PhreOrSif2MCONWdSvhHFKXaFzFjoavQlhtqPgxj7OGLp7J3XCl1EKOIIUuLlCYHZrhgj2QYLjj+AISiZT90ZFuD9yYA== X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:CH2PR10MB4344.namprd10.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230031)(346002)(136003)(396003)(39860400002)(366004)(376002)(451199024)(186009)(1800799009)(66946007)(66476007)(66556008)(316002)(478600001)(26005)(44832011)(6666004)(38100700002)(84970400001)(41300700001)(86362001)(6486002)(6512007)(6506007)(2906002)(8676002)(4326008)(8936002)(1076003)(2616005)(5660300002)(107886003)(36756003); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: V5QZ3mFwNuSmVIecqnU+SnPokFLFB6HhhAIZPrFU0oZmY3alI+nJdHl10vcXb1PDpp72li3qpEV5Zld6iaZgox973LmqEDN5ZqaNs2PCC3zGc3MVbJCKPkHXnTbw+S/OAL+gbMDpuM9ssaR/Wep7/85+cCMK1d7QbgynTUMDldjaNn13sAS26rIri4YTaFUGv4szogAY7VTkxyJ8kcTKcdojONUBpNW3HhKuXKLqwaNSKOdCWd8c0fmsSZrhs07dcqI5tz08sPkgxHcN/ktQls6v6tzAxNqiQrLwShDFq4RhTtejEnpxHIxSzElWTvyqCPIubQjoFCajUCrTQHZMcKJUIjU+rdPwG0R1F9h5PQwFwa63gbRnmI5vN9/js2ZBmFW3CQr+OCthPoHZtWIRFvhkwFC/KfafRH97ZtbUxcOljU/7IWDBGq1WlQTlzmmJaBLFVRPeOOgGYio6eoGID622Zsf58lQuyWD134N4Om6yewpMV7FSWJgmm0qOntLXLG7ZLOkrhbdQlUyQfdVcKMXTT7IMgdG35VGpmEmaIkzTJNW6+G7dhzL9ZsaNUWKcdu09XLirxnDn2V47yGMvWYC92DDd9H3fOL5j8ZuITadeDn61j//nTcVJNZoqLbDDjOnciSpL7q6SZeYb3f/EYm7ydzE86Dj9sT64Kn+CHOJoP/YpEIsMFDt7gg+b0zm4hSi5KZN9a3wFtZkGzYQ2NyeiX7etZh4YkYwaYBlGn+eqBlEKfaWLZ0vo2uoF6ybzajRljn81GLBG29H31LtK+MlNnoI4Q6iKFxjnFV5aU5hqsTWS5HE279J7UZ30nn0r+cX92YXL+bOz0U7nGYLpzXLlYhVeUkCzHBx/8kNMEZp/UUky3JkNPYxkP2jVGatBRj8eACSaBTR4RKfGT4jPh9HGByNCYR8tz73QrwaiNtSXbrRVs4dlRpTg9a1TIBkhN022visOlxyUNGYoWJx5lnL/kIRl/ccdaKi66JXVOX2dTfuDbKZolTdTZcIxYEo8iE6v36pya+kwYcoPQWHusx2X7GI/1cvdIedxV84BJUYQfs1zwYOo55+E9yGfKDHRXP061G4P1BlVzfRfVfMX9xzRRFhnMugsu+yyh5+qQbM7+0ml3mo0eoOiGP3jr0XmWkwkUr6lIdSLlJoXIB705h+En/+1F5R9hDXOQwGe2L49dciONlnBwYJWm0HZSPSOI4F+MQtPk3FHpnG8ZfAsesMlU9nIO+/PwvizJkXyzj5owXCtx9ejXGe7bxaIUpa8rSBK5/RTyMbuGx86eMXHbob3U5OEeYChdyoIID+JbtQVE27flJBFcBUomkcYBOmtOLhtCkbEIlL1EPWj7Q+W4XHG18zZlTFnm8we0aL43eHEDiyx6v0r4LtJisbbglwOwtyl8IqMgU1C7TyjlRxEgRwyMUtabxANgIIlK9mKIeY2JSoeC4RXDka2HiMKJfH8vWqP3j/wYhUGX4Ayguiqtd2F/Q5TEu21iAB+78py/ieR3ptWiq1atOJqpGh4vXOz2DTExbg5/RsqXtJDOFUu4i83tdpe8qUAaaxtpadBqECQXHqRBu8U9kjOQxxI2T8C X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: vE1b9dSNwcX1EcMlKUB5cI5uVNfPnaz59o2iw79BOybUf5PtPvGtiDhxVb5cbqjr8547Rsh04mMexr/1cx1rqr+pr1DI9jCUV/6fEPMI3caE/22wSC1ofzULi0LYY8zj1fA6odMbRAJOQ7Y0+uCC/sdzn/QxtRrVlbdP1sBGGkLOSHDVZn94ZDKqRGCbhGOaLFRFQ2gTRR2TSJeA/OFk0L4IZq8xvU8cyuMkXCweW4RC0ymKW716xQn6Os6xKqq83slWwTU1QPvuqm2D32PPmZaa4ceRMAs6GxIB7iX8+TgPcQEpJKJuaWjLE0FG/g1uV+uNBpf7isFHGRbNr1o288AHnkH4mFkKtylIFIXcQzfeEkt37LKQ3EIZkZ+1XH4ySZ4Vyu9oAcX/G9HDQSPiQfRRgBPhtwChBs/i8nddVp948TmndBF0hytERm+gphekWvqiWItiGHR7LURfaC5ClW204uZvaKERI8as7A5axGzF4dVbUr4g7c0TE0tTl4f51wGy2WbqVcc+pLjQsdYBCw0i2yZjCaKDava5HEJi+pLQqMBhwHfppsstDPbMYcheCnDU7gK55ZnIE85SamG0TT7rWTXzZC5H/xq6qvIEqU9BCqDcIn8xE/Jdk26wgTbKS9aTkfyBAK1w2JbGWaw/HKHg8R7ZB7aOQrgFsv1W/EHgcb3lizVdj9gyHT7rgXFOSfUrxDoQoc58tT2ZjHG1H5+pkcfmuGmbP+h0uXdxNh1KT17h6NNy/nye3ftDI5DEMWHVnFwyQr31DIivyZxZ/B+zm8anvolWrt4BCPSpYQceT29LJSPgPR05wO7EZLJmjItJOPkTUJA39mhO3J67PhHzghRh+lVrlsWMDE49Ol1e8x456tME7FD0fqiyPqUofsF5a4lA/1+6GC1a6LjnmRnWkGaYC+XB2Bq3dCKcHrffDeEsewktm6NqD7Vykydp X-OriginatorOrg: oracle.com X-MS-Exchange-CrossTenant-Network-Message-Id: e1c7ac23-2be3-477b-4774-08dba57f68e3 X-MS-Exchange-CrossTenant-AuthSource: CH2PR10MB4344.namprd10.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 25 Aug 2023 15:24:44.4518 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 4e2c6054-71cb-48f1-bd6c-3a9705aca71b X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: y50KNEhi9DZZzNGKp+n+qdqd90vnM6wKS0uTKQFjARo1sdR/4epq+O3NpyItzKQn0ZgmK0j/XNJg+d7YZlIoGw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY5PR10MB4241 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.957,Hydra:6.0.601,FMLib:17.11.176.26 definitions=2023-08-25_13,2023-08-25_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 mlxscore=0 spamscore=0 bulkscore=0 malwarescore=0 phishscore=0 suspectscore=0 adultscore=0 mlxlogscore=810 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2308100000 definitions=main-2308250137 X-Proofpoint-GUID: VKkodp4UVymexTdzLqOOhb6qQsCVmAR_ X-Proofpoint-ORIG-GUID: VKkodp4UVymexTdzLqOOhb6qQsCVmAR_ X-Spam-Status: No, score=-11.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, 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-Patchwork-Original-From: Qing Zhao via Gcc-patches From: Qing Zhao Reply-To: Qing Zhao Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1775215332110772432 X-GMAIL-MSGID: 1775215332110772432 Use the counted_by attribute information in bound sanitizer. gcc/c-family/ChangeLog: PR C/108896 * c-ubsan.cc (ubsan_instrument_bounds): Use counted_by attribute information. gcc/testsuite/ChangeLog: PR C/108896 * gcc.dg/ubsan/flex-array-counted-by-bounds.c: New test. * gcc.dg/ubsan/flex-array-counted-by-bounds-2.c: New test. --- gcc/c-family/c-ubsan.cc | 16 +++++++ .../ubsan/flex-array-counted-by-bounds-2.c | 27 +++++++++++ .../ubsan/flex-array-counted-by-bounds.c | 46 +++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/ubsan/flex-array-counted-by-bounds-2.c create mode 100644 gcc/testsuite/gcc.dg/ubsan/flex-array-counted-by-bounds.c diff --git a/gcc/c-family/c-ubsan.cc b/gcc/c-family/c-ubsan.cc index 51aa83a378d2..a99e8433069f 100644 --- a/gcc/c-family/c-ubsan.cc +++ b/gcc/c-family/c-ubsan.cc @@ -362,6 +362,10 @@ ubsan_instrument_bounds (location_t loc, tree array, tree *index, { tree type = TREE_TYPE (array); tree domain = TYPE_DOMAIN (type); + /* whether the array ref is a flexible array member with valid counted_by + attribute. */ + bool fam_has_count_attr = false; + tree counted_by = NULL_TREE; if (domain == NULL_TREE) return NULL_TREE; @@ -375,6 +379,17 @@ ubsan_instrument_bounds (location_t loc, tree array, tree *index, && COMPLETE_TYPE_P (type) && integer_zerop (TYPE_SIZE (type))) bound = build_int_cst (TREE_TYPE (TYPE_MIN_VALUE (domain)), -1); + /* If the array ref is to flexible array member field which has + counted_by attribute. We can use the information from the + attribute as the bound to instrument the reference. */ + else if ((counted_by = component_ref_get_counted_by (array)) + != NULL_TREE) + { + fam_has_count_attr = true; + bound = fold_build2 (MINUS_EXPR, TREE_TYPE (counted_by), + counted_by, + build_int_cst (TREE_TYPE (counted_by), 1)); + } else return NULL_TREE; } @@ -387,6 +402,7 @@ ubsan_instrument_bounds (location_t loc, tree array, tree *index, -fsanitize=bounds-strict. */ tree base = get_base_address (array); if (!sanitize_flags_p (SANITIZE_BOUNDS_STRICT) + && !fam_has_count_attr && TREE_CODE (array) == COMPONENT_REF && base && (INDIRECT_REF_P (base) || TREE_CODE (base) == MEM_REF)) { diff --git a/gcc/testsuite/gcc.dg/ubsan/flex-array-counted-by-bounds-2.c b/gcc/testsuite/gcc.dg/ubsan/flex-array-counted-by-bounds-2.c new file mode 100644 index 000000000000..77ec333509d0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ubsan/flex-array-counted-by-bounds-2.c @@ -0,0 +1,27 @@ +/* test the attribute counted_by and its usage in + bounds sanitizer combined with VLA. */ +/* { dg-do run } */ +/* { dg-options "-fsanitize=bounds" } */ + +#include + +void __attribute__((__noinline__)) setup_and_test_vla (int n, int m) +{ + struct foo { + int n; + int p[][n] __attribute__((counted_by(n))); + } *f; + + f = (struct foo *) malloc (sizeof(struct foo) + m*sizeof(int[n])); + f->n = m; + f->p[m][n-1]=1; + return; +} + +int main(int argc, char *argv[]) +{ + setup_and_test_vla (10, 11); + return 0; +} + +/* { dg-output "17:8: runtime error: index 11 out of bounds for type" } */ diff --git a/gcc/testsuite/gcc.dg/ubsan/flex-array-counted-by-bounds.c b/gcc/testsuite/gcc.dg/ubsan/flex-array-counted-by-bounds.c new file mode 100644 index 000000000000..81eaeb3f2681 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ubsan/flex-array-counted-by-bounds.c @@ -0,0 +1,46 @@ +/* test the attribute counted_by and its usage in + bounds sanitizer. */ +/* { dg-do run } */ +/* { dg-options "-fsanitize=bounds" } */ + +#include + +struct flex { + int b; + int c[]; +} *array_flex; + +struct annotated { + int b; + int c[] __attribute__ ((counted_by (b))); +} *array_annotated; + +void __attribute__((__noinline__)) setup (int normal_count, int annotated_count) +{ + array_flex + = (struct flex *)malloc (sizeof (struct flex) + + normal_count * sizeof (int)); + array_flex->b = normal_count; + + array_annotated + = (struct annotated *)malloc (sizeof (struct annotated) + + annotated_count * sizeof (int)); + array_annotated->b = annotated_count; + + return; +} + +void __attribute__((__noinline__)) test (int normal_index, int annotated_index) +{ + array_flex->c[normal_index] = 1; + array_annotated->c[annotated_index] = 2; +} + +int main(int argc, char *argv[]) +{ + setup (10, 10); + test (10, 10); + return 0; +} + +/* { dg-output "36:21: runtime error: index 10 out of bounds for type" } */