From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 065E9384D3EA; Fri, 9 Dec 2022 17:24:18 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 065E9384D3EA DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1670606658; bh=ahM7BXZwMsNHzBdwKTvQoK5ljblxBmT0jw2NyBYBiDs=; h=From:To:Subject:Date:From; b=lIhQMDjLuNVhWX0fGbxQHOipI40fZXhl0HzhhvmGoVzwLT/jubZBNfwqQ4KxASluc XoE0iuiSNGLWNNtnXjAMZqGWm5i1Q2qy9wp5b7TPvvhXBOElumSPj/4Iw9SMej2TlL fgedJw3c/BKxhGpmKEyBIMkrwksCQ9tryAtDi5II= From: "colomar.6.4.3 at gmail dot com" To: gcc-bugs@gcc.gnu.org Subject: [Bug c/108036] New: Spurious warning for zero-sized array parameters to a function Date: Fri, 09 Dec 2022 17:24:17 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c X-Bugzilla-Version: 12.2.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: colomar.6.4.3 at gmail dot com X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter target_milestone Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 List-Id: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D108036 Bug ID: 108036 Summary: Spurious warning for zero-sized array parameters to a function Product: gcc Version: 12.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: colomar.6.4.3 at gmail dot com Target Milestone: --- It's interesting to pass pointers to one past the end of an array to a function, acting as a sentinel value that serves as an alternative to the s= ize of the buffer. It helps chaining string copy functions, for example: char * ustr2stpe(char *dst, const char *restrict src, size_t n, char past_end[0]) { bool trunc; char *end; ptrdiff_t len; if (dst =3D=3D past_end) return past_end; trunc =3D false; len =3D strnlen(src, n); if (len > past_end - dst - 1) { len =3D past_end - dst - 1; trunc =3D true; } end =3D mempcpy(dst, src, len); *end =3D '\0'; return trunc ? past_end : end; } However, if you use array syntax for it, which clarifies where it points to, the GCC complains, not at the function implementation, but at call site: #define nitems(arr) (sizeof((arr)) / sizeof((arr)[0])) 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; 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"); puts(dest); // "pre.some-long-body" } $ 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 in= 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 in= a region of size 0 [-Wstringop-overflow=3D] 44 | p =3D ustr2stpe(p, src, strlen(src) - strlen(post), past_e= nd); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 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 in= 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 in= 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 in= a region of size 0 [-Wstringop-overflow=3D] 44 | p =3D ustr2stpe(p, src, strlen(src) - strlen(post), past_e= nd); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 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 in= 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]) | ^~~~~~~~~ The warnings are invalid. While it's true that I'm referencing a pointer of size 0, it's false that I'm "accessing 1 byte" in that region. I guess thi= s 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. See the original report in the mailing list, where Richard Biener had some guess of what might be the reason: =