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

            Bug ID: 92334
           Summary: incorrect __builtin_object_size result for negative
                    offsets
           Product: gcc
           Version: 10.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 pointer argument to __builtin_object_size() is at a negative offset
from the beginning of an object the function seems to return the sum of the
absolute value of the offset and the size of the object rather than zero, thus
defeating the _FORTIFY_SOURCE protection against out of bounds writes.  The
-Warray-bounds and -Wstringop-overflow warnings do detect some of these bugs.

$ cat z.c && gcc -O2 -S -Wall -fdump-tree-strlen=/dev/stdout z.c
void sink (void*);

void f (const void *p)
{
  int i = -7;

  char a[3];
  char *q = a + i;

  __builtin___memcpy_chk (q, p, 10, __builtin_object_size (p, 1));

  sink (a);
}

void g (const void *p)
{
  int i = -7;

  char a[3];
  char *q = a + i;

  __builtin___memcpy_chk (q, p, 13, __builtin_object_size (p, 1));

  sink (a);
}

z.c: In function ‘f’:
z.c:8:9: warning: array subscript -7 is outside array bounds of ‘char[3]’
[-Warray-bounds]
    8 |   char *q = a + i;
      |         ^
z.c:7:8: note: while referencing ‘a’
    7 |   char a[3];
      |        ^

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

;; 1 loops found
;;
;; Loop 0
;;  header 0, latch 1
;;  depth 0, outer -1
;;  nodes: 0 1 2
;; 2 succs { 1 }
f (const void * p)
{
  char a[3];

  <bb 2> [local count: 1073741824]:
  __builtin_memcpy (&MEM <char[3]> [(void *)&a + -7B], p_3(D), 10);
  sink (&a);
  a ={v} {CLOBBER};
  return;

}


z.c: In function ‘g’:
z.c:20:9: warning: array subscript -7 is outside array bounds of ‘char[3]’
[-Warray-bounds]
   20 |   char *q = a + i;
      |         ^
z.c:19:8: note: while referencing ‘a’
   19 |   char a[3];
      |        ^

;; Function g (g, funcdef_no=1, decl_uid=1938, cgraph_uid=2, symbol_order=1)

;; 1 loops found
;;
;; Loop 0
;;  header 0, latch 1
;;  depth 0, outer -1
;;  nodes: 0 1 2
;; 2 succs { 1 }
g (const void * p)
{
  char a[3];

  <bb 2> [local count: 1073741824]:
  __builtin_memcpy (&MEM <char[3]> [(void *)&a + -7B], p_3(D), 13);
  sink (&a);
  a ={v} {CLOBBER};
  return;

}


z.c:22:3: warning: ‘__builtin_memcpy’ writing 13 bytes into a region of size 10
overflows the destination [-Wstringop-overflow=]
   22 |   __builtin___memcpy_chk (q, p, 13, __builtin_object_size (p, 1));
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Reply via email to