https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89748
Bug ID: 89748 Summary: missing _FORTIFY_SOURCE protection due to stpcpy folding Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gcc dot gnu.org Target Milestone: --- When _FORTIFY_SOURCE is defined GCC instruments the string concatenation in g() against buffer overflow as expected. But as a result of folding chained stpcpy calls to memcpy, GCC fails to do the same instrumentation in the equivalent (but more efficient) code in h(). The buffer overflow is only detected "by accident" by the -Warray-bounds warning in gimple-ssa-warn-restrict.c. $ cat t.c && gcc -D_FORTIFY_SOURCE=2 -O2 -S -Wall -fdump-tree-lower=/dev/stdout t.c #include <string.h> void f (void*); void g (void) { char a[8]; strcat (strcpy (a, "12345678"), "abcdefgh"); f (a); } void h (void) { char a[8]; stpcpy (stpcpy (a, "12345678"), "abcdefgh"); f (a); } ;; Function g (g, funcdef_no=11, decl_uid=2153, cgraph_uid=12, symbol_order=11) g () { char a[8]; try { _1 = strcpy (&a, "12345678"); strcat (_1, "abcdefgh"); f (&a); } finally { a = {CLOBBER}; } return; } ;; Function strcpy (<unset-asm-name>, funcdef_no=6, decl_uid=887, cgraph_uid=7, symbol_order=6) __attribute__((artificial, gnu_inline, always_inline, leaf, nothrow)) strcpy (char * restrict __dest, const char * restrict __src) { char * D.2161; _1 = __builtin_object_size (__dest, 1); D.2161 = __builtin___strcpy_chk (__dest, __src, _1); goto <D.2162>; <D.2162>: return D.2161; } ;; Function strcat (<unset-asm-name>, funcdef_no=9, decl_uid=881, cgraph_uid=10, symbol_order=9) __attribute__((artificial, gnu_inline, always_inline, leaf, nothrow)) strcat (char * restrict __dest, const char * restrict __src) { char * D.2163; _1 = __builtin_object_size (__dest, 1); D.2163 = __builtin___strcat_chk (__dest, __src, _1); goto <D.2164>; <D.2164>: return D.2163; } ;; Function h (h, funcdef_no=12, decl_uid=2157, cgraph_uid=13, symbol_order=12) h () { char a[8]; try { __builtin_memcpy (&a, "12345678", 9); _1 = &a + 8; __builtin_memcpy (_1, "abcdefgh", 9); f (&a); } finally { a = {CLOBBER}; } return; } In file included from /usr/include/string.h:494, from t.c:1: In function ‘strcpy’, inlined from ‘g’ at t.c:7:3: /usr/include/bits/string_fortified.h:90:10: warning: ‘__builtin___memcpy_chk’ forming offset 9 is out of the bounds [0, 8] of object ‘a’ with type ‘char[8]’ [-Warray-bounds] 90 | return __builtin___strcpy_chk (__dest, __src, __bos (__dest)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ t.c: In function ‘g’: t.c:6:8: note: ‘a’ declared here 6 | char a[8]; | ^ In file included from /usr/include/string.h:494, from t.c:1: In function ‘strcat’, inlined from ‘g’ at t.c:7:3: /usr/include/bits/string_fortified.h:128:10: warning: ‘__builtin___memcpy_chk’ writing 9 bytes into a region of size 0 overflows the destination [-Wstringop-overflow=] 128 | return __builtin___strcat_chk (__dest, __src, __bos (__dest)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ t.c: In function ‘h’: cc1: warning: ‘__builtin_memcpy’ forming offset 9 is out of the bounds [0, 8] of object ‘a’ with type ‘char[8]’ [-Warray-bounds] t.c:13:8: note: ‘a’ declared here 13 | char a[8]; | ^ t.c:14:3: warning: ‘__builtin_memcpy’ forming offset [9, 17] is out of the bounds [0, 8] of object ‘a’ with type ‘char[8]’ [-Warray-bounds] 14 | stpcpy (stpcpy (a, "12345678"), "abcdefgh"); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ t.c:13:8: note: ‘a’ declared here 13 | char a[8]; | ^