]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/testsuite/gcc.dg/builtin-stringop-chk-6.c
Update copyright years.
[thirdparty/gcc.git] / gcc / testsuite / gcc.dg / builtin-stringop-chk-6.c
CommitLineData
ee92e7ba
MS
1/* Test exercising -Wrawmem-overflow and -Wstringop-overflow warnings. */
2/* { dg-do compile } */
3/* { dg-options "-O2 -Wstringop-overflow=2" } */
4
5#define offsetof(type, mem) __builtin_offsetof (type, mem)
6
7/* Return the number of bytes from member MEM of TYPE to the end
8 of object OBJ. */
9#define offsetfrom(type, obj, mem) (sizeof (obj) - offsetof (type, mem))
10
11
12typedef __SIZE_TYPE__ size_t;
13extern void* memcpy (void*, const void*, size_t);
14extern void* memset (void*, int, __SIZE_TYPE__);
15
16
17struct A { char a, b; };
18struct B { struct A a; char c, d; };
19
20/* Function to call to "escape" pointers from tests below to prevent
21 GCC from assuming the values of the objects they point to stay
22 the unchanged. */
23void escape (void*, ...);
24
25/* Function to "generate" a random number each time it's called. Declared
26 (but not defined) and used to prevent GCC from making assumptions about
27 their values based on the variables uses in the tested expressions. */
28size_t random_unsigned_value (void);
29
30/* Return a random unsigned value between MIN and MAX. */
31
32static inline size_t
33range (size_t min, size_t max)
34{
35 const size_t val = random_unsigned_value ();
36 return val < min || max < val ? min : val;
37}
38
39
40void test_memop_warn_object (const void *src)
41{
42 unsigned n = range (17, 29);
43
44 struct A a[2];
45
46 /* At both -Wstringop-overflow=2, like at 1, the destination of functions
47 that operate on raw memory is considered to be the whole array and its
48 size is therefore sizeof a. */
49 memcpy (&a[0], src, n); /* { dg-warning "writing between 17 and 29 bytes into a region of size 4 overflows the destination" } */
50 escape (a);
51}
52
53void test_memop_warn_subobject (const void *src)
54{
55 unsigned n = range (17, 31);
56
57 struct B b[2];
58
59 /* At -Wrawmem-overflow=2 the destination is considered to be
60 the member sobobject of the first array element and its size
61 is therefore sizeof b[0].a. */
62 memcpy (&b[0].a, src, n); /* { dg-warning "writing between 17 and 31 bytes into a region of size 8 overflows the destination" } */
63
64 escape (b);
65}
66
67void test_memop_nowarn_subobject (void)
68{
69 struct B b[2];
70
71 /* The following idiom of clearing multiple members of a struct
72 has been seen in a few places in the Linux kernel. Verify
73 that a warning is not issued for it. */
74 memset (&b[0].c, 0, sizeof b[0] - offsetof (struct B, c));
75
76 escape (b);
77}
78
79struct C { char a[3], b; };
80struct D { struct C c; char d, e; };
81
82extern char* strncpy (char*, const char*, __SIZE_TYPE__);
83
84void test_stringop_warn_object (const char *str)
85{
86 unsigned n = range (2 * sizeof (struct D), 32);
87
88 struct C c[2];
89
90 /* Similarly, at -Wstringop-overflow=2 the destination is considered
91 to be the array member of the first element of the array c and its
92 size is therefore sizeof c[0].a. */
93 strncpy (c[0].a, "123", n); /* { dg-warning "writing between 12 and 32 bytes into a region of size 3 overflows the destination" } */
94 escape (c);
95
96 strncpy (c[0].a, str, n); /* { dg-warning "writing between 12 and 32 bytes into a region of size 3 overflows the destination" } */
97 escape (c);
98}
99
100void test_stringop_warn_subobject (const char *src)
101{
102 unsigned n = range (2 * sizeof (struct D), 32);
103
104 struct D d[2];
105
106 /* Same as above. */
107 strncpy (d[0].c.a, "123", n); /* { dg-warning "writing between 12 and 32 bytes into a region of size 3 overflows the destination" } */
108 escape (d);
109
110 strncpy (d[0].c.a, src, n); /* { dg-warning "writing between 12 and 32 bytes into a region of size 3 overflows the destination" } */
111 escape (d);
112}