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