https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88780
Bug ID: 88780 Summary: Wstringop-truncation Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gcc dot gnu.org Target Milestone: --- In the test case below the assignment suppression logic where we look for the next statement to see if it assigns a nul to the destination is never entered, resulting in a false positive. I don't know/remember why it isn't used here, but using it doesn't seem that it would do the right thing here anyway: it would find the addition that computes pointer to use for the assignment: _3 = buf_8(D) + namelen_6; The logic isn't robust enough to track pointer arithmetic when looking for the assignment. To avoid the false positive the logic needs to be enhanced to track the destination across pointer arithmetic. $ cat u.c && gcc -O2 -S -Wall u.c typedef __SIZE_TYPE__ size_t; void f (char *d, const char *s, size_t n) { size_t len = __builtin_strlen (s); if (n < len + 1) return; __builtin_strncpy (d, s, len); d[len] = '\0'; } u.c: In function ‘f’: u.c:3:6: note: finish_function 3 | void f (char *d, const char *s, size_t n) | ^ u.c:8:3: warning: ‘__builtin_strncpy’ output truncated before terminating nul copying as many bytes from a string as its length [-Wstringop-truncation] 8 | __builtin_strncpy (d, s, len); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ u.c:5:16: note: length computed here 5 | size_t len = __builtin_strlen (s); | ^~~~~~~~~~~~~~~~~~~~ The test case was isolated from the following function: /* Extract the common name of 'cert' into 'buf'. */ static int get_common_name(CERTCertificate *cert, char *buf, size_t bufsiz) { /* FIXME --- truncating names with spaces */ size_t namelen; char *name = CERT_GetCommonName(&cert->subject); if (!name) return -1; namelen = strlen(name); if (bufsiz < namelen+1) return -1; strncpy(buf, name, namelen); buf[namelen] = '\0'; PORT_Free(name); return 0; } and the following warning during a Fedora build with GCC 9: In file included from /usr/include/string.h:494, from /usr/include/nss3/secport.h:45, from /usr/include/nss3/seccomon.h:27, from /usr/include/nss3/nss.h:34, from certwatch.c:77: In function 'strncpy', inlined from 'get_common_name' at certwatch.c:249:5, inlined from 'check_cert' at certwatch.c:289:9, inlined from 'main' at certwatch.c:387:12: /usr/include/bits/string_fortified.h:106:10: error: '__builtin___strncpy_chk' output truncated before terminating nul copying as many bytes from a string as its length [-Werror=stringop-truncation] 106 | return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ certwatch.c: In function 'main': certwatch.c:246:15: note: length computed here 246 | namelen = strlen(name); | ^~~~~~~~~~~~ cc1: all warnings being treated as errors