public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/108036] New: Spurious warning for zero-sized array parameters to a function
@ 2022-12-09 17:24 colomar.6.4.3 at gmail dot com
  2022-12-09 19:09 ` [Bug c/108036] " pinskia at gcc dot gnu.org
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: colomar.6.4.3 at gmail dot com @ 2022-12-09 17:24 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108036

            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 size
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 == past_end)
                return past_end;

        trunc = false;
        len = strnlen(src, n);
        if (len > past_end - dst - 1) {
                len = past_end - dst - 1;
                trunc = true;
        }

        end = mempcpy(dst, src, len);
        *end = '\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] = "pre.";
        char *post = ".post";
        char *src = "some-long-body.post";
        char dest[100];
         char *p, *past_end;

        past_end = dest + nitems(dest);
        p = dest;
        p = ustr2stpe(p, pre, nitems(pre), past_end);
        p = ustr2stpe(p, src, strlen(src) - strlen(post), past_end);
        p = ustr2stpe(p, "", 0, past_end);
        if (p == past_end)
                fprintf(stderr, "truncation\n");

        puts(dest);  // "pre.some-long-body"
}

$ cc -Wall -Wextra ustr2stpe.c
ustr2stpe.c: In function ‘main’:
ustr2stpe.c:43:13: warning: ‘ustr2stpe’ accessing 1 byte in a region of size 0
[-Wstringop-overflow=]
    43 |         p = ustr2stpe(p, pre, nitems(pre), past_end);
       |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ustr2stpe.c:43:13: note: referencing argument 4 of type ‘char[0]’
ustr2stpe.c:10:1: note: in a call to function ‘ustr2stpe’
    10 | ustr2stpe(char *dst, const char *restrict src, size_t n, char
past_end[0])
       | ^~~~~~~~~
ustr2stpe.c:44:13: warning: ‘ustr2stpe’ accessing 1 byte in a region of size 0
[-Wstringop-overflow=]
    44 |         p = ustr2stpe(p, src, strlen(src) - strlen(post), past_end);
       |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ustr2stpe.c:44:13: note: referencing argument 4 of type ‘char[0]’
ustr2stpe.c:10:1: note: in a call to function ‘ustr2stpe’
    10 | ustr2stpe(char *dst, const char *restrict src, size_t n, char
past_end[0])
       | ^~~~~~~~~
ustr2stpe.c:45:13: warning: ‘ustr2stpe’ accessing 1 byte in a region of size 0
[-Wstringop-overflow=]
    45 |         p = ustr2stpe(p, "", 0, past_end);
       |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ustr2stpe.c:45:13: note: referencing argument 4 of type ‘char[0]’
ustr2stpe.c:10:1: note: in a call to function ‘ustr2stpe’
    10 | ustr2stpe(char *dst, const char *restrict src, size_t n, char
past_end[0])
       | ^~~~~~~~~
ustr2stpe.c:43:13: warning: ‘ustr2stpe’ accessing 1 byte in a region of size 0
[-Wstringop-overflow=]
    43 |         p = ustr2stpe(p, pre, nitems(pre), past_end);
       |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ustr2stpe.c:43:13: note: referencing argument 4 of type ‘char[0]’
ustr2stpe.c:10:1: note: in a call to function ‘ustr2stpe’
    10 | ustr2stpe(char *dst, const char *restrict src, size_t n, char
past_end[0])
       | ^~~~~~~~~
ustr2stpe.c:44:13: warning: ‘ustr2stpe’ accessing 1 byte in a region of size 0
[-Wstringop-overflow=]
    44 |         p = ustr2stpe(p, src, strlen(src) - strlen(post), past_end);
       |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ustr2stpe.c:44:13: note: referencing argument 4 of type ‘char[0]’
ustr2stpe.c:10:1: note: in a call to function ‘ustr2stpe’
    10 | ustr2stpe(char *dst, const char *restrict src, size_t n, char
past_end[0])
       | ^~~~~~~~~
ustr2stpe.c:45:13: warning: ‘ustr2stpe’ accessing 1 byte in a region of size 0
[-Wstringop-overflow=]
    45 |         p = ustr2stpe(p, "", 0, past_end);
       |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ustr2stpe.c:45:13: note: referencing argument 4 of type ‘char[0]’
ustr2stpe.c:10:1: note: in a call to function ‘ustr2stpe’
    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 this 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:
<https://gcc.gnu.org/pipermail/gcc/2022-December/240230.html>

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2024-03-07 10:53 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-09 17:24 [Bug c/108036] New: Spurious warning for zero-sized array parameters to a function colomar.6.4.3 at gmail dot com
2022-12-09 19:09 ` [Bug c/108036] " pinskia at gcc dot gnu.org
2022-12-09 19:13 ` [Bug middle-end/108036] [11/12/13 Regression] " pinskia at gcc dot gnu.org
2022-12-09 19:13 ` pinskia at gcc dot gnu.org
2022-12-09 19:18 ` colomar.6.4.3 at gmail dot com
2022-12-09 19:22 ` pinskia at gcc dot gnu.org
2022-12-09 19:23 ` colomar.6.4.3 at gmail dot com
2022-12-21 11:45 ` rguenth at gcc dot gnu.org
2023-05-29 10:07 ` [Bug middle-end/108036] [11/12/13/14 " jakub at gcc dot gnu.org
2024-03-07 10:18 ` daniel.lundin.mail at gmail dot com
2024-03-07 10:53 ` alx at kernel dot org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).