--- Comment #3 from Martin Sebor <msebor at gcc dot> ---
There are actually yet another couple of bugs at play here.  In the test case
compiled without -D_FORTIFY_SOURCE, strcpy(buf, "hello ") is folded into a
MEM_REF by gimple_fold_builtin_strcpy() without checking to see if there's room
in the destination, so that's not diagnosed.

If the subsequent strcat() doesn't append more characters than would fit in the
destination if it were empty the strcat() also isn't diagnosed because it too
is folded, this time by gimple_fold_builtin_strcat() and into __builtin_memcpy.
 At the time it's folded the length of the string to which it's being appended
is not available.

When __builtin_memcpy() is handled in tree-ssa-strlen it should be able to warn
on the overflow because it should have access to the length of the destination
string and it knows the length of the source.  But strlen doesn't know how to
deal with MEM_REF (either due to bug 77357 or one of the other strlen missing
optimizations tracked under the meta bug 83819), and even if it did, 
handle_builtin_memcpy() in strlen doesn't do any overflow checking.

Finally, at the time the overflow checking is done during expansion in
builtins.c, although the length of the destination string that __builtin_memcpy
is being called to append to isn't accessible anymore, the memcpy destination
is &a + 4 which is too simple for compute_builtin_object_size() to handle (it
handles non-constant offsets but not the trivial constant case).  This works in
GCC 7 where the destination is &MEM[(void *)&a + 4B] that
compute_builtin_object_size() does know how to deal with.  Phew!

So with all these gaps the following isn't diagnosed in GCC 8 while it is
caught in GCC 7.

$ cat x.c && gcc -O2 -S -Wall -fdump-tree-optimized=/dev/stdout x.c
char a[4];

void f (void)
  __builtin_strcpy (a, "1234");
  __builtin_strcat (a, "567");

;; Function f (f, funcdef_no=0, decl_uid=1959, cgraph_uid=0, symbol_order=1)

f ()
  char[4] * _4;

  <bb 2> [local count: 1073741825]:
  MEM[(char * {ref-all})&a] = MEM[(char * {ref-all})"1234"];
  _4 = &a + 4;
  __builtin_memcpy (_4, "567", 4); [tail call]


Reply via email to