annotate gcc/testsuite/gcc.dg/builtin-stringop-chk-5.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Test exercising -Wrawmem-overflow and -Wstringop-overflow warnings. */
kono
parents:
diff changeset
2 /* { dg-do compile } */
kono
parents:
diff changeset
3 /* { dg-options "-O2 -Wstringop-overflow=1" } */
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 #define offsetof(type, mem) __builtin_offsetof (type, mem)
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 /* Return the number of bytes from member MEM of TYPE to the end
kono
parents:
diff changeset
8 of object OBJ. */
kono
parents:
diff changeset
9 #define offsetfrom(type, obj, mem) (sizeof (obj) - offsetof (type, mem))
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 typedef __SIZE_TYPE__ size_t;
kono
parents:
diff changeset
13 extern void* memcpy (void*, const void*, size_t);
kono
parents:
diff changeset
14 extern void* memset (void*, int, __SIZE_TYPE__);
kono
parents:
diff changeset
15
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 struct A { char a, b; };
kono
parents:
diff changeset
18 struct B { struct A a; char c, d; };
kono
parents:
diff changeset
19
kono
parents:
diff changeset
20 /* Function to call to "escape" pointers from tests below to prevent
kono
parents:
diff changeset
21 GCC from assuming the values of the objects they point to stay
kono
parents:
diff changeset
22 the unchanged. */
kono
parents:
diff changeset
23 void escape (void*, ...);
kono
parents:
diff changeset
24
kono
parents:
diff changeset
25 /* Function to "generate" a random number each time it's called. Declared
kono
parents:
diff changeset
26 (but not defined) and used to prevent GCC from making assumptions about
kono
parents:
diff changeset
27 their values based on the variables uses in the tested expressions. */
kono
parents:
diff changeset
28 size_t random_unsigned_value (void);
kono
parents:
diff changeset
29
kono
parents:
diff changeset
30 /* Return a random unsigned value between MIN and MAX. */
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 static inline size_t
kono
parents:
diff changeset
33 range (size_t min, size_t max)
kono
parents:
diff changeset
34 {
kono
parents:
diff changeset
35 const size_t val = random_unsigned_value ();
kono
parents:
diff changeset
36 return val < min || max < val ? min : val;
kono
parents:
diff changeset
37 }
kono
parents:
diff changeset
38
kono
parents:
diff changeset
39 /* Verify that writing past the end of a local array is diagnosed. */
kono
parents:
diff changeset
40
kono
parents:
diff changeset
41 void test_memop_warn_local (const void *src)
kono
parents:
diff changeset
42 {
kono
parents:
diff changeset
43 size_t n;
kono
parents:
diff changeset
44
kono
parents:
diff changeset
45 n = range (8, 32);
kono
parents:
diff changeset
46
kono
parents:
diff changeset
47 struct A a[2];
kono
parents:
diff changeset
48
kono
parents:
diff changeset
49 memcpy (a, src, n); /* { dg-warning "writing between 8 and 32 bytes into a region of size 4 overflows the destination" } */
kono
parents:
diff changeset
50 escape (a, src);
kono
parents:
diff changeset
51
kono
parents:
diff changeset
52 /* At -Wrawmem-overflow=1 the destination is considered to be
kono
parents:
diff changeset
53 the whole array and its size is therefore sizeof a. */
kono
parents:
diff changeset
54 memcpy (&a[0], src, n); /* { dg-warning "writing between 8 and 32 bytes into a region of size 4 overflows the destination" } */
kono
parents:
diff changeset
55 escape (a, src);
kono
parents:
diff changeset
56
kono
parents:
diff changeset
57 /* Verify the same as above but by writing into the first mmeber
kono
parents:
diff changeset
58 of the first element of the array. */
kono
parents:
diff changeset
59 memcpy (&a[0].a, src, n); /* { dg-warning "writing between 8 and 32 bytes into a region of size 4 overflows the destination" } */
kono
parents:
diff changeset
60 escape (a, src);
kono
parents:
diff changeset
61
kono
parents:
diff changeset
62 n = range (12, 32);
kono
parents:
diff changeset
63
kono
parents:
diff changeset
64 struct B b[2];
kono
parents:
diff changeset
65
kono
parents:
diff changeset
66 memcpy (&b[0], src, n); /* { dg-warning "writing between 12 and 32 bytes into a region of size 8 overflows the destination" } */
kono
parents:
diff changeset
67 escape (b);
kono
parents:
diff changeset
68
kono
parents:
diff changeset
69 /* The following idiom of clearing multiple members of a struct is
kono
parents:
diff changeset
70 used in a few places in the Linux kernel. Verify that a warning
kono
parents:
diff changeset
71 is issued for it when it writes past the end of the array object. */
kono
parents:
diff changeset
72 memset (&b[0].a.b, 0, offsetfrom (struct B, b, a.b) + 1); /* { dg-warning "writing 8 bytes into a region of size 7" } */
kono
parents:
diff changeset
73 escape (b);
kono
parents:
diff changeset
74
kono
parents:
diff changeset
75 memset (&b->a.b, 0, offsetfrom (struct B, b, a.b) + 1); /* { dg-warning "writing 8 bytes into a region of size 7" } */
kono
parents:
diff changeset
76 escape (b);
kono
parents:
diff changeset
77
kono
parents:
diff changeset
78 memset (&b[0].c, 0, offsetfrom (struct B, b, c) + 1); /* { dg-warning "writing 7 bytes into a region of size 6" } */
kono
parents:
diff changeset
79 escape (b);
kono
parents:
diff changeset
80
kono
parents:
diff changeset
81 memset (&b->c, 0, offsetfrom (struct B, b, c) + 1); /* { dg-warning "writing 7 bytes into a region of size 6" } */
kono
parents:
diff changeset
82 escape (b);
kono
parents:
diff changeset
83
kono
parents:
diff changeset
84 memset (&b[0].d, 0, offsetfrom (struct B, b, d) + 1); /* { dg-warning "writing 6 bytes into a region of size 5" } */
kono
parents:
diff changeset
85 escape (b);
kono
parents:
diff changeset
86
kono
parents:
diff changeset
87 memset (&b->d, 0, offsetfrom (struct B, b, d) + 1); /* { dg-warning "writing 6 bytes into a region of size 5" } */
kono
parents:
diff changeset
88 escape (b);
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 /* Same as above but clearing just elements of the second element
kono
parents:
diff changeset
91 of the array. */
kono
parents:
diff changeset
92 memset (&b[1].a.b, 0, offsetfrom (struct B, b[1], a.b) + 1); /* { dg-warning "writing 4 bytes into a region of size 3" } */
kono
parents:
diff changeset
93 escape (b);
kono
parents:
diff changeset
94
kono
parents:
diff changeset
95 memset (&b[1].c, 0, offsetfrom (struct B, b[1], c) + 1); /* { dg-warning "writing 3 bytes into a region of size 2" } */
kono
parents:
diff changeset
96 escape (b);
kono
parents:
diff changeset
97
kono
parents:
diff changeset
98 memset (&b[1].d, 0, offsetfrom (struct B, b[1], d) + 1); /* { dg-warning "writing 2 bytes into a region of size 1" } */
kono
parents:
diff changeset
99 escape (b);
kono
parents:
diff changeset
100 }
kono
parents:
diff changeset
101
kono
parents:
diff changeset
102 /* Verify that writing past the end of a dynamically allocated array
kono
parents:
diff changeset
103 of known size is diagnosed. */
kono
parents:
diff changeset
104
kono
parents:
diff changeset
105 void test_memop_warn_alloc (const void *src)
kono
parents:
diff changeset
106 {
kono
parents:
diff changeset
107 size_t n;
kono
parents:
diff changeset
108
kono
parents:
diff changeset
109 n = range (8, 32);
kono
parents:
diff changeset
110
kono
parents:
diff changeset
111 struct A *a = __builtin_malloc (sizeof *a * 2);
kono
parents:
diff changeset
112
kono
parents:
diff changeset
113 memcpy (a, src, n); /* { dg-warning "writing between 8 and 32 bytes into a region of size 4 overflows the destination" "memcpy into allocated" { xfail *-*-*} } */
kono
parents:
diff changeset
114 escape (a, src);
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116 /* At -Wrawmem-overflow=1 the destination is considered to be
kono
parents:
diff changeset
117 the whole array and its size is therefore sizeof a. */
kono
parents:
diff changeset
118 memcpy (&a[0], src, n); /* { dg-warning "writing between 8 and 32 bytes into a region of size 4 overflows the destination" "memcpy into allocated" { xfail *-*-*} } */
kono
parents:
diff changeset
119 escape (a, src);
kono
parents:
diff changeset
120
kono
parents:
diff changeset
121 /* Verify the same as above but by writing into the first mmeber
kono
parents:
diff changeset
122 of the first element of the array. */
kono
parents:
diff changeset
123 memcpy (&a[0].a, src, n); /* { dg-warning "writing between 8 and 32 bytes into a region of size 4 overflows the destination" "memcpy into allocated" { xfail *-*-*} } */
kono
parents:
diff changeset
124 escape (a, src);
kono
parents:
diff changeset
125
kono
parents:
diff changeset
126 n = range (12, 32);
kono
parents:
diff changeset
127
kono
parents:
diff changeset
128 struct B *b = __builtin_malloc (sizeof *b * 2);
kono
parents:
diff changeset
129
kono
parents:
diff changeset
130 memcpy (&b[0], src, n); /* { dg-warning "writing between 12 and 32 bytes into a region of size 8 overflows the destination" "memcpy into allocated" { xfail *-*-*} } */
kono
parents:
diff changeset
131 escape (b);
kono
parents:
diff changeset
132
kono
parents:
diff changeset
133 /* The following idiom of clearing multiple members of a struct is
kono
parents:
diff changeset
134 used in a few places in the Linux kernel. Verify that a warning
kono
parents:
diff changeset
135 is issued for it when it writes past the end of the array object. */
kono
parents:
diff changeset
136 memset (&b[0].a.b, 0, offsetfrom (struct B, b, a.b) + 1); /* { dg-warning "writing 8 bytes into a region of size 7" "memcpy into allocated" { xfail *-*-*} } */
kono
parents:
diff changeset
137 escape (b);
kono
parents:
diff changeset
138
kono
parents:
diff changeset
139 memset (&b->a.b, 0, offsetfrom (struct B, b, a.b) + 1); /* { dg-warning "writing 8 bytes into a region of size 7" "memcpy into allocated" { xfail *-*-*} } */
kono
parents:
diff changeset
140 escape (b);
kono
parents:
diff changeset
141
kono
parents:
diff changeset
142 memset (&b[0].c, 0, offsetfrom (struct B, b, c) + 1); /* { dg-warning "writing 7 bytes into a region of size 6" "memcpy into allocated" { xfail *-*-*} } */
kono
parents:
diff changeset
143 escape (b);
kono
parents:
diff changeset
144
kono
parents:
diff changeset
145 memset (&b->c, 0, offsetfrom (struct B, b, c) + 1); /* { dg-warning "writing 7 bytes into a region of size 6" "memcpy into allocated" { xfail *-*-*} } */
kono
parents:
diff changeset
146 escape (b);
kono
parents:
diff changeset
147
kono
parents:
diff changeset
148 memset (&b[0].d, 0, offsetfrom (struct B, b, d) + 1); /* { dg-warning "writing 6 bytes into a region of size 5" "memcpy into allocated" { xfail *-*-*} } */
kono
parents:
diff changeset
149 escape (b);
kono
parents:
diff changeset
150
kono
parents:
diff changeset
151 memset (&b->d, 0, offsetfrom (struct B, b, d) + 1); /* { dg-warning "writing 6 bytes into a region of size 5" "memcpy into allocated" { xfail *-*-*} } */
kono
parents:
diff changeset
152 escape (b);
kono
parents:
diff changeset
153
kono
parents:
diff changeset
154 /* Same as above but clearing just elements of the second element
kono
parents:
diff changeset
155 of the array. */
kono
parents:
diff changeset
156 memset (&b[1].a.b, 0, offsetfrom (struct B, b[1], a.b) + 1); /* { dg-warning "writing 4 bytes into a region of size 3" "memcpy into allocated" { xfail *-*-*} } */
kono
parents:
diff changeset
157 escape (b);
kono
parents:
diff changeset
158
kono
parents:
diff changeset
159 memset (&b[1].c, 0, offsetfrom (struct B, b[1], c) + 1); /* { dg-warning "writing 3 bytes into a region of size 2" "memcpy into allocated" { xfail *-*-*} } */
kono
parents:
diff changeset
160 escape (b);
kono
parents:
diff changeset
161
kono
parents:
diff changeset
162 memset (&b[1].d, 0, offsetfrom (struct B, b[1], d) + 1); /* { dg-warning "writing 2 bytes into a region of size 1" "memcpy into allocated" { xfail *-*-*} } */
kono
parents:
diff changeset
163 escape (b);
kono
parents:
diff changeset
164 }
kono
parents:
diff changeset
165
kono
parents:
diff changeset
166
kono
parents:
diff changeset
167 void test_memop_nowarn (const void *src)
kono
parents:
diff changeset
168 {
kono
parents:
diff changeset
169 struct B b[2];
kono
parents:
diff changeset
170
kono
parents:
diff changeset
171 size_t n = range (sizeof b, 32);
kono
parents:
diff changeset
172
kono
parents:
diff changeset
173 /* Verify that clearing the whole array is not diagnosed regardless
kono
parents:
diff changeset
174 of whether the expression pointing to its beginning is obtained
kono
parents:
diff changeset
175 from the array itself or its first member(s). */
kono
parents:
diff changeset
176 memcpy (b, src, n);
kono
parents:
diff changeset
177 escape (b);
kono
parents:
diff changeset
178
kono
parents:
diff changeset
179 memcpy (&b[0], src, n);
kono
parents:
diff changeset
180 escape (b);
kono
parents:
diff changeset
181
kono
parents:
diff changeset
182 memcpy (&b[0].a, src, n);
kono
parents:
diff changeset
183 escape (b, src);
kono
parents:
diff changeset
184
kono
parents:
diff changeset
185 memcpy (&b[0].a.a, src, n);
kono
parents:
diff changeset
186 escape (b, src);
kono
parents:
diff changeset
187
kono
parents:
diff changeset
188 /* Clearing multiple elements of an array of structs. */
kono
parents:
diff changeset
189 memset (&b[0].a.b, 0, sizeof b - offsetof (struct B, a.b));
kono
parents:
diff changeset
190 escape (b);
kono
parents:
diff changeset
191
kono
parents:
diff changeset
192 memset (&b->a.b, 0, sizeof b - offsetof (struct B, a.b));
kono
parents:
diff changeset
193 escape (b);
kono
parents:
diff changeset
194
kono
parents:
diff changeset
195 memset (&b[0].c, 0, sizeof b - offsetof (struct B, c));
kono
parents:
diff changeset
196 escape (b);
kono
parents:
diff changeset
197
kono
parents:
diff changeset
198 memset (&b->c, 0, sizeof b - offsetof (struct B, c));
kono
parents:
diff changeset
199 escape (b);
kono
parents:
diff changeset
200
kono
parents:
diff changeset
201 memset (&b[0].d, 0, sizeof b - offsetof (struct B, d));
kono
parents:
diff changeset
202 escape (b);
kono
parents:
diff changeset
203
kono
parents:
diff changeset
204 memset (&b->d, 0, sizeof b - offsetof (struct B, d));
kono
parents:
diff changeset
205 escape (b);
kono
parents:
diff changeset
206
kono
parents:
diff changeset
207 /* Same as above but clearing just elements of the second element
kono
parents:
diff changeset
208 of the array. */
kono
parents:
diff changeset
209 memset (&b[1].a.b, 0, sizeof b[1] - offsetof (struct B, a.b));
kono
parents:
diff changeset
210 escape (b);
kono
parents:
diff changeset
211
kono
parents:
diff changeset
212 memset (&b[1].c, 0, sizeof b[1] - offsetof (struct B, c));
kono
parents:
diff changeset
213 escape (b);
kono
parents:
diff changeset
214
kono
parents:
diff changeset
215 memset (&b[1].d, 0, sizeof b[1] - offsetof (struct B, d));
kono
parents:
diff changeset
216 escape (b);
kono
parents:
diff changeset
217 }
kono
parents:
diff changeset
218
kono
parents:
diff changeset
219
kono
parents:
diff changeset
220 /* The foollowing function could specify in its API that it takes
kono
parents:
diff changeset
221 an array of exactly two elements, as shown below. Verify that
kono
parents:
diff changeset
222 writing into both elements is not diagnosed. */
kono
parents:
diff changeset
223 void test_memop_nowarn_arg (struct A[2], const void*);
kono
parents:
diff changeset
224
kono
parents:
diff changeset
225 void test_memop_nowarn_arg (struct A *a, const void *src)
kono
parents:
diff changeset
226 {
kono
parents:
diff changeset
227 memcpy (a, src, 2 * sizeof *a);
kono
parents:
diff changeset
228 escape (a, src);
kono
parents:
diff changeset
229
kono
parents:
diff changeset
230 memcpy (a, src, range (2 * sizeof *a, 123));
kono
parents:
diff changeset
231 escape (a, src);
kono
parents:
diff changeset
232 }
kono
parents:
diff changeset
233
kono
parents:
diff changeset
234
kono
parents:
diff changeset
235 struct C { char a[3], b; };
kono
parents:
diff changeset
236 struct D { struct C c; char d, e; };
kono
parents:
diff changeset
237
kono
parents:
diff changeset
238 extern char* strncpy (char*, const char*, __SIZE_TYPE__);
kono
parents:
diff changeset
239
kono
parents:
diff changeset
240 void test_stringop_warn (void)
kono
parents:
diff changeset
241 {
kono
parents:
diff changeset
242 size_t n = range (2 * sizeof (struct D) + 1, 33);
kono
parents:
diff changeset
243
kono
parents:
diff changeset
244 struct C c[2];
kono
parents:
diff changeset
245
kono
parents:
diff changeset
246 /* Similarly, at -Wstringop-overflow=1 the destination is considered
kono
parents:
diff changeset
247 to be the whole array and its size is therefore sizeof c. */
kono
parents:
diff changeset
248 strncpy (c[0].a, "123", n); /* { dg-warning "writing between 13 and 33 bytes into a region of size 8 overflows the destination" } */
kono
parents:
diff changeset
249
kono
parents:
diff changeset
250 escape (c);
kono
parents:
diff changeset
251 }
kono
parents:
diff changeset
252
kono
parents:
diff changeset
253
kono
parents:
diff changeset
254 void test_stringop_nowarn (void)
kono
parents:
diff changeset
255 {
kono
parents:
diff changeset
256 struct D d[2];
kono
parents:
diff changeset
257
kono
parents:
diff changeset
258 strncpy (d[0].c.a, "123", range (sizeof d, 32));
kono
parents:
diff changeset
259 escape (d);
kono
parents:
diff changeset
260 }