https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71319
Bug ID: 71319 Summary: unnecessary call to __strcat_chk emitted after buffer reset Product: gcc Version: 7.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: --- Similar to bug 71304, in the following test case, since the string in the destination buffer is truncated at a known offset after it has been copied there by the checked call, the subsequent strcat call doesn't need to expand to a checked call because there is enough space in the buffer to append the source string to its contents. GCC performs this optimization in the first test case (function f) when the string a truncated by calling strcpy, but it doesn't do the same thing when the string is truncated by inserting a NUL into the same position. $ cat strcat.c && /home/msebor/build/gcc-6-branch/gcc/xgcc -B/home/msebor/build/gcc-6-branch/gcc -O2 -S -fdump-tree-optimized=/dev/stdout strcat.c #define strcat(d, s)\ __builtin___strcat_chk (d, s, __builtin_object_size (d, 0)) #define strcpy(d, s) \ __builtin___strcpy_chk (d, s, __builtin_object_size (d, 0)) void sink (const char*); int f (const char *s) { char a [4] = "1"; strcat (a, "2"); // safe strcat (a, s); // must be checked strcpy (a, "1"); strcat (a, "3"); // safe sink (a); } int g (const char *s) { char a [4] = "1"; strcat (a, "2"); // safe strcat (a, s); // must be checked a [1] = '\0'; strcat (a, "3"); // safe but checked (missing optimization) sink (a); } ;; Function f (f, funcdef_no=0, decl_uid=1758, cgraph_uid=0, symbol_order=0) f (const char * s) { char a[4]; <bb 2>: a = "1"; __builtin___strcpy_chk (&MEM[(void *)&a + 2B], s_4(D), 4); MEM[(char * {ref-all})&a] = 49; __builtin_memcpy (&MEM[(void *)&a + 1B], "3", 2); sink (&a); a ={v} {CLOBBER}; return; } ;; Function g (g, funcdef_no=1, decl_uid=1762, cgraph_uid=1, symbol_order=1) g (const char * s) { char a[4]; <bb 2>: a = "1"; __builtin___strcpy_chk (&MEM[(void *)&a + 2B], s_4(D), 4); a[1] = 0; __builtin___strcat_chk (&a, "3", 4); sink (&a); a ={v} {CLOBBER}; return; }