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];
      |        ^

Reply via email to