Mercurial > hg > CbC > CbC_gcc
diff gcc/testsuite/gcc.dg/builtin-stringop-chk-6.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gcc/testsuite/gcc.dg/builtin-stringop-chk-6.c Fri Oct 27 22:46:09 2017 +0900 @@ -0,0 +1,112 @@ +/* Test exercising -Wrawmem-overflow and -Wstringop-overflow warnings. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -Wstringop-overflow=2" } */ + +#define offsetof(type, mem) __builtin_offsetof (type, mem) + +/* Return the number of bytes from member MEM of TYPE to the end + of object OBJ. */ +#define offsetfrom(type, obj, mem) (sizeof (obj) - offsetof (type, mem)) + + +typedef __SIZE_TYPE__ size_t; +extern void* memcpy (void*, const void*, size_t); +extern void* memset (void*, int, __SIZE_TYPE__); + + +struct A { char a, b; }; +struct B { struct A a; char c, d; }; + +/* Function to call to "escape" pointers from tests below to prevent + GCC from assuming the values of the objects they point to stay + the unchanged. */ +void escape (void*, ...); + +/* Function to "generate" a random number each time it's called. Declared + (but not defined) and used to prevent GCC from making assumptions about + their values based on the variables uses in the tested expressions. */ +size_t random_unsigned_value (void); + +/* Return a random unsigned value between MIN and MAX. */ + +static inline size_t +range (size_t min, size_t max) +{ + const size_t val = random_unsigned_value (); + return val < min || max < val ? min : val; +} + + +void test_memop_warn_object (const void *src) +{ + unsigned n = range (17, 29); + + struct A a[2]; + + /* At both -Wstringop-overflow=2, like at 1, the destination of functions + that operate on raw memory is considered to be the whole array and its + size is therefore sizeof a. */ + memcpy (&a[0], src, n); /* { dg-warning "writing between 17 and 29 bytes into a region of size 4 overflows the destination" } */ + escape (a); +} + +void test_memop_warn_subobject (const void *src) +{ + unsigned n = range (17, 31); + + struct B b[2]; + + /* At -Wrawmem-overflow=2 the destination is considered to be + the member sobobject of the first array element and its size + is therefore sizeof b[0].a. */ + memcpy (&b[0].a, src, n); /* { dg-warning "writing between 17 and 31 bytes into a region of size 8 overflows the destination" } */ + + escape (b); +} + +void test_memop_nowarn_subobject (void) +{ + struct B b[2]; + + /* The following idiom of clearing multiple members of a struct + has been seen in a few places in the Linux kernel. Verify + that a warning is not issued for it. */ + memset (&b[0].c, 0, sizeof b[0] - offsetof (struct B, c)); + + escape (b); +} + +struct C { char a[3], b; }; +struct D { struct C c; char d, e; }; + +extern char* strncpy (char*, const char*, __SIZE_TYPE__); + +void test_stringop_warn_object (const char *str) +{ + unsigned n = range (2 * sizeof (struct D), 32); + + struct C c[2]; + + /* Similarly, at -Wstringop-overflow=2 the destination is considered + to be the array member of the first element of the array c and its + size is therefore sizeof c[0].a. */ + strncpy (c[0].a, "123", n); /* { dg-warning "writing between 12 and 32 bytes into a region of size 3 overflows the destination" } */ + escape (c); + + strncpy (c[0].a, str, n); /* { dg-warning "writing between 12 and 32 bytes into a region of size 3 overflows the destination" } */ + escape (c); +} + +void test_stringop_warn_subobject (const char *src) +{ + unsigned n = range (2 * sizeof (struct D), 32); + + struct D d[2]; + + /* Same as above. */ + strncpy (d[0].c.a, "123", n); /* { dg-warning "writing between 12 and 32 bytes into a region of size 3 overflows the destination" } */ + escape (d); + + strncpy (d[0].c.a, src, n); /* { dg-warning "writing between 12 and 32 bytes into a region of size 3 overflows the destination" } */ + escape (d); +}