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

            Bug ID: 87296
           Summary: -Wstringop-overflow false positive
           Product: gcc
           Version: 8.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: curlypaul924 at gmail dot com
  Target Milestone: ---

Tested on gcc 8.1 and 8.2 on Ubuntu 16.04, and also on gcc (trunk) on
gcc.godbolt.org.

The following code:

extern "C" char *strncpy(char *, const char *, unsigned long);

void fill(char const * begin, char const * end, char c);

struct q {
  char ids[4];
  char username[6];
};

q & get();

int main() {
  auto & c = get();

  fill(c.ids, c.ids + sizeof(c.ids), '\0');
  strncpy(c.username, "root", sizeof(c.username));
}

when compiled with g++ -O1 on x86-64, produces:

v.cpp: In function ‘int main()’:
v.cpp:16:10: warning: ‘char* strncpy(char*, const char*, long unsigned int)’
writing 6 bytes into a region of size 4 overflows the destination
[-Wstringop-overflow=]
   strncpy(c.username, "root", sizeof(c.username));
   ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

It seems that the compiler is confusing ids and username, somehow related to
passing c.ids + 4 to fill().

If I reduce the size of username to 5 bytes, the compiler generates MOV BYTE
instead of MOV DWORD for the null-padding, and there is no warning.

Reply via email to