From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-il1-x12d.google.com (mail-il1-x12d.google.com [IPv6:2607:f8b0:4864:20::12d]) by sourceware.org (Postfix) with ESMTPS id 3008738540A8 for ; Fri, 9 Dec 2022 20:04:16 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 3008738540A8 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-il1-x12d.google.com with SMTP id x12so453638ilg.1 for ; Fri, 09 Dec 2022 12:04:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=to:references:message-id:date:cc:in-reply-to:from:mime-version :subject:content-transfer-encoding:from:to:cc:subject:date :message-id:reply-to; bh=Op7WeuqS23TGwpmI6cbS8fdtKVRXzEjJFEhbciPg04A=; b=MhxHyLcc10fkXjRJh8JS8ukyMbGO7iZ58zc+Oi1KSwVQzpV28P0mbQbMhUWzYaOw// oRkQpvumQJWwRJm09/TS5cId4Ll06+qZkRudYQcIX9XNrzcad9eOE6skRLsRKXOx0eVR /TcFt7XZYbJeIoWKmXGjWJHr8Ndcx3qe0cJvY5lBC1GkraMneJtvEUh89PUfESBZhzCC 0gHvi04KTBhSOYxilfc7+Z3H4umJ1psmBzDRa594LCgVXqvJc6cGZdVMnBMihexUAVH6 dHA4F0TLeRpKiwPfIk5MXLZuBogdNCM51RdAq26RGF+++qlt2lnPdi7RBbRSnzTFeNUD W+8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=to:references:message-id:date:cc:in-reply-to:from:mime-version :subject:content-transfer-encoding:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Op7WeuqS23TGwpmI6cbS8fdtKVRXzEjJFEhbciPg04A=; b=pgru6B6WehEoINSJKL4zbNkNBj7FrJInb+rpPqaNdVUz+Fb4WDe/gTaMW1TWZCxwsb MPJ61ib+uy0qgINJQgJRDgQJjsEVSjiKDaYZFohqGu/HtVOPOWH819Mx9TB4Y87U4+CF 2XX6I2uzBglPrCzaD1jAtzhxsB2DbqFsThGgmQEYBBzC0BBDHb7koZrcSu+j9OZZSx6c 2yi4pebtDYX3ovmeQgHU5xhApLKvURaKGWnUTYyYa7po6dCr0dTz186Qx/p1pcVOBn7i KzfcJNQ811wgSOxoWVGnB/DIkvJ1QAMX5X492IvYT13mCvqxizz2r+u7YIqgH8GvdWQB fb4w== X-Gm-Message-State: ANoB5pm5izxd/fg8M5laA0X+Brvs0UFzUwCu0i/k1LES9pQTVCadconk 3Zp5FQPmWArBVcxPLb05wcCGEY3/NXQ= X-Google-Smtp-Source: AA0mqf70eBYX8v19wsVwrmLFfQmk3kGmCThBaxLhRtRZoQKVyNE00UnNKFDLqnGlK9mpeZIhrfOcDA== X-Received: by 2002:a05:6e02:ee9:b0:303:3d01:7ca0 with SMTP id j9-20020a056e020ee900b003033d017ca0mr3900295ilk.28.1670616255113; Fri, 09 Dec 2022 12:04:15 -0800 (PST) Received: from smtpclient.apple (97-118-125-148.hlrn.qwest.net. [97.118.125.148]) by smtp.gmail.com with ESMTPSA id ce10-20020a0566381a8a00b003884192cc05sm723644jab.120.2022.12.09.12.04.14 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 09 Dec 2022 12:04:14 -0800 (PST) Content-Type: multipart/mixed; boundary=Apple-Mail-6AB3FA5D-2040-457E-A3BE-BFF95FDC498E Content-Transfer-Encoding: 7bit Subject: Re: Spurious warning for zero-sized array parameters to a function Mime-Version: 1.0 (1.0) X-Apple-Notify-Thread: NO X-Universally-Unique-Identifier: F8901362-4AA2-437E-902B-71632C6F91D8 From: msebor@gmail.com In-Reply-To: <55aaeff6-11ad-b7e5-1e81-bee6edc606e4@gmail.com> Cc: gcc@gcc.gnu.org Date: Fri, 9 Dec 2022 13:04:13 -0700 X-Apple-Message-Smime-Encrypt: NO Message-Id: References: <55aaeff6-11ad-b7e5-1e81-bee6edc606e4@gmail.com> To: Alejandro Colomar X-Mailer: iPad Mail (19H117) X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,KAM_ASCII_DIVIDERS,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: --Apple-Mail-6AB3FA5D-2040-457E-A3BE-BFF95FDC498E Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable > On Dec 6, 2022, at 9:22 AM, Alejandro Colomar via Gcc wr= ote: >=20 > =EF=BB=BFHi! >=20 > In the following function, past_end is a pointer to one-past-the-end of th= e array. Holding such a pointer is legal in C. I use it as a sentinel valu= e that helps (1) avoid overrunning the buffer, and (2) detect truncation. I= mark it as having a size of [0], which clearly states that it can't be dere= ferenced (and as you can see, I don't). >=20 > /* > * This function copies an unterminated string into a string. > * - It never overruns the dest buffer. > * - It can be chained, to concatenate strings. > * - It detects truncation. > * - Truncation only needs to be tested once after all concatenations. > * - The name is self-documenting, compared to its alternative: strncat(3)= . > */ > char * > ustr2stpe(char *dst, const char *restrict src, size_t n, char past_end[0])= > { > bool trunc; > char *end; > ptrdiff_t len; >=20 > if (dst =3D=3D past_end) > return past_end; >=20 > trunc =3D false; > len =3D strnlen(src, n); > if (len > past_end - dst - 1) { > len =3D past_end - dst - 1; > trunc =3D true; > } >=20 > end =3D mempcpy(dst, src, len); > *end =3D '\0'; >=20 > return trunc ? past_end : end; > } >=20 >=20 > If I compile the code above, GCC considers the function definition to be f= ine. However, at call site, it always warns: >=20 >=20 > #define nitems(arr) (sizeof((arr)) / sizeof((arr)[0])) >=20 > int > main(void) > { > char pre[4] =3D "pre."; > char *post =3D ".post"; > char *src =3D "some-long-body.post"; > char dest[100]; > char *p, *past_end; >=20 > past_end =3D dest + nitems(dest); > p =3D dest; > p =3D ustr2stpe(p, pre, nitems(pre), past_end); > p =3D ustr2stpe(p, src, strlen(src) - strlen(post), past_end); > p =3D ustr2stpe(p, "", 0, past_end); > if (p =3D=3D past_end) > fprintf(stderr, "truncation\n"); >=20 > puts(dest); // "pre.some-long-body" > } >=20 >=20 >=20 > $ cc -Wall -Wextra ustr2stpe.c > ustr2stpe.c: In function =E2=80=98main=E2=80=99: > ustr2stpe.c:43:13: warning: =E2=80=98ustr2stpe=E2=80=99 accessing 1 byte i= n a region of size 0 [-Wstringop-overflow=3D] > 43 | p =3D ustr2stpe(p, pre, nitems(pre), past_end); > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > ustr2stpe.c:43:13: note: referencing argument 4 of type =E2=80=98char[0]=E2= =80=99 > ustr2stpe.c:10:1: note: in a call to function =E2=80=98ustr2stpe=E2=80=99 > 10 | ustr2stpe(char *dst, const char *restrict src, size_t n, char past_= end[0]) > | ^~~~~~~~~ > ustr2stpe.c:44:13: warning: =E2=80=98ustr2stpe=E2=80=99 accessing 1 byte i= n a region of size 0 [-Wstringop-overflow=3D] > 44 | p =3D ustr2stpe(p, src, strlen(src) - strlen(post), past_en= d); > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~= > ustr2stpe.c:44:13: note: referencing argument 4 of type =E2=80=98char[0]=E2= =80=99 > ustr2stpe.c:10:1: note: in a call to function =E2=80=98ustr2stpe=E2=80=99 > 10 | ustr2stpe(char *dst, const char *restrict src, size_t n, char past_= end[0]) > | ^~~~~~~~~ > ustr2stpe.c:45:13: warning: =E2=80=98ustr2stpe=E2=80=99 accessing 1 byte i= n a region of size 0 [-Wstringop-overflow=3D] > 45 | p =3D ustr2stpe(p, "", 0, past_end); > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > ustr2stpe.c:45:13: note: referencing argument 4 of type =E2=80=98char[0]=E2= =80=99 > ustr2stpe.c:10:1: note: in a call to function =E2=80=98ustr2stpe=E2=80=99 > 10 | ustr2stpe(char *dst, const char *restrict src, size_t n, char past_= end[0]) > | ^~~~~~~~~ > ustr2stpe.c:43:13: warning: =E2=80=98ustr2stpe=E2=80=99 accessing 1 byte i= n a region of size 0 [-Wstringop-overflow=3D] > 43 | p =3D ustr2stpe(p, pre, nitems(pre), past_end); > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > ustr2stpe.c:43:13: note: referencing argument 4 of type =E2=80=98char[0]=E2= =80=99 > ustr2stpe.c:10:1: note: in a call to function =E2=80=98ustr2stpe=E2=80=99 > 10 | ustr2stpe(char *dst, const char *restrict src, size_t n, char past_= end[0]) > | ^~~~~~~~~ > ustr2stpe.c:44:13: warning: =E2=80=98ustr2stpe=E2=80=99 accessing 1 byte i= n a region of size 0 [-Wstringop-overflow=3D] > 44 | p =3D ustr2stpe(p, src, strlen(src) - strlen(post), past_en= d); > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~= > ustr2stpe.c:44:13: note: referencing argument 4 of type =E2=80=98char[0]=E2= =80=99 > ustr2stpe.c:10:1: note: in a call to function =E2=80=98ustr2stpe=E2=80=99 > 10 | ustr2stpe(char *dst, const char *restrict src, size_t n, char past_= end[0]) > | ^~~~~~~~~ > ustr2stpe.c:45:13: warning: =E2=80=98ustr2stpe=E2=80=99 accessing 1 byte i= n a region of size 0 [-Wstringop-overflow=3D] > 45 | p =3D ustr2stpe(p, "", 0, past_end); > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > ustr2stpe.c:45:13: note: referencing argument 4 of type =E2=80=98char[0]=E2= =80=99 > ustr2stpe.c:10:1: note: in a call to function =E2=80=98ustr2stpe=E2=80=99 > 10 | ustr2stpe(char *dst, const char *restrict src, size_t n, char past_= end[0]) > | ^~~~~~~~~ >=20 >=20 > The warnings are invalid. While it's true that I'm referencing a pointer o= f size 0, it's false that I'm "accessing 1 byte" in that region. I guess th= is is all about the bogus design of 'static' in ISO C, where you can have an= array parameter of size 0, which is very useful in cases like this one. Most of these warnings are designed to find simple mistakes in common use ca= ses so "tricky," unusual, or otherwise unexpected code is likely to lead to s= urprises. This warning expects that in calls to a function, every parameter= declared using the array syntax (which is expected to have a nonzero bound)= is passed a dereferenceable pointer as an argument. It considers neither t= he definition of the function to see if it does in fact dereference the argu= ment, nor this unlikely (and strictly invalid) use case. The warning should not be issued if the parameter is declared as an ordinary= pointer so I would suggest to use that instead. It's possible that declari= ng the array parameter with attribute access none might also suppress the wa= rning, but there is no utility in using a zero-length array in this context.= The intended purpose of the zero-length array GCC extension is as trailing= members of structs in legacy (pre-C99 code) that cannot use flexible array m= embers. Using them anywhere else is likely to be surprising, both to tools a= nd to readers, so the attribute on a pointer parameter would be preferable. Martin >=20 > Cheers, >=20 > Alex >=20 >=20 > --=20 > --Apple-Mail-6AB3FA5D-2040-457E-A3BE-BFF95FDC498E Content-Type: application/octet-stream; name=OpenPGP_signature; x-apple-part-url=618F874D-FC1F-4A84-BEED-27C8629BAEFE Content-Disposition: attachment; filename=OpenPGP_signature Content-Transfer-Encoding: 7bit -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEE6jqH8KTroDDkXfJAnowa+77/2zIFAmOPa2EACgkQnowa+77/ 2zLF6g/9HwjlNrqNgUaX44/834zxY19e53rVCZ7mY1WWXa+mYOWjXEpgic0gG0+e 2n6YjJGGbZNsQs5e8DNwnq+XG0sr4ZWzAQR2tiADXPx9khBGZaoD2NsTUk5Nm6S1 pFrVACkD9FXmOzPpm15m1/MyFA0TfR60NNlxJFP+tgB3Pc+MX521xY+7ekDfRJkf oNlvlbdq0DovkQSP5TJRu71CtP80WNZdbefj6fseaGjHJVNg/Dx76Y+uRE51p7Te ZJtvEILAu8h775sjtSxwNFM5IPeudA5FPJaP1BOffnhXFVO4ncVtiVJsre2CM+AZ lCFf9sYWX3KbYPFEwwmTIYCBDtuju4hZjrFvwvHywfgIKaiTMriBxnT3OCEVXI72 rZOZlvZpSwnf9EuKJ0UFdXgYwi8/OeB+wwh9+AfdkIuEQLZ8Qt/CJOcsnEaS5I1D nmi9xifcPSvF7FAb9Ugjkw44KRPttRwrGUSK2lK14/Al/z6yngf+UFmsPcYDV8pH NiJg2vwQ6Ovf75ua36afittM1fpj9Bwwefo1cQWbvHcbShMRjuu50Lq2ArWQFN1B 5FYoY5Cl3YR9AatITkPWEpb5l0A+Z4KK0kanmQVSIAiGyzc/bLivTOg0nvCb8HKj 5+RnCx7m4q+ATrwRX4qcho3E/YuT1FN/KYw+vCmn+F4fDzizqvM= =3WDu -----END PGP SIGNATURE----- --Apple-Mail-6AB3FA5D-2040-457E-A3BE-BFF95FDC498E--