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

            Bug ID: 77622
           Summary: __builtin_object_size incorrect for an out-of-bounds
                    pointer prior to destination object
           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: ---

When the __builtin_object_size intrinsic is passed a pointer that's derived
from the address of an object but points past its end it returns zero in all
types.  This makes it possible for _FORTIFY_SOURCE to detect writing past the
end of the destination buffer.

However, when the function is passed a similarly derived pointer that points
before the beginning of the object it instead returns a positive value,
preventing GCC from emitting the checking calls, and allowing buffer overflows
to go undetected.

The test case below shows these two cases.

$ 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)) \

int main (void)
{
  char d [3];
  int i = 10;
  char *p;

  {
    p = &d[3] - i;

    P (p);

    memcpy (p, "abcdef", 5);

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

  { 
    p = &d[3] + i;

    P (p);

    memcpy (p, "abcdef", 5);

    __builtin_printf ("%.0s", p);
  }
}
x.c: In function ‘main’:
x.c:19:7: warning: array subscript is below array bounds [-Warray-bounds]
     p = &d[3] - i;
     ~~^~~~~~~~~~~
x.c:19:7: warning: array subscript is below array bounds [-Warray-bounds]
x.c:29:7: warning: array subscript is above array bounds [-Warray-bounds]
     p = &d[3] + i;
     ~~^~~~~~~~~~~
x.c:29:7: warning: array subscript is above array bounds [-Warray-bounds]

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

main ()
{
  char d[3];

  <bb 2>:
  __builtin_printf ("%2zd %2zd %2zd %2zd\n", 10, 10, 10, 10);
  __builtin_memcpy (&MEM[(void *)&d + -7B], "abcdef", 5);
  __builtin_printf ("%.0s", &MEM[(void *)&d + -7B]);
  __builtin_printf ("%2zd %2zd %2zd %2zd\n", 0, 0, 0, 0);
  __builtin___memcpy_chk (&MEM[(void *)&d + 13B], "abcdef", 5, 0);
  __builtin_printf ("%.0s", &MEM[(void *)&d + 13B]);
  d ={v} {CLOBBER};
  return 0;

}


x.c:3:3: warning: call to __builtin___memcpy_chk will always overflow
destination buffer
   __builtin___memcpy_chk (dest, src, n, bos (dest))
   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
x.c:33:5: note: in expansion of macro ‘memcpy’
     memcpy (p, "abcdef", 5);
     ^~~~~~
10 10 10 10
 0  0  0  0
*** buffer overflow detected ***: ./a.out terminated

Reply via email to