https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91205
--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> --- _FORTIFY_SOURCE=1 checks for all covered functions just whether they don't overflow whole objects, while _FORTIFY_SOURCE=2 goes for a subset of functions (e.g. those str*/stp* but not mem*) further and requires that they don't cross structure field boundaries, say for struct S { char s[4]; char t[4]; } s; memcpy (s.s, "abcdefg", 8); // ok strcpy (s.s, "abcdefg"); // invalid The only valid field that can go beyond end of the structure is flexible array member, which is b in struct T { int a; char b[]; };, but GCC goes beyond that, and allows [0], or even [23] as the last array in the structure, and handles I believe even the union case you have in #c2, but it certainly isn't allowing e.g. to cross from element to element of a multi-dimensional array or your #c0 case.