https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85484

            Bug ID: 85484
           Summary: missing -Wstringop-overflow for strcpy with a string
                    of non-const length
           Product: gcc
           Version: 8.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: ---

The buffer overflow reported in bug 85476 can be reduced to the test case
below.    The overflow is quite obvious and should be easy to detect at
compile-time via the -Wstringop-overflow warning yet GCC does not detect it,
either with or without -D_FORTIFY_SOURCE.  That's because __builtin_object_size
that -Wstringop-overflow relies on only deals with constant sizes.  But the
non-constant string length and allocation size are both readily available in
the tree-ssa-strlen pass and so the bug can easily be detected there.

$ cat x.c && gcc -O2 -S -Wall -Wextra -Wpedantic -fdump-tree-strlen=/dev/stdout
x.c
void f (char*);

void g (const char *s)
{
  unsigned n = __builtin_strlen (s);
  char *d = __builtin_alloca (n);   // off-by-one error (should be n + 1)
  __builtin_strcpy (d, s);          // missing -Wstringop-overflow
  f (d);
}

void h (const char *s)
{
  unsigned n = __builtin_strlen (s);
  char *d = __builtin_alloca (n);
  __builtin___strcpy_chk (d, s, __builtin_object_size (d, 1));
  f (d);
}


;; Function g (g, funcdef_no=0, decl_uid=1960, cgraph_uid=0, symbol_order=0)

g (const char * s)
{
  char * d;
  long unsigned int _1;
  long unsigned int _8;
  long unsigned int _10;

  <bb 2> [local count: 1073741825]:
  _1 = __builtin_strlen (s_3(D));
  _8 = _1 & 4294967295;
  d_5 = __builtin_alloca (_8);
  _10 = _1 + 1;
  __builtin_memcpy (d_5, s_3(D), _10);
  f (d_5);
  return;

}



;; Function h (h, funcdef_no=1, decl_uid=1965, cgraph_uid=1, symbol_order=1)

h (const char * s)
{
  char * d;
  long unsigned int _1;
  long unsigned int _2;
  long unsigned int _9;

  <bb 2> [local count: 1073741825]:
  _1 = __builtin_strlen (s_4(D));
  _9 = _1 & 4294967295;
  d_6 = __builtin_alloca (_9);
  _2 = _1 + 1;
  __builtin_memcpy (d_6, s_4(D), _2);
  f (d_6);
  return;

}

Reply via email to