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

            Bug ID: 77608
           Summary: missing protection on trivially detectable runtime
                    buffer overflow
           Product: gcc
           Version: 7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: msebor at gcc dot gnu.org
  Target Milestone: ---

The __builtin_object_size function is documented to return the size of the
smallest or largest, respectively, object referenced by its first argument,
ptr,  depending on its second argument.  When the size of the object ptr points
to is known at compile time but ptr is the result of pointer arithmetic such
the addition expression where the integer operand is not known,
__builtin_object_size fails instead of returning the (maximum or minimum) size
of the object.  This failure in turn disables the protection even in otherwise
obvious cases of buffer overflow.

For example, the call to memcpy in the following program clearly overflows the
destination buffer regardless of the value of i, yet because of the
__builtin_object_size failure, GCC fails to instrument the call and the
overflow is allowed to go undetected.

$ cat x.c && /build/gcc-trunk-git/gcc/xgcc -B /build/gcc-trunk-git/gcc -O2
-Wall -Wextra -Wpedantic -fdump-tree-optimized=/dev/stdout x.c && ./a.out
#define bos(dest) __builtin_object_size (dest, 0)
#define memcpy(dest, src, n)                            \
  __builtin___memcpy_chk (dest, src, n, bos (dest))

#define P(x) \
    __builtin_printf ("%2zd %2zd %2zd %2zd\n", \
                      __builtin_object_size (x, 0), \
                      __builtin_object_size (x, 1), \
                      __builtin_object_size (x, 2), \
                      __builtin_object_size (x, 3)) \

volatile unsigned i;

int main (void)
{
  {
    char d [3];

    P (d + i);

    memcpy (d + i, "abcdef", 5);

    __builtin_printf ("%.0s", d);
  }
}

;; Function main (main, funcdef_no=0, decl_uid=1792, cgraph_uid=0,
symbol_order=1) (executed once)

main ()
{
  char d[3];
  unsigned int i.0_1;
  sizetype _2;
  void * _3;

  <bb 2>:
  __builtin_printf ("%2zd %2zd %2zd %2zd\n", 18446744073709551615,
18446744073709551615, 0, 0);
  i.0_1 ={v} i;
  _2 = (sizetype) i.0_1;
  _3 = &d + _2;
  __builtin_memcpy (_3, "abcdef", 5);
  __builtin_printf ("%.0s", &d);
  d ={v} {CLOBBER};
  return 0;

}


-1 -1  0  0

Reply via email to