https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85623
Bug ID: 85623 Summary: strncmp() warns about attribute 'nonstring' incorrectly in -Wstringop-overflow Product: gcc Version: 8.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: gandalf at winds dot org Target Milestone: --- The following code emits a warning when using strncmp() to compare a small quoted string with a "char data[4]" array declared __attribute__((nonstring)). The warning only appears if the quoted string is smaller than the size of the data[] array. My use of the data[] array is intended to act like a NUL-terminated string unless it is 4 bytes long, at which point it is non-NUL-terminated. This is the expected behavior when using strncpy() to fill (and truncate) arbitrary strings into a fixed-sized char[] array. I understand I can let GCC know of this intent by marking the array with __attribute__((nonstring)). My anticipated fix for GCC is that this warning should only appear with strcmp() and not strncmp(). extern char *strncpy (char *, const char *, long); extern int strncmp (const char *, const char *, long); extern __attribute__((nonstring)) char data[4]; void test(char *string) { if(strncmp(data, "??", sizeof(data))) strncpy(data, string, sizeof(data)); } # gcc -O3 test.c -c -Wall test.c: In function ‘test’: test.c:8:6: warning: ‘__builtin_strcmp’ argument 1 declared attribute ‘nonstring’ [-Wstringop-overflow=] if(strncmp(data, "??", sizeof(data))) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test.c:4:40: note: argument ‘data’ declared here Incidentally, changing the "??" to "????" or to a variable of type char* does not cause the warning. In my understanding, strncmp() is the correct function to use here because the size (3rd arg) does not overflow the length of data[4]. Nothing has overflowed here to warrant a stringop-overflow warning. I'm also unsure why the warning says '__builtin_strcmp' when strncmp() instead of strcmp() is being used. Removing the __attribute__((nonstring)) causes strncpy() to warn instead: extern char *strncpy (char *, const char *, long); extern int strncmp (const char *, const char *, long); extern char data[4]; void test(char *string) { if(strncmp(data, "??", sizeof(data))) strncpy(data, string, sizeof(data)); } # gcc -O3 test.c -c -Wall test.c: In function ‘test’: test.c:9:5: warning: ‘strncpy’ specified bound 4 equals destination size [-Wstringop-truncation] strncpy(data, string, sizeof(data)); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Conclusion: If GCC 8+ intends that we mark non-NUL-terminated strings with __attribute__((nonstring)) going forward, then there needs to be a way to cleanly use strncmp() to compare strings saved with strncpy() without any warnings.