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

            Bug ID: 92718
           Summary: Bogus Wstringop-overflow in __builtin_memset() of an
                    element of array of size 1 of struct
           Product: gcc
           Version: 8.3.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: rlibby at gmail dot com
  Target Milestone: ---

Created attachment 47392
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=47392&action=edit
Minimized test case

Gcc is emitting bogus, or maybe pessimistic, Wstringop-overflow or
Warray-bounds warnings (depending on warning flags).

$ cat min.c
struct s {
        int x;
};

extern int n;
struct s a[1];

void
f(void)
{
        struct s *ps;
        int i;

        for (i = 0; i < n; i++) {
                ps = &a[i];
                __builtin_memset(ps, 0, sizeof(*ps));
                ps->x = 1;
        }
}

$ /tmp/gcc/bin/bin/gcc -O -c min.c
min.c: In function ‘f’:
min.c:16:3: warning: ‘__builtin_memset’ writing 4 bytes into a region of size 0
overflows the destination [-Wstringop-overflow=]
   16 |   __builtin_memset(ps, 0, sizeof(*ps));
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

$ /tmp/gcc/bin/bin/gcc -Wall -O -c min.c
min.c: In function ‘f’:
min.c:16:3: warning: ‘__builtin_memset’ offset [4, 7] is out of the bounds [0,
4] of object ‘a’ with type ‘struct s[1]’ [-Warray-bounds]
   16 |   __builtin_memset(ps, 0, sizeof(*ps));
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
min.c:6:10: note: ‘a’ declared here
    6 | struct s a[1];
      |          ^

My unprofessional opinion is that it seems like the compiler is emitting
a warning for when i >= 1, but the compiler does not know whether that
is actually possible.  Note that a warning is not emitted if any of
these changes are made:
 - The size of array "a" is changed from 1 to 2.
 - A check of "n" against the array size is inserted:
        if (n > 1)
                return;
 - The assignment of "x" after __builtin_memset() is deleted.
 - The array of struct is changed to array of int.

The warning is emitted as -Wstringop-overflow with the default warning
options.  In latest source, with -Wall, the warning is emitted as
Warray-bounds, but in previous versions (I checked 8.3.0) -Wall emits
Wstringop-overflow.  I'm not sure when this aspect may have changed.

I have tested this case and seen a warning on:
 - gcc 7.4.0
 - gcc 8.3.0
 - gcc current sources (r278812, "10.0.0")

I looked through the bugs linked to bug 88443 and was not immediately
able to identify this as a duplicate of one.  Apologies if it is.

Reply via email to