From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx0a-00069f02.pphosted.com (mx0a-00069f02.pphosted.com [205.220.165.32]) by sourceware.org (Postfix) with ESMTPS id 6DEB73858430 for ; Fri, 8 Sep 2023 14:12:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 6DEB73858430 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=oracle.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=oracle.com Received: from pps.filterd (m0246629.ppops.net [127.0.0.1]) by mx0b-00069f02.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 388DxHVU024937; Fri, 8 Sep 2023 14:12:29 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : cc : subject : date : message-id : references : in-reply-to : content-type : content-id : content-transfer-encoding : mime-version; s=corp-2023-03-30; bh=2aONdr2+Oq9JmyE3RFKUrJXmOzxX3iyZNXBHGjXyQ4s=; b=nKe0Uh+6NfLTPGau+OFRrwMw/yuMXOZD9HpugpUfvlhWUp6lhVFskSwuuhx3FXngNPA6 okM95sAL5m1UKupvdotg3Q+YVL1mM2lpup2sNcQv9vmWpfRlynM0zIVRhkUdzYoDBL9Z dyJ2U6SBXXgDwvc8LphAvJwnibJRy6LNWtNNdB+IlRJRtTcTr/gpyXAvTwNatsZQ8Ua7 y8/Z+P236ISQrUUhFO6xn+O2oVLpT7052QjmGul0YTtIS7YjVaUixTNFdSU3btqAIgCz zrkgyMEMqxYi53XC8dNRN1Jur23XzxZMnp+J8EUTSQXquCavsliA6JTKokq5leukWLia 8w== Received: from phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (phxpaimrmta01.appoci.oracle.com [138.1.114.2]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 3t04sjr2fj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 08 Sep 2023 14:12:28 +0000 Received: from pps.filterd (phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com [127.0.0.1]) by phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (8.17.1.19/8.17.1.19) with ESMTP id 388CgWS6025340; Fri, 8 Sep 2023 14:12:28 GMT Received: from nam12-bn8-obe.outbound.protection.outlook.com (mail-bn8nam12lp2174.outbound.protection.outlook.com [104.47.55.174]) by phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (PPS) with ESMTPS id 3suug973xf-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 08 Sep 2023 14:12:27 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=hPDMc4WhbIk5hVg90pz1MOWxv0fTOUTGyyhAkNTtHlecKjicpu8GjIrqUKjBwQjjvC+3RNsc2sGuZdYaapcBLZkrsk7Hi8uubMke+hsmCSNeqDNNqRDsj6XT8E7dTTN9YnVCPpPuXNbD/IYP3aegbloJKCqTctq1PwU7R883QU7yDwf8LmJeqOQgU1OSlAaeGHUcLgdxgp/mBflK+jS9goZuhYbYgisV87HeAPxoYR18MIAshZE0ytzzBTcvSEwApa7jl90+Dk+N/9gzPfU7T5KieMRMYy+PJnwgo7SEjYMLxeHHjGdNfPEaFuK0aIMKK+dt0qH6yP2KSkmCxvDe5Q== 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=2aONdr2+Oq9JmyE3RFKUrJXmOzxX3iyZNXBHGjXyQ4s=; b=Ejnv3N8e5cGXUOUnXyoDdIaNbnFNf6qsJFA0F2RrdRwdQ+eMJewH5P8pDk6vzxcL8uhZIBd6NjxLzi8JBqAKY0rFzED+x2zZVe8mKaqYVlTZ/yblERlCZIrCRRswHSgz626n56KJa04OIEeH0LDHo5tsjGOOGkrYI9Rku51tGF9xP+NSr9VYXrgrvh4O3EdymxiQFCoO6iMqWDxi59wmow3eT4mayoFI26F0vlhp+fBV/TVCbL3Ts6aAoUZP48dqMoerIJ2EDHBrpmA8HIPgjOzc6b+8ThmT+LkuEGPYyOg0/CPhi99aMPzs9hGCZv2PQERD+3YNa6EP6kRpJDYlLQ== 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 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.onmicrosoft.com; s=selector2-oracle-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=2aONdr2+Oq9JmyE3RFKUrJXmOzxX3iyZNXBHGjXyQ4s=; b=CDYv3q+t0gM0NSY9S7t5Mv7NdbktAnjpzFIkksAhoP9xG6dACRZQhp4ZGfCgLcMlMEqzxxNcnnC2+zeG3ZY9PHHtnIKE5NKGFcJwlr3hg+SYd2/XWIXDRMYbZn2Gk+Gjaf+prEsBfBfsjXv2XPi1VOen76Vk8OpqldzOmdhq+dQ= Received: from CH2PR10MB4344.namprd10.prod.outlook.com (2603:10b6:610:af::19) by BN0PR10MB5189.namprd10.prod.outlook.com (2603:10b6:408:117::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6768.30; Fri, 8 Sep 2023 14:12:25 +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.6768.029; Fri, 8 Sep 2023 14:12:25 +0000 From: Qing Zhao To: Joseph Myers , "richard.guenther@gmail.com" , jakub Jelinek , "gcc-patches@gcc.gnu.org" CC: "keescook@chromium.org" , "siddhesh@gotplt.org" , "uecker@tugraz.at" , "isanbard@gmail.com" Subject: Re: [V3][PATCH 1/3] Provide counted_by attribute to flexible array member field (PR108896) Thread-Topic: [V3][PATCH 1/3] Provide counted_by attribute to flexible array member field (PR108896) Thread-Index: AQHZ12hBjKMnBp+fbEKNJydjoqv0ULARDiiA Date: Fri, 8 Sep 2023 14:12:24 +0000 Message-ID: <455BB7B3-9DE8-4D7B-A3BF-7284D25207A8@oracle.com> References: <20230825152425.2417656-1-qing.zhao@oracle.com> <20230825152425.2417656-2-qing.zhao@oracle.com> In-Reply-To: <20230825152425.2417656-2-qing.zhao@oracle.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-mailer: Apple Mail (2.3696.120.41.1.3) x-ms-publictraffictype: Email x-ms-traffictypediagnostic: CH2PR10MB4344:EE_|BN0PR10MB5189:EE_ x-ms-office365-filtering-correlation-id: cbd9b9d0-33be-4ccc-3331-08dbb075a053 x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: UHZrSg2V3w40xO12fJ+xh3Mu8lOMbtwoJzDTaSBBmcAIuD1w0LJOzF2u5cB3wyvh236ycQpEegJUdiffk2al3P0sfe32HzpbRdYRrHowKjnyosEJll3MC8WZo8fRJJOh1RP6j3hkv/Euj9nDjOyz39S6hfBotnBHZFR3heZ+KeGngjY+tKczX4GUxpswCry6kF3WHoJ4fo5PjR11KdSmFlCMGxftMI2iLFm1ZDFRiKg/qST3prx9F7R0tT0XSwI9YUyL+zKWcNDCEtDuB9g4LsB5TseP1mg3Q8urnJYoFc1CK7S9EihIzwO0GMZMvbgISXlJKWd8+2+unP75oYC115tNxAW5IK7srvmvPTQATrDc8k887fRrrlZl/o/xPztzfVef9GK4uWYVPwqxl6bElZBsTsTjEQPAMHIY7Jv0nJIWsS5WdZ0Vq6iPsJFvMVCp5reNQiKT9m1JeWWMWlpPdx2Q9N9xUYk+VOY9i+Objdy4NYcxkoPb3ovXICvIWLOQHTS2EZnSOcx5HpgKzJcv4atgtAb3y4uM/ywidaC4MZ3+506ziR7gOTRjeHuvCcjeAAtUeZyLW3jq4w7TIm1l0zhUlV2c/FBOuVGqr8EPn5PrwH//Ot9ejQocl6T8MLKx6N+IrefwDDYvq0d3XKBpSA== 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)(39860400002)(396003)(376002)(366004)(136003)(186009)(451199024)(1800799009)(8676002)(5660300002)(4326008)(8936002)(41300700001)(30864003)(76116006)(66446008)(66946007)(54906003)(64756008)(66476007)(66556008)(44832011)(84970400001)(316002)(91956017)(110136005)(2906002)(122000001)(38070700005)(38100700002)(83380400001)(53546011)(33656002)(2616005)(26005)(86362001)(6512007)(71200400001)(478600001)(6486002)(36756003)(6506007)(45980500001)(579004);DIR:OUT;SFP:1101; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?E/fy/3JMvPqeY/NW5eZhNh3svNROUG5g00C+Dk3Bx/otzzwYUWbQgdW+ymVW?= =?us-ascii?Q?cPqwGx8KWrzNP9R1VIWAJHlVErDYuAGBDHaTN9e2qXhjUJ4APDYtLCvLSqJh?= =?us-ascii?Q?9W5l2NBC/QSdimwAynkCCKdseq8ppH3rMo2Kk+F4zjAcHe/jdM5Z/x/McCfo?= =?us-ascii?Q?rL00kdyOQMPFkoMssOE5oZbM3tYkfwXeeYP3Qx668LWIRRlWnTtzvmBwsQih?= =?us-ascii?Q?7xeqoyS3o3FfqPwCwDOEN4G8Xw/IG/abJ9cxDxHBVhKA2gTPBujpxkqxV3kW?= =?us-ascii?Q?TNemjKitOrj8zF2CZiAfswl25XWqkipkKEve94vQNFv3yXTy6IX8qDKAE6xB?= =?us-ascii?Q?MS7QXBKtccF4syh36MvDqy/4HDcgQDDSO2nxr3pOy9FfrYiA3wSw1ZGeQ4ZW?= =?us-ascii?Q?sVZy2qsBhzm9KYZyZCnBngMWl2QBtezET9oaknCpGCt4Ij8CuMi/0dYXnlzW?= =?us-ascii?Q?+TP5kQQFBucI3qBBYj+vHP0O99jEeLQ4MXspAaTDgUFseGvEDPiZc0EBmkVU?= =?us-ascii?Q?CE43hmrFOFW6c4RvsNSw2t+kal3lQAUedCq5HRZJvlMZy56eKM8jC1pWyaV+?= =?us-ascii?Q?zPHI1chyCulkgfzg4ZuDLmnn5CYseuFVXI8hxBZyN1BsGC/9GqmiZrhD0jbs?= =?us-ascii?Q?iPgfXdFCt3p5nhHwF9bG6W3Q+GweQS7TEjidaJl1y7+xD+sOe03thhBAk7bK?= =?us-ascii?Q?gJ5ywdUjgWIep3t50gRLRjE5SJbYjxwhvFZ2ZkVNebTYBF/FOgpTM2G9stNp?= =?us-ascii?Q?TcXccggiPxydMQy5iUiZ3bjCEIQpPLlBc2UcHXabSDcNk4ZGa31KE194XQrn?= =?us-ascii?Q?PZ7ww0ed3OkeabYQfLdUCOg0NYJEfGWk7TCxGeSdJ96JRIhRPK/2K33I2xXD?= =?us-ascii?Q?VsjJkpfJ3tDejj7z6hu+ckDErZtZ8juKKfhnSHj9PDLn/qNCKj5CQvXvYSJU?= =?us-ascii?Q?yw3TwhXtFgennB1vFv7hTR6ftDW34XP974hhktF5byhTceTIgnNCyRSaW/UP?= =?us-ascii?Q?QHsOGNWV+xsZiXsVllNcmSSDU+CQoeBRdHbXdbhyBwLtD9jE6jWP5G3cb4oj?= =?us-ascii?Q?x46upiEiC5cO4jqsS5qhIY1XY4FPXx/d+UoHys145pfIrZWnDD838xhICAO8?= =?us-ascii?Q?2Szg3uE46GlahwNBV+FlsjUpbASiZAxW9//Ddz4pBxVQZ0B/GOa4bRPvF5rU?= =?us-ascii?Q?6IPN4u5mJQSgc/KX168g1D2/EzW3fQ1kqOjdYCy0atq1CI7oJvjTP5dNQ+XT?= =?us-ascii?Q?pbpjPhUqBMiakwl2Y/bn67wc76iJsKy7Un56TQAzRSznEMqZ5vt6oVLCxJcY?= =?us-ascii?Q?qQKecVAl3xYbzuIUqSWCzBczf/zuIFYws7/e3jkq5TCbWgVxr40TnCFldGAf?= =?us-ascii?Q?eK9LenNg+sq9IBstWIl8AbUaCX8UtHFhHNzK/OcdOz35IJ8gsoidYKgKHOGq?= =?us-ascii?Q?1AFsA8pk28+cqud9jFKx7janQgSzGjOWt3IB4fWiqvCj6093xgUQeW9rYKb6?= =?us-ascii?Q?MH9Fird8rQl+e37m11TnYimoePu7VEOv0CPlyUvkysIXorO55aQ1qibkqJKF?= =?us-ascii?Q?CDwmWpD7Wi//wHZA+39FjAGHl9+6UuJR5TGDRV5S?= Content-Type: text/plain; charset="us-ascii" Content-ID: Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: =?us-ascii?Q?F0xvPKqLwN3fOfSrv1jd7hrK5R/ZiXHEEHyjbIrqiLlcy6UcJerzyND4lIz6?= =?us-ascii?Q?lSwztZlP/xZ5bPpnHurUfCaecNYH/5QM63wg+kTgHZwoHKTQY/OlNJpshCxm?= =?us-ascii?Q?YGKblRclHnsRo594HyJSRnwCGP3zq64l+8vT8jZDXL/pmhqsSVwbfFM00/KY?= =?us-ascii?Q?jqt0/hDDGMXjDPfYSQl2f6c7YPjjoBO+XQ3aMqJJTCx8isUCsRehXQFpdX+W?= =?us-ascii?Q?kmxjxSOgCpDV8xukGOz7Gt18gtTFfEX5fTyce9IysCEfgjftX9s0v/X2W67P?= =?us-ascii?Q?LCs0na8I4Wgg0KIJy1IWJtuio71FicKTo/1XLrwEvylpPGzonQ41PJrUm62G?= =?us-ascii?Q?nNMf5iNOpymA3EBlmw2cv+bvq6Ba3jAYgj0r0D+vf0SegEmjo5Ig+zt6v7mZ?= =?us-ascii?Q?I88vNbzYXPJLC7seXq4+v+PDPXEZqAX502ZrBEWH590Y55uMbfHWkYErqzcm?= =?us-ascii?Q?8r0KILywr+iqNwHCiLnFYkNBoieJ5KxYBx/hC65+Tcwpoot0qlMJ7T7741m5?= =?us-ascii?Q?zh+d89UfTVK3pGEAROmEPg9O4hpE5FexkMlDEaqxUd/yFGEbCGmxpbQ2Sg8M?= =?us-ascii?Q?VH4amHHREu2B7fpPhvSvET4xPwMROfuRQ3znv1YzmLJtGK89FqjkPblenpxT?= =?us-ascii?Q?FDOnBX7+RAPW7LzeaylNA3Vl0NVU6l9iXNMF64r8X1h96hKI3g9FK4ZzyLXq?= =?us-ascii?Q?dyCUpWTFpFE4ABafmS8pQDG0Ptk3Lm9GLl9n8yeUfOsajiokv0J4cUtvRDrN?= =?us-ascii?Q?Z8vymhqhZB0ezuVs3r360Moa+RwuIV349Xoidn9i8Xl1Ajz/KlHJkd2QEq3r?= =?us-ascii?Q?oXeoeVcES/dkKLjC0CFqmDftfHgXN0yEqTkfJR6/PSYm4TgzMpcmwPSeoruA?= =?us-ascii?Q?zQClTZ26300wtB9aL3Yp+7UWmDO+cUG7j/xBl+RLA54vOKQ4ERWXYil8ucoA?= X-OriginatorOrg: oracle.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: CH2PR10MB4344.namprd10.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: cbd9b9d0-33be-4ccc-3331-08dbb075a053 X-MS-Exchange-CrossTenant-originalarrivaltime: 08 Sep 2023 14:12:25.0016 (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: TLePvKY9UlW0rcoaF86FGVRAlnb40E3JZn+xhOYaT/MkazAJNp8WSFSgagSpRXcmhGHPImQ5yvNcs6erJoTggg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN0PR10MB5189 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-09-08_10,2023-09-05_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 spamscore=0 mlxlogscore=999 adultscore=0 phishscore=0 bulkscore=0 mlxscore=0 suspectscore=0 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2308100000 definitions=main-2309080131 X-Proofpoint-GUID: J9GGl4gEueNBQhZiQ6shbeJaWub5JwHi X-Proofpoint-ORIG-GUID: J9GGl4gEueNBQhZiQ6shbeJaWub5JwHi 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 List-Id: PIng. thanks. Qing > On Aug 25, 2023, at 11:24 AM, Qing Zhao wrote: >=20 > Provide a new counted_by attribute to flexible array member field. >=20 > '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'. >=20 > For instance, the following code: >=20 > struct P { > size_t count; > char other; > char array[] __attribute__ ((counted_by (count))); > } *p; >=20 > specifies that the 'array' is a flexible array member whose number > of elements is given by the field 'count' in the same structure. >=20 > 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. >=20 > 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. >=20 > #define SIZE_BUMP 10 > struct P *sbuf; > void alloc_buf (size_t nelems) > { > sbuf =3D (struct P *) malloc (MAX (sizeof (struct P), > (offsetof (struct P, array[0]) > + nelems * sizeof (char)))); > sbuf->count =3D nelems + SIZE_BUMP; > /* This is invalid when the sbuf->array has less than sbuf->co= unt > elements. */ > } >=20 > 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. >=20 > #define SIZE_BUMP 10 > struct P *sbuf; > void alloc_buf (size_t nelems) > { > sbuf =3D (struct P *) malloc (MAX (sizeof (struct P), > (offsetof (struct P, array[0]) > + (nelems + SIZE_BUMP) * sizeo= f (char)))); > sbuf->count =3D nelems; > /* This is valid when the sbuf->array has at least sbuf->count > elements. */ > } > void use_buf (int index) > { > sbuf->count =3D sbuf->count + SIZE_BUMP + 1; > /* Now the value of sbuf->count is larger than the number > of elements of sbuf->array. */ > sbuf->array[index] =3D 0; > /* then the out-of-bound access to this array > might not be detected. */ > } >=20 > gcc/c-family/ChangeLog: >=20 > 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. >=20 > gcc/c/ChangeLog: >=20 > 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. >=20 > gcc/ChangeLog: >=20 > PR C/108896 > * doc/extend.texi: Document attribute counted_by. > * tree.cc (get_named_field): New function. > * tree.h (get_named_field): New prototype. >=20 > gcc/testsuite/ChangeLog: >=20 > 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 >=20 > 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 (tre= e *, 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[= ] =3D > 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, tr= ee name, > return NULL_TREE; > } >=20 > +/* 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 =3D *node; > + tree argval =3D TREE_VALUE (args); > + > + /* This attribute only applies to field decls of a structure. */ > + if (TREE_CODE (decl) !=3D 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 =3D true; > + } > + /* This attribute only applies to field with array type. */ > + else if (TREE_CODE (TREE_TYPE (decl)) !=3D ARRAY_TYPE) > + { > + error_at (DECL_SOURCE_LOCATION (decl), > + "%qE attribute may not be specified for a non-array field", > + name); > + *no_add_attrs =3D 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 =3D true; > + } > + /* The argument should be an identifier. */ > + else if (TREE_CODE (argval) !=3D IDENTIFIER_NODE) > + { > + error_at (DECL_SOURCE_LOCATION (decl), > + "% argument not an identifier"); > + *no_add_attrs =3D true; > + } > + > + return NULL_TREE; > +} > + > /* Handle a "weak" attribute; arguments as in > struct attribute_spec.handler. */ >=20 > 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); > } >=20 > +/* 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) =3D=3D ARRAY_TYPE > + && TYPE_SIZE (type) =3D=3D NULL_TREE > + && TYPE_DOMAIN (type) !=3D NULL_TREE > + && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) =3D=3D NULL_TREE) > + return true; > + > + return false; > +} > + > /* Get the LEVEL of the strict_flex_array for the ARRAY_FIELD based on th= e > 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); >=20 > 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 *d= ecl, > return decl; > } >=20 > -/* 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) =3D=3D ARRAY_TYPE > - && TYPE_SIZE (type) =3D=3D NULL_TREE > - && TYPE_DOMAIN (type) !=3D NULL_TREE > - && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) =3D=3D 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 in= it) >=20 > elt =3D CONSTRUCTOR_ELTS (init)->last ().value; > type =3D 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, >=20 > bool is_zero_length_array =3D zero_length_array_type_p (TREE_TYPE (x)); > bool is_one_element_array =3D one_element_array_type_p (TREE_TYPE (x)); > - bool is_flexible_array =3D flexible_array_member_type_p (TREE_TYPE (x)= ); > + bool is_flexible_array =3D c_flexible_array_member_type_p (TREE_TYPE (= x)); >=20 > unsigned int strict_flex_array_level =3D c_strict_flex_array_level_of (= x); >=20 > @@ -9124,6 +9111,61 @@ is_flexible_array_member_p (bool is_last_field, > return false; > } >=20 > +/* Verify the argument of the counted_by attribute of the flexible array > + member FIELD_DECL is a valid field of the containing structure's fiel= dlist, > + 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 =3D 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 > + =3D 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 =3D 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) > + =3D 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 =3D TREE_CHAIN (counted_by_field); > + tree real_field =3D TREE_VALUE (counted_by_field); > + > + if (TREE_CODE (TREE_TYPE (real_field)) !=3D 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) > + =3D remove_attribute ("counted_by", DECL_ATTRIBUTES (field_decl)); > + } > + } > + > + return; > +} >=20 > /* 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 fieldli= st, tree attributes, > DECL_PACKED (x) =3D 1; >=20 > /* 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) =3D=3D UNION_TYPE) > { > @@ -9265,6 +9307,9 @@ finish_struct (location_t loc, tree t, tree fieldli= st, tree attributes, > "members"); > TREE_TYPE (x) =3D error_mark_node; > } > + /* if there is a counted_by attribute attached to this field, > + verify it. */ > + verify_counted_by_attribute (fieldlist, x); > } >=20 > if (pedantic && TREE_CODE (t) =3D=3D RECORD_TYPE > @@ -9279,7 +9324,7 @@ finish_struct (location_t loc, tree t, tree fieldli= st, tree attributes, > when x is an array and is the last field. */ > if (TREE_CODE (TREE_TYPE (x)) =3D=3D ARRAY_TYPE) > TYPE_INCLUDES_FLEXARRAY (t) > - =3D is_last_field && flexible_array_member_type_p (TREE_TYPE (x)); > + =3D 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. >=20 > +@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 inte= ger > +type. An explicit @code{counted_by} annotation defines a relationship b= etween > +two objects, @code{p->array} and @code{p->count}, that @code{p->array} h= as > +@emph{at least} @code{p->count} number of elements available. This rela= tionship > +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 ele= ments > +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 =3D (struct P *) malloc (MAX (sizeof (struct P), > + (offsetof (struct P, array[0]) > + + nelems * sizeof (char)))); > + sbuf->count =3D 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 =3D (struct P *) malloc (MAX (sizeof (struct P), > + (offsetof (struct P, array[0]) > + + (nelems + SIZE_BUMP) * sizeof (char)))); > + sbuf->count =3D nelems; > + /* This is valid when the sbuf->array has at least sbuf->count > + elements. */ > +@} > +void use_buf (int index) > +@{ > + sbuf->count =3D sbuf->count + SIZE_BUMP + 1; > + /* Now the value of sbuf->count is larger than the number > + of elements of sbuf->array. */ > + sbuf->array[index] =3D 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. */ =20 > +/* { dg-do compile } */ > +/* { dg-options "-O2" } */ > + > +#include > + > +int size; > +int x __attribute ((counted_by (size))); /* { dg-error "attribute may no= t 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 "attr= ibute 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 "arg= ument not an identifier" } */ > +}; > + > +struct trailing_array_3 { > + int other; > + int array_3[] __attribute ((counted_by (L"count"))); /* { dg-error "ar= gument not an identifier" } */ > +}; > + > +struct trailing_array_4 { > + int other; > + int array_4[] __attribute ((counted_by (count))); /* { dg-error "attri= bute 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 "attri= bute 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), ex= p); > } >=20 > +/* Given a field list, FIELDLIST, of a structure/union, return a TREE_LI= ST, > + with each TREE_VALUE a FIELD_DECL stepping down the chain to the FIEL= D > + 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 o= f > + length one, but if the field is embedded with (nested) anonymous stru= ctures > + or unions, this list steps down the chain to the field. */ > +tree > +get_named_field (tree fieldlist, const char *fieldname) > +{ > + tree named_field =3D NULL_TREE; > + for (tree field =3D fieldlist; field; field =3D DECL_CHAIN (field)) > + { > + if (TREE_CODE (field) !=3D FIELD_DECL) > + continue; > + if (DECL_NAME (field) !=3D NULL) > + if (strcmp (IDENTIFIER_POINTER (DECL_NAME (field)), fieldname) =3D=3D 0= ) > + { > + named_field =3D tree_cons (NULL_TREE, field, named_field); > + break; > + } > + else > + continue; > + /* if the field is an anonymous struct/union, we will check the ne= sted > + fields inside it recursively. */ > + else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))) > + if ((named_field =3D get_named_field (TYPE_FIELDS (TREE_TYPE (field))= , > + fieldname)) !=3D NULL_TREE) > + { > + named_field =3D 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. */ >=20 > 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); >=20 > +/* 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 *); >=20 > --=20 > 2.31.1 >=20