1 /* PR 35503 - Warn about restricted pointers
2 { dg-do compile }
3 { dg-options "-O2 -Wrestrict -ftrack-macro-expansion=0" } */
4
5 #include "../gcc.dg/range.h"
6
7 #if !defined LINE
8 # define LINE 0
9 #endif
10
11 #if __cplusplus
12 # define restrict __restrict
13 extern "C" {
14 #endif
15
16 extern void* memcpy (void* restrict, const void* restrict, size_t);
17 extern void* mempcpy (void* restrict, const void* restrict, size_t);
18 extern void* memmove (void*, const void*, size_t);
19
20 extern char* stpcpy (char* restrict, const char* restrict);
21
22 extern char* strcat (char* restrict, const char* restrict);
23 extern char* strcpy (char* restrict, const char* restrict);
24 extern char* strncpy (char* restrict, const char* restrict, size_t);
25
26 #if __cplusplus
27 } /* extern "C" */
28 #endif
29
30 void sink (void*, ...);
31
32 struct MemArrays
33 {
34 char a8[8];
35 char a16[16];
36 char ax[];
37 };
38
39 /* Exercise memcpy with constant or known arguments. */
40
41 void test_memcpy_cst (void *d, const void *s)
42 {
43 #undef T
44 #define T(dst, src, n) do { \
45 if (!LINE || LINE == __LINE__) { \
46 char a[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; \
47 void *pd = (dst); \
48 const void *ps = (src); \
49 memcpy (pd, ps, (n)); \
50 sink (a, pd, ps); \
51 } \
52 } while (0)
53
54 T (a, a, 0);
55
56 /* This isn't detected because memcpy calls with size of 1 are
57 intentionally folded into safe copies equivalent to memmove,
58 regardless of the target (larger power-of-2 copies may or
59 may not be folded depending on the target -- see non_strict_align
60 below, for example).
61 It's marked xfail only because there is value in detecting such
62 invalid calls for portability, and as a reminder of why it isn't
63 diagnosed. */
64 T (a, a + 1, 1); /* { dg-warning "\\\[-Wrestrict" "memcpy with a small power of 2 size" { xfail *-*-* } } */
65 T (a, a + 3, 3);
66 T (a, a + 3, 5); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
67
68 {
69 char a[3][7];
70 sink (a);
71
72 void *d = a[0];
73 const void *s = a[1];
74 memcpy (d, s, sizeof a[0]);
75 sink (&a);
76
77 d = a[0];
78 s = a[1];
79 /* The following is only diagnosed for sizes that aren't small
80 powers of 2. */
81 memcpy (d, s, sizeof a[0] + 2); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
82 sink (&a);
83
84 d = a[0] + 1;
85 s = a[1] + 1;
86 memcpy (d, s, sizeof a[0]);
87 sink (&a);
88
89 d = a[0] + 1;
90 s = a[1] + 1;
91 memcpy (d, s, sizeof a[0] + 2); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
92 sink (&a);
93 }
94
95 {
96 struct {
97 char a[7];
98 char b[7];
99 char c[7];
100 } x;
101 sink (&x);
102
103 void *d = x.a;
104 const void *s = x.b;
105 memcpy (d, s, sizeof x.a);
106 sink (&x);
107
108 d = x.a + 4;
109 s = x.b;
110 memcpy (d, s, sizeof x.a); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
111 sink (&x);
112
113 d = x.a + 6;
114 s = x.b;
115 memcpy (d, s, 1);
116 sink (&x);
117
118 d = x.a + 7;
119 s = x.b;
120 memcpy (d, s, 3); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
121 sink (&x);
122
123 d = x.a + 7;
124 s = x.b + 1;
125 memcpy (d, s, 1);
126 sink (&x);
127
128 d = x.b;
129 s = x.a;
130 memcpy (d, s, 1);
131 sink (&x);
132
133 d = x.b;
134 s = x.a;
135 memcpy (d, s, sizeof x.b);
136 sink (&x);
137
138 d = x.b + 2;
139 s = x.a + 1;
140 memcpy (d, s, sizeof x.b);
141 sink (&x);
142
143 d = x.b + 2;
144 s = x.a + 2;
145 memcpy (d, s, sizeof x.b);
146 sink (&x);
147
148 d = x.b + 2;
149 s = x.a + 3;
150 memcpy (d, s, sizeof x.b); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
151 sink (&x);
152 }
153
154 {
155 #undef T
156 #define T(dst, src, n) do { \
157 if (!LINE || LINE == __LINE__) { \
158 char a[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; \
159 memcpy ((dst), (src), (n)); \
160 sink (a); \
161 } \
162 } while (0)
163
164 /* Verify the offset of the overlap is the same regardless of whether
165 the destination is at lower or higher offset than the source. */
166 T (a, a + 1, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and 1 overlaps 4 bytes at offset 1" "memcpy" } */
167 T (a, a + 2, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and 2 overlaps 3 bytes at offset 2" "memcpy" } */
168 T (a, a + 3, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and 3 overlaps 2 bytes at offset 3" "memcpy" } */
169
170 T (a + 1, a, 5); /* { dg-warning "accessing 5 bytes at offsets 1 and 0 overlaps 4 bytes at offset 1" "memcpy" } */
171 T (a + 2, a, 5); /* { dg-warning "accessing 5 bytes at offsets 2 and 0 overlaps 3 bytes at offset 2" "memcpy" } */
172 T (a + 3, a, 5); /* { dg-warning "accessing 5 bytes at offsets 3 and 0 overlaps 2 bytes at offset 3" "memcpy" } */
173 }
174 }
175
176 /* Exercise memcpy with destination or source offset or size in
177 a determinate range. */
178
179 void test_memcpy_range (char *d, size_t sz)
180 {
181 #undef T
182 #define T(dst, src, n) do { \
183 if (!LINE || LINE == __LINE__) { \
184 char a[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; \
185 void *pd = (dst); \
186 const void *ps = (src); \
187 memcpy (pd, ps, (n)); \
188 sink (a, pd, ps); \
189 } \
190 } while (0)
191
192 ptrdiff_t ir = SR (2, 3);
193 T (a + ir, a, 0);
194 T (a + ir, a, 1);
195 T (a + ir, a, 2);
196 T (a + ir, a, 3);
197 /* The following fails because the size is a small power of 2. */
198 T (a + ir, a, 4); /* { dg-warning "accessing 4 bytes at offsets \\\[2, 3] and 0 overlaps between 1 and 2 bytes at offset \(\\\[3, 2]|\\\[2, 3]\)" "pr79220" { xfail non_strict_align } } */
199 T (a + ir, a, 5); /* { dg-warning "accessing 5 bytes at offsets \\\[2, 3] and 0 overlaps between 2 and 3 bytes at offset \\\[2, 3]" "memcpy" } */
200
201 T (d + ir, d, 0);
202 T (d + ir, d, 1);
203 T (d + ir, d, 2);
204 T (d + ir, d, 3);
205 T (d + ir, d, 4); /* { dg-warning "accessing 4 bytes at offsets \\\[2, 3] and 0 overlaps between 1 and 2 bytes at offset \\\[2, 3]" "pr79220" { xfail non_strict_align } } */
206 T (d + ir, d, 5); /* { dg-warning "accessing 5 bytes at offsets \\\[2, 3] and 0 overlaps between 2 and 3 bytes at offset \\\[2, 3]" "memcpy" } */
207
208 /* Because the size is constant and a power of 2 the following is
209 folded too early to detect the overlap. */
210 T (d + ir, d, 4); /* { dg-warning "accessing 4 bytes at offsets \\\[2, 3] and 0 overlaps between 1 and 2 bytes at offset \\\[2, 3]" "pr79220" { xfail non_strict_align } } */
211 T (d + ir, d, 5); /* { dg-warning "accessing 5 bytes at offsets \\\[2, 3] and 0 overlaps between 2 and 3 bytes at offset \\\[2, 3]" "memcpy" } */
212
213 /* Exercise the full range of size_t. */
214 T (d + sz, d, 0);
215 T (d + sz, d, 1);
216 T (d + sz, d, 9);
217
218 T (a, a + 1, SR (0, 1));
219 T (a, a + 1, SR (0, 2));
220 T (a, a + 1, SR (1, 2));
221 T (a, a + 1, SR (2, 3)); /* { dg-warning "accessing between 2 and 3 bytes at offsets 0 and 1 overlaps between 1 and 2 bytes at offset 1" "memcpy" } */
222 T (a, a + 1, UR (2, DIFF_MAX + (size_t)1)); /* { dg-warning "accessing 2 or more bytes at offsets 0 and 1 overlaps 1 or more bytes at offset 1" "memcpy" } */
223 T (a, a + 1, UR (2, SIZE_MAX - 1)); /* { dg-warning "accessing 2 or more bytes at offsets 0 and 1 overlaps 1 or more bytes at offset 1" "memcpy" } */
224 T (a, a + 2, SR (2, 3));
225 T (a, a + 2, SR (3, 4)); /* { dg-warning "accessing between 3 and 4 bytes at offsets 0 and 2 overlaps between 1 and 2 bytes at offset 2" "memcpy" } */
226 T (a, a + 3, SR (3, 4));
227 T (a, a + 3, SR (4, 5)); /* { dg-warning "accessing between 4 and 5 bytes at offsets 0 and 3 overlaps between 1 and 2 bytes at offset 3" "memcpy" } */
228 T (a, a + 3, SR (5, 6)); /* { dg-warning "accessing between 5 and 6 bytes at offsets 0 and 3 overlaps between 2 and 3 bytes at offset 3" "memcpy" } */
229
230 T (a + 1, a, SR (0, 1));
231 T (a + 1, a, SR (0, 2));
232 T (a + 1, a, SR (1, 2));
233 T (a + 1, a, SR (2, 3)); /* { dg-warning "accessing between 2 and 3 bytes at offsets 1 and 0 overlaps between 1 and 2 bytes at offset 1" "memcpy" } */
234 T (a + 1, a, UR (2, DIFF_MAX + (size_t)1)); /* { dg-warning "accessing 2 or more bytes at offsets 1 and 0 overlaps 1 or more bytes at offset 1" "memcpy" } */
235 T (a + 1, a, UR (2, SIZE_MAX - 1)); /* { dg-warning "accessing 2 or more bytes at offsets 1 and 0 overlaps 1 or more bytes at offset 1" "memcpy" } */
236 T (a + 2, a, SR (2, 3));
237 T (a + 2, a, SR (3, 4)); /* { dg-warning "accessing between 3 and 4 bytes at offsets 2 and 0 overlaps between 1 and 2 bytes at offset 2" "memcpy" } */
238 T (a + 3, a, SR (3, 4));
239 T (a + 3, a, SR (4, 5)); /* { dg-warning "accessing between 4 and 5 bytes at offsets 3 and 0 overlaps between 1 and 2 bytes at offset 3" "memcpy" } */
240 T (a + 3, a, SR (5, 6)); /* { dg-warning "accessing between 5 and 6 bytes at offsets 3 and 0 overlaps between 2 and 3 bytes at offset 3" "memcpy" } */
241
242 ir = SR (2, 5);
243 T (a, a + ir, 4);
244 T (a, a + ir, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[2, 5] overlaps between 1 and 3 bytes at offset \\\[2, 4]" "memcpy" } */
245 T (a, a + ir, 6); /* { dg-warning "accessing 6 bytes at offsets 0 and \\\[2, 5] overlaps between 3 and 4 bytes at offset \\\[2, 3]" "memcpy" } */
246
247 /* Below, there are two possible regions for the source of the copy:
248 1) one just before the high end of the address space that's 3
249 bytes large close to the lower end of the offset range, and
250 2) another in the [DIFF_MIN, -8] range from D and so at least
251 8 bytes in size
252 A copy from (1) overlaps but one from (2) does not. Verify that
253 the copy is not diagnosed. (This test case was reduced from
254 the Linux kernel.) */
255 T (d, d + UR (DIFF_MAX - 3, SIZE_MAX - 7), 5);
256 T (d, d + UR (DIFF_MAX - 3, SIZE_MAX - 7), 6);
257 T (d, d + UR (DIFF_MAX - 3, SIZE_MAX - 7), 7);
258 T (d, d + UR (DIFF_MAX - 3, SIZE_MAX - 7), 9);
259
260 T (d + UR (DIFF_MAX - 3, SIZE_MAX - 7), d, 5);
261 T (d + UR (DIFF_MAX - 3, SIZE_MAX - 7), d, 6);
262 T (d + UR (DIFF_MAX - 3, SIZE_MAX - 7), d, 7);
263 T (d + UR (DIFF_MAX - 3, SIZE_MAX - 7), d, 9);
264
265 {
266 /* Create an offset in the range [0, -1]. */
267 size_t o = sz << 1;
268 #if __SIZEOF_SIZE_T__ < 4
269 T (d, d + o, 1234);
270 T (d + o, d, 2345);
271 #else
272 T (d, d + o, 12345);
273 T (d + o, d, 23456);
274 #endif
275 }
276
277 /* Exercise memcpy with both destination and source pointer offsets
278 in some known range. */
279 size_t n = UR (3, 4);
280 T (a + SR (1, 3), a + SR (1, 3), n); /* { dg-warning "accessing between 3 and 4 bytes at offsets \\\[1, 3] and \\\[1, 3] overlaps between 1 and 4 bytes at offset \\\[1, 3]" "memcpy" } */
281
282 /* This is an interesting case:
283 memcpy (a + i, a + j, n) with i in [1, 3], j in [2, 3], and n in [3, 4]
284 we have the following possibilities ('^' denotesthe destination offset,
285 '*' marks the overlap, and '?' is the possible overlap for large n):
286 i j | a = 012345678 SIZ OFF (size and offset of the overlap)
287 1 2 | ^**? 2-3 2
288 1 3 | ^ *? 1-2 3
289 2 2 | ***? 3-4 2
290 2 3 | ^**? 2-3 3
291 3 3 | ***? 3-4 3
292 There are two ways to present the results:
293 1) overlaps between 1 and 4 bytes at offset [2, 3]
294 2) overlaps between 1 and 4 bytes at offset 2. */
295 T (a + SR (1, 3), a + SR (2, 3), n); /* { dg-warning "accessing between 3 and 4 bytes at offsets \\\[1, 3] and \\\[2, 3] overlaps between 1 and 4 bytes at offset \\\[2, 3]" "memcpy" } */
296 T (a + SR (1, 3), a + SR (3, 4), n);
297
298 T (a + SR (2, 3), a + SR (3, 4), n); /* { dg-warning "accessing between 3 and 4 bytes at offsets \\\[2, 3] and \\\[3, 4] overlaps between 1 and 4 bytes at offset \\\[3, 4]" "memcpy" } */
299
300 T (a + SR (1, 3), a + SR (4, 5), n);
301 T (a + SR (2, 3), a + SR (4, 5), n);
302 T (a + SR (3, 4), a + SR (4, 5), n); /* { dg-warning "accessing between 3 and 4 bytes at offsets \\\[3, 4] and \\\[4, 5] overlaps between 1 and 4 bytes at offset \\\[4, 5]" "memcpy" } */
303
304 /* Exercise the full range of size_t. */
305 T (d, d + sz, 0);
306 T (d, d + sz, 1);
307 T (d, d + sz, 9);
308 }
309
310 /* Exercise memcpy with offset and/or size in a determinate anti-range. */
311
312 void test_memcpy_anti_range (char *d, const char *s)
313 {
314 T (d, d + SAR (0, 3), 1);
315 T (d, d + SAR (0, 3), 2);
316 T (d, d + SAR (0, 3), 3);
317 T (d, d + SAR (0, 3), DIFF_MAX - 2); /* { dg-warning "overlaps \[0-9\]+ bytes at offset 2" "memcpy" } */
318 T (d, d + SAR (0, 3), DIFF_MAX - 1); /* { dg-warning "overlaps \[0-9\]+ bytes at offset 1" "memcpy" } */
319 T (d, d + SAR (0, 3), DIFF_MAX); /* { dg-warning "overlaps \[0-9\]+ bytes at offset 0" "memcpy" } */
320
321 T (d, d + SAR (0, 3), UR (DIFF_MAX - 2, DIFF_MAX)); /* { dg-warning "accessing \[0-9\]+ or more bytes at offsets 0 and \\\[-?\[0-9\]+, -?\[0-9\]+] overlaps \[0-9\]+ bytes at offset 2" "memcpy" } */
322
323 /* Verify that a size in an anti-range ~[1, N] where N >= PTRDIFF_MAX - 2
324 doesn't trigger a warning.
325 With ~[1, PTRDIFF_MAX - 1] the difference between the just-past-the-end
326 pointer to A and A for char A[PTRDIFF_MAX] wouldn't be representable in
327 ptrdiff_t. Since such a large object cannot exist, so the size of
328 the region must be zero. */
329 T (d, s, UAR (1, DIFF_MAX / 2 - 1));
330 T (d, s, UAR (1, DIFF_MAX - 1));
331 T (d, s, UAR (1, DIFF_MAX));
332 T (d, s, UAR (1, SIZE_MAX - 1));
333 T (d, s, UAR (1, SIZE_MAX));
334 }
335
336 /* Verify calls to memcpy() where the combination of offsets in some
337 range and size is such that either overlap is unavoidable or one
338 or both offsets would exceed the maximum size of an object
339 (DIFF_MAX). */
340
341 void test_memcpy_range_exceed (char *d, const char *s)
342 {
343 /* Verify offset and size both in some range. The memcpy checking
344 is less strict than that of string functions like strncpy and
345 doesn't trigger unless the overlap is certain. The following
346 overlaps for (r == 3 && n > 3) but not, for example, for
347 (r == 4 && n == 4), and so it's not diagnosed. */
348 ptrdiff_t i = SR (3, 5);
349 size_t n = UR (4, 6);
350
351 T (a, a + i, n);
352 T (a + i, a, n);
353 /* Ditto for objects of unknown sizes. */
354 T (d, d + i, n);
355 T (d + i, d, n);
356
357 /* Verify that a warning is issued for a copy between two regions
358 whose aggregate size would exceed DIFF_MAX if it were to not
359 overlap. */
360 T (d, s, DIFF_MAX / 2);
361 T (d, s, DIFF_MAX / 2 + 1); /* { dg-warning "overlaps 1 byte" "memcpy" } */
362 T (d, s, DIFF_MAX / 2 + 2); /* { dg-warning "overlaps 3 bytes" "memcpy" } */
363 T (d, s, DIFF_MAX / 2 + 3); /* { dg-warning "overlaps 5 bytes" "memcpy" } */
364
365 i = SR (DIFF_MAX - 2, DIFF_MAX);
366
367 /* Verify a warning for an out-of-bounds offset range and constant
368 size addition. */
369 T (d, d + i, 3); /* { dg-warning "accessing 3 bytes at offsets 0 and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 byte" "memcpy" } */
370 T (d + i, d, 3); /* { dg-warning "accessing 3 bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and 0 overlaps 1 byte" "memcpy" } */
371
372 T (d + 1, d + i, 3); /* { dg-warning "accessing 3 bytes at offsets 1 and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 byte" "memcpy" } */
373 T (d + i, d + 1, 3); /* { dg-warning "accessing 3 bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and 1 overlaps 1 byte" "memcpy" } */
374
375 /* Verify that the warnings above are independent of whether the source
376 and destination are known to be based on the same object. */
377 T (d, s + i, 3); /* { dg-warning "accessing 3 bytes at offsets 0 and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 byte" "memcpy" } */
378 T (d + i, s, 3); /* { dg-warning "accessing 3 bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and 0 overlaps 1 byte" "memcpy" } */
379
380 T (d + 1, s + i, 3); /* { dg-warning "accessing 3 bytes at offsets 1 and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 byte" "memcpy" } */
381 T (d + i, s + 1, 3); /* { dg-warning "accessing 3 bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and 1 overlaps 1 byte" "memcpy" } */
382
383 #if __SIZEOF_SIZE_T__ == 8
384 /* Verfiy the offset and size computation is correct. The overlap
385 offset mentioned in the warning plus sthe size of the access must
386 not exceed DIFF_MAX. */
387 T (d, d + i, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[9223372036854775805, 9223372036854775807] overlaps 3 bytes at offset 9223372036854775802" "LP64" { target lp64 } } */
388 T (d + i, d, 5); /* { dg-warning "accessing 5 bytes at offsets \\\[9223372036854775805, 9223372036854775807] and 0 overlaps 3 bytes at offset 9223372036854775802" "LP64" { target lp64 } } */
389
390 T (d, s + i, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[9223372036854775805, 9223372036854775807] overlaps 3 bytes at offset 9223372036854775802" "LP64" { target lp64 } } */
391 T (d + i, s, 5); /* { dg-warning "accessing 5 bytes at offsets \\\[9223372036854775805, 9223372036854775807] and 0 overlaps 3 bytes at offset 9223372036854775802" "LP64" { target lp64 } } */
392 #elif __SIZEOF_SIZE_T__ == 4
393 T (d, d + i, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[2147483645, 2147483647] overlaps 3 bytes at offset 2147483642" "ILP32" { target ilp32 } } */
394 T (d + i, d, 5); /* { dg-warning "accessing 5 bytes at offsets \\\[2147483645, 2147483647] and 0 overlaps 3 bytes at offset 2147483642" "ILP32" { target ilp32 } } */
395
396 T (d, s + i, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[2147483645, 2147483647] overlaps 3 bytes at offset 2147483642" "ILP32" { target ilp32 } } */
397 T (d + i, s, 5); /* { dg-warning "accessing 5 bytes at offsets \\\[2147483645, 2147483647] and 0 overlaps 3 bytes at offset 2147483642" "ILP32" { target ilp32} } */
398 #endif
399
400 ptrdiff_t j = SR (DIFF_MAX - 9, DIFF_MAX - 1);
401 i = SR (DIFF_MAX - 5, DIFF_MAX - 1);
402 n = UR (4, 5);
403 T (d + i, d + j, n);
404
405 n = UR (4, DIFF_MAX - 1);
406 T (d + i, d + j, n);
407
408 n = UR (4, SIZE_MAX - 1);
409 T (d + i, d + j, n);
410
411 j = SR (DIFF_MAX - 8, DIFF_MAX - 1);
412 T (d + i, d + j, n);
413
414 j = SR (DIFF_MAX - 7, DIFF_MAX - 1);
415 T (d + i, d + j, n); /* { dg-warning "accessing 4( or more)? bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and \\\[\[0-9\]+, \[0-9\]+] overlaps" "memcpy" } */
416
417 j = SR (DIFF_MAX - 6, DIFF_MAX - 1);
418 T (d + i, d + j, n); /* { dg-warning "accessing 4( or more)? bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and \\\[\[0-9\]+, \[0-9\]+] overlaps" "memcpy" } */
419
420 n = UR (3, DIFF_MAX);
421 T (d + i, d + j, n);
422
423 j = SR (DIFF_MAX - 6, DIFF_MAX - 1);
424 T (d + i, d + j, n);
425
426 j = SR (DIFF_MAX - 5, DIFF_MAX - 1);
427 T (d + i, d + j, n); /* { dg-warning "accessing 3 or more bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 or more bytes" "memcpy" } */
428
429 j = SR (DIFF_MAX - 4, DIFF_MAX - 1);
430 T (d + i, d + j, n); /* { dg-warning "accessing 3 or more bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 or more bytes" "memcpy" } */
431
432 j = SR (DIFF_MAX - 2, DIFF_MAX - 1);
433 T (d + i, d + j, n); /* { dg-warning "accessing 3 or more bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 or more bytes" "memcpy" } */
434 }
435
436 /* Exercise memcpy with destination and source of unknown size. */
437
438 void test_memcpy_var (char *d, const char *s)
439 {
440 size_t n = unsigned_value ();
441
442 /* Since no copying takes place no warning should be issued. */
443 memcpy (d, d, 0);
444 sink (d);
445
446 /* The following overlaps if n is greater than 1. */
447 s = d + 1;
448 memcpy (d, s, n);
449 sink (d);
450
451 s = d + n;
452 memcpy (d, s, n);
453 sink (d);
454
455 s = d + signed_value ();
456 memcpy (d, s, unsigned_value ());
457 sink (d);
458
459 s = d + 3;
460 n = 1;
461 memcpy (d, s, n);
462 sink (d);
463
464 s = d + 3;
465 n = 2;
466 memcpy (d, s, n);
467 sink (d);
468
469 s = d + 3;
470 n = 3;
471 memcpy (d, s, n);
472 sink (d);
473
474 s = d + 3;
475 n = 4;
476 memcpy (d, s, n); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
477 sink (d);
478
479 s = d + 5;
480 n = 7;
481 memcpy (d, s, n); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
482 }
483
484
485 void test_memcpy_memarrray (struct MemArrays *p)
486 {
487 #undef T
488 #define T(dst, src, n) do { \
489 if (!LINE || LINE == __LINE__) { \
490 void *pd = (dst); \
491 const void *ps = (src); \
492 memcpy (pd, ps, (n)); \
493 sink (pd, ps); \
494 } \
495 } while (0)
496
497 T (p->a8, p->a8, 0);
498 T (p->a8, p->a8 + 1, 1);
499 T (p->a8, p->a8 + 2, 2);
500 T (p->a8, p->a8 + 8, 1);
501
502 T (p->a8, p->a8 + 2, 3); /* { dg-warning "accessing 3 bytes at offsets 0 and 2 overlaps 1 byte at offset 2" "memcpy" } */
503 }
504
505 /* Exercise the absence of warnings with memmove. */
506
507 void test_memmove (void)
508 {
509 {
510 char d[7];
511 sink (d);
512
513 const void *s = d;
514 memmove (d, s, 7);
515 sink (d);
516
517 s = d + 1;
518 memmove (d, s, 6);
519 sink (d);
520
521 s = d + 2;
522 memmove (d + 1, s, 5);
523 sink (d);
524 }
525 }
526
527 /* Exercise strcat with constant or known arguments. */
528
529 void test_strcat_cst (const char *s)
530 {
531 #undef T
532 #define T(init, dst, src) do { \
533 if (!LINE || LINE == __LINE__) { \
534 char a[9] = init; \
535 char *pd = (dst); \
536 const char *ps = (src); \
537 strcat (pd, ps); \
538 sink (a, pd, ps); \
539 } \
540 } while (0)
541
542 T ("0", a, a); /* { dg-warning "source argument is the same as destination" "strcat" } */
543 T ("01", a, a); /* { dg-warning "source argument is the same as destination" "strcat" } */
544 T ("012", a, a); /* { dg-warning "source argument is the same as destination" "strcat" } */
545 /* The 3 bytes "12\0" being appended to "012" overwrite the final NUL. */
546 T ("012", a, a + 1); /* { dg-warning "accessing 3 bytes at offsets 0 and 1 overlaps 1 byte at offset 3" "strcat" } */
547 T ("012", a, a + 2); /* { dg-warning "accessing 2 bytes at offsets 0 and 2 overlaps 1 byte at offset 3" "strcat" } */
548 /* The nul copied from a[3] to a[3] overwrites itself so this is
549 diagnosed. */
550 T ("012", a, a + 3); /* { dg-warning "accessing 1 byte at offsets 0 and 3 overlaps 1 byte at offset 3" "strcat" } */
551
552 T ("012", a, a + 4);
553 T ("012", a, a + 5);
554 T ("012", a, a + 6);
555 T ("012", a, a + 7);
556 T ("012", a, a + 8);
557
558 T ("0", a + 1, a); /* { dg-warning "accessing 2 bytes at offsets 1 and 0 overlaps 1 byte at offset 1" "strcat" } */
559 T ("0", a + 2, a);
560
561 /* The first of the two offsets in the diagnostic for strcat is that
562 of the first write into the destination, not that of the initial
563 read from it to compute its length. */
564 T ("01", a + 1, a); /* { dg-warning "accessing 3 bytes at offsets 1 and 0 overlaps 1 byte at offset 2" "strcat" } */
565 T ("01", a + 2, a); /* { dg-warning "accessing 3 bytes at offsets 2 and 0 overlaps 1 byte at offset 2" "strcat" } */
566 T ("01", a + 3, a);
567
568 T ("012", a + 1, a); /* { dg-warning "accessing 4 bytes at offsets 1 and 0 overlaps 1 byte at offset 3" "strcat" } */
569 T ("012", a + 2, a); /* { dg-warning "accessing 4 bytes at offsets 2 and 0 overlaps 1 byte at offset 3" "strcat" } */
570 T ("012", a + 3, a); /* { dg-warning "accessing 4 bytes at offsets 3 and 0 overlaps 1 byte at offset 3 " "strcat" } */
571 T ("012", a + 4, a);
572 T ("012", a + 5, a);
573
574 /* Verify that the obviously benign cases below aren't diagnosed. */
575 T ("012", a, "012");
576 T ("012", a, s);
577 T ("01234567", a, s);
578 }
579
580 /* Exercise strcat with destination and source of unknown length. */
581
582 void test_strcat_var (char *d, const char *s)
583 {
584 #undef T
585 #define T(dst, src) do { \
586 if (!LINE || LINE == __LINE__) { \
587 char *pd = (dst); \
588 const char *ps = (src); \
589 strcat (pd, ps); \
590 sink (pd, ps); \
591 } \
592 } while (0)
593
594 T (d, d); /* { dg-warning "source argument is the same as destination" "strcat" } */
595 T (d, d + 1); /* { dg-warning "accessing 2 or more bytes at offsets 0 and 1 may overlap 1 byte" "strcat" } */
596 T (d, d + 2); /* { dg-warning "accessing 3 or more bytes at offsets 0 and 2 may overlap 1 byte at offset 2" "strcat" } */
597 T (d, d + 999); /* { dg-warning "accessing 1000 or more bytes at offsets 0 and 999 may overlap 1 byte at offset 999" "strcat" } */
598
599 /* The source string must be at least 100 bytes in length for the copy
600 below to overlap. */
601 T (d, d + -99); /* { dg-warning "accessing 100 or more bytes at offsets 0 and -99 may overlap 1 byte" "strcat" } */
602
603 size_t n = unsigned_value ();
604
605 T (d + n, d + n); /* { dg-warning "\\\[-Wrestrict" "strcat" } */
606
607 /* Verify that the obviously benign cases below aren't diagnosed. */
608 T (d, "012");
609 T (d + 1, "0123");
610 T (d + n, "01234");
611 T (d, s);
612 T (d + 1, s);
613 T (d + n, s);
614
615 /* Since the offset is unknown the overlap in the call below, while
616 possible, is certainly not inevitable. Conservatively, it should
617 not be diagnosed. For safety, an argument for diagnosing can be
618 made. It's a judgment call, partly determined by the effort and
619 complexity of treating this case differently from other similar
620 to it. */
621 T (d, d + n); /* { dg-warning "may overlap" "strcat" } */
622 }
623
624 /* Exercise strcpy with constant or known arguments. */
625
626 void test_strcpy_cst (ptrdiff_t i)
627 {
628 #undef T
629 #define T(init, dst, src) do { \
630 if (!LINE || LINE == __LINE__) { \
631 char a[8] = init; \
632 char *pd = (dst); \
633 const char *ps = (src); \
634 strcpy (pd, ps); \
635 sink (a, pd, ps); \
636 } \
637 } while (0)
638
639 T ("012", a, a); /* { dg-warning "source argument is the same as destination" "strcpy" } */
640 T ("012", a, a + 1); /* { dg-warning "accessing 3 bytes at offsets 0 and 1 overlaps 2 bytes at offset 1" "strcpy" } */
641 T ("012", a, a + 2);
642 T ("012", a, a + 3);
643 T ("012", a, a + sizeof a); /* { dg-warning "\\\[-Wstringop-overread" "pr81437" } */
644
645 /* The terminating nul written to d[2] overwrites s[0]. */
646 T ("0123", a, a + 2); /* { dg-warning "accessing 3 bytes at offsets 0 and 2 overlaps 1 byte at offset 2" } */
647
648 /* The '5' copied from s[2] to d[2] overwrites s[0]. */
649 T ("01234", a, a + 2); /* { dg-warning "accessing 4 bytes at offsets 0 and 2 overlaps 2 bytes at offset 2" } */
650
651 /* This happens to be safe in GCC but it's still wrong. */
652 T ("012", a, a); /* { dg-warning "source argument is the same as destination" "strcpy" } */
653
654 T ("012", a + 1, a); /* { dg-warning "accessing 4 bytes at offsets 1 and 0 overlaps 3 bytes at offset 1" "strcpy" } */
655 T ("012", a + 2, a); /* { dg-warning "accessing 4 bytes at offsets 2 and 0 overlaps 2 bytes at offset 2" "strcpy" } */
656 T ("012", a + 3, a); /* { dg-warning "accessing 4 bytes at offsets 3 and 0 overlaps 1 byte at offset 3" "strcpy" } */
657 T ("012", a + 4, a);
658 /* The following doesn't overlap but it triggers -Wstringop-overflow
659 for writing past the end. */
660 T ("012", a + sizeof a, a); /* { dg-warning "\\\[-Wstringop-overflow" } */
661 }
662
663 /* Exercise strcpy with constant or known arguments offset by a range.
664 The tests verify the use of the lower bound of the range which is
665 more restrictive than using the upper bound for positive values. */
666
667 void test_strcpy_range (void)
668 {
669 #undef T
670 #define T(N, init, dst, src) \
671 do { \
672 if (!LINE || LINE == __LINE__) { \
673 char a[N] = init; \
674 char *pd = (dst); \
675 const char *ps = (src); \
676 strcpy (pd, ps); \
677 sink (a, pd, ps); \
678 } \
679 } while (0)
680
681 ptrdiff_t r;
682
683 r = SR (0, 1);
684 T (8, "0", a + r, a); /* { dg-warning "accessing between 1 and 2 bytes at offsets \\\[0, 1] and 0 overlaps up to 2 bytes at offset \\\[0, 1]" "strcpy" { xfail *-*-*} } */
685
686 r = SR (2, 5);
687 T (8, "01", a + r, a); /* { dg-warning "accessing 3 bytes at offsets \\\[2, 5] and 0 may overlap 1 byte at offset 2" } */
688 T (8, "012", a + r, a); /* { dg-warning "accessing 4 bytes at offsets \\\[2, 5] and 0 may overlap up to 2 bytes at offset \\\[2, 3]" "strcpy" } */
689
690 /* The highest offset to which to copy without overflowing the 8-byte
691 destination is 3 and that overlaps 2 bytes. */
692 T (8, "0123", a + r, a); /* { dg-warning "accessing 5 bytes at offsets \\\[2, 5] and 0 overlaps between 2 and 3 bytes at offset \\\[2, 3]" "strcpy" } */
693
694 /* With a 9-byte destination the highest offset is 4 and that still
695 overlaps 1 byte (the final NUL). */
696 T (9, "0123", a + r, a); /* { dg-warning "accessing 5 bytes at offsets \\\[2, 5] and 0 overlaps between 1 and 3 bytes at offset \\\[2, 4]" "strcpy" } */
697
698 /* With a 10-byte buffer it's possible to copy all 5 bytes without
699 overlap at (a + 5). Copying at offsets 2 through 4 overflows
700 between 3 and 1 bytes, respectively. */
701 T (10, "0123", a + r, a); /* { dg-warning "accessing 5 bytes at offsets \\\[2, 5] and 0 may overlap up to 3 bytes at offset \\\[2, 4]" "strcpy" } */
702
703
704 r = SR (3, 4);
705 T (8, "01", a + r, a);
706 T (8, "012", a + r, a); /* { dg-warning "accessing 4 bytes at offsets \\\[3, 4] and 0 may overlap 1 byte at offset 3" "strcpy" } */
707
708 /* The highest offset to which to copy without overflowing the 8-byte
709 destination is 3 and that overlaps 2 bytes. */
710 T (8, "0123", a + r, a); /* { dg-warning "accessing 5 bytes at offsets \\\[3, 4] and 0 overlaps 2 bytes at offset 3" "strcpy" } */
711
712 /* With a 9-byte destination the highest offset is 4 and that still
713 overlaps 1 byte (the final NUL). */
714 T (9, "0123", a + r, a); /* { dg-warning "accessing 5 bytes at offsets \\\[3, 4] and 0 overlaps between 1 and 2 bytes at offset \\\[3, 4]" "strcpy" } */
715
716 /* With a 10-byte buffer it's possible to copy all 5 bytes without
717 overlap at (a + 5). Copying at offsets 2 through 4 overflows
718 between 3 and 1 bytes, respectively. */
719 T (10, "0123", a + r, a); /* { dg-warning "accessing 5 bytes at offsets \\\[3, 4] and 0 overlaps between 1 and 2 bytes at offset \\\[3, 4]" "strcpy" } */
720
721 T (8, "01", a, a + r);
722 T (8, "012", a, a + r);
723 T (8, "0123", a, a + r);
724 T (8, "01234", a, a + r);
725
726 /* With the smaller offset of 3 the final NUL definitely overlaps
727 the '4' at a[3], but with the larger offset of 4 there is no
728 overlap, so the warning is a "may overlap" and the size of
729 the overlap is 1 byte. */
730 T (8, "012345", a, a + r); /* { dg-warning "accessing between 3 and 4 bytes at offsets 0 and \\\[3, 4] may overlap 1 byte at offset 3" "strcpy" } */
731 T (8, "0123456", a, a + r); /* { dg-warning "accessing between 4 and 5 bytes at offsets 0 and \\\[3, 4] may overlap up to 2 bytes at offset \\\[3, 4]" "strcpy" } */
732
733 r = SR (3, DIFF_MAX - 3);
734 T (8, "01", a + r, a);
735
736 /* The accesses below might trigger either
737 -Wrestrict: accessing 4 bytes at offsets [3, \[0-9\]+] and 0 may overlap 1 byte at offset 3
738 or
739 -Wstringop-overflow: writing 4 bytes into a region of size 0
740 Either of the two is appropriate. */
741 T (8, "012", a + r, a); /* { dg-warning "\\\[-Wrestrict|-Wstringop-overflow" } */
742
743 r = SR (DIFF_MAX - 2, DIFF_MAX - 1);
744 T (8, "012", a + r, a); /* { dg-warning "\\\[-Wrestrict|-Wstringop-overflow" } */
745
746 /* Exercise the full range of ptrdiff_t. */
747 r = signed_value ();
748
749 /* The overlap in the cases below isn't inevitable but it is diagnosed
750 because it is possible and so the code is considered unsafe. */
751 T (8, "", a, a + r); /* { dg-warning "accessing 1 byte at offsets 0 and \\\[0, 8] may overlap 1 byte" "strcpy" } */
752 T (8, "0", a + r, a); /* { dg-warning "accessing 2 bytes at offsets \\\[0, 8] and 0 may overlap up to 2 bytes" "strcpy" } */
753 T (8, "012", a + r, a); /* { dg-warning "accessing 4 bytes at offsets \\\[0, 8] and 0 may overlap up to 4 bytes" "strcpy" } */
754
755 T (8, "", a, a + r); /* { dg-warning "accessing 1 byte at offsets 0 and \\\[0, 8] may overlap" "strcpy" } */
756 T (8, "0", a, a + r); /* { dg-warning "accessing between 1 and 2 bytes at offsets 0 and \\\[0, 8] may overlap up to 2 bytes" "strcpy" } */
757 T (8, "012", a, a + r); /* { dg-warning "accessing between 1 and 4 bytes at offsets 0 and \\\[0, 8] may overlap up to 4 bytes" "strcpy" } */
758 }
759
760 /* Exercise strcpy with destination and/or source of unknown lengthu. */
761
762 void test_strcpy_var (char *d, const char *s)
763 {
764 #undef T
765 #define T(dst, src) do { \
766 if (!LINE || LINE == __LINE__) { \
767 char *pd = (dst); \
768 const char *ps = (src); \
769 strcpy (pd, ps); \
770 sink (pd, ps); \
771 } \
772 } while (0)
773
774 T (d, s);
775
776 T (d, &d[0]); /* { dg-warning "source argument is the same as destination" "strcpy" } */
777 T (&d[0], d); /* { dg-warning "source argument is the same as destination" "strcpy" } */
778
779 s = d;
780 T (d, s); /* { dg-warning "source argument is the same as destination" "strcpy" } */
781
782 /* The following overlaps if *s is not nul. It arguably should be
783 diagnosed. */
784 T (d, d + 1);
785
786 /* The following overlaps if strlen (d) is greater than 1. Like
787 the above, it possibly should be diagnosed too. */
788 int r = SR (2, 3);
789 T (d, d + r);
790
791 /* The following overlaps only if strlen (s + n) >= n so it's not
792 diagnosed. */
793 s = d + signed_value ();
794 T (d, s);
795 }
796
797 /* Exercise strncpy with constant or known arguments. */
798
799 void test_strncpy_cst (void)
800 {
801 #undef T
802 #define T(init, dst, src, size) do { \
803 if (!LINE || LINE == __LINE__) { \
804 char a[9] = init; \
805 char *pd = (dst); \
806 const char *ps = (src); \
807 strncpy (pd, ps, (size)); \
808 sink (a, pd, ps); \
809 } \
810 } while (0)
811
812 T ("012", a, a, 0);
813 T ("012", a, a, 1); /* { dg-warning "source argument is the same as destination " "strncpy" } */
814
815 T ("012", a, a + 1, 1);
816 T ("012", a, a + 1, 2); /* { dg-warning "accessing 2 bytes at offsets 0 and 1 overlaps 1 byte at offset 1" "strncpy" } */
817 T ("012", a, a + 1, 3); /* { dg-warning "accessing 3 bytes at offsets 0 and 1 overlaps 2 bytes at offset 1" "strncpy" } */
818 T ("012", a, a + 1, 4); /* { dg-warning "accessing 4 bytes at offsets 0 and 1 overlaps 3 bytes at offset 1" "strncpy" } */
819 T ("012", a, a + 1, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and 1 overlaps 3 bytes at offset 1" "strncpy" } */
820 T ("012", a, a + 1, 6); /* { dg-warning "accessing 6 bytes at offsets 0 and 1 overlaps 3 bytes at offset 1" "strncpy" } */
821
822 T ("012", a, a + 2, 1);
823 T ("012", a, a + 2, 2);
824 /* The third written byte (nul) overwrites a[2]. */
825 T ("012", a, a + 2, 3); /* { dg-warning "accessing 3 bytes at offsets 0 and 2 overlaps 1 byte at offset 2" "strncpy" } */
826 T ("012", a, a + 2, 4); /* { dg-warning "accessing 4 bytes at offsets 0 and 2 overlaps 2 bytes at offset 2" "strncpy" } */
827 T ("012", a, a + 2, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and 2 overlaps 2 bytes at offset 2" "strncpy" } */
828
829 T ("0123", a, a + 2, 1);
830 T ("0123", a, a + 2, 2);
831 /* The terminating nul written to a[2] overwrites s[0]. */
832 T ("0123", a, a + 2, 3); /* { dg-warning "accessing 3 bytes at offsets 0 and 2 overlaps 1 byte at offset 2" "strncpy" } */
833 T ("0123", a, a + 2, 4); /* { dg-warning "accessing 4 bytes at offsets 0 and 2 overlaps 2 bytes at offset 2" "strncpy" } */
834 T ("0123", a, a + 2, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and 2 overlaps 3 bytes at offset 2" "strncpy" } */
835 T ("0123", a, a + 2, 6); /* { dg-warning "accessing 6 bytes at offsets 0 and 2 overlaps 3 bytes at offset 2" "strncpy" } */
836
837 T ("01234", a, a + 2, 1);
838 T ("01234", a, a + 2, 2);
839 T ("01234", a, a + 2, 3); /* { dg-warning "accessing 3 bytes at offsets 0 and 2 overlaps 1 byte at offset 2" "strncpy" } */
840 /* The '5' copied from s[2] to d[2] overwrites s[0]. */
841 T ("01234", a, a + 2, 4); /* { dg-warning "accessing 4 bytes at offsets 0 and 2 overlaps 2 bytes at offset 2" "strncpy" } */
842 T ("01234", a, a + 2, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and 2 overlaps 3 bytes at offset 2" "strncpy" } */
843 }
844
845
846 /* Exercise strncpy with one or more arguments in a determinate range. */
847
848 void test_strncpy_range (char *d, size_t n)
849 {
850 #undef T
851 #define T(init, dst, src, size) do { \
852 if (!LINE || LINE == __LINE__) { \
853 char a[9] = init; \
854 strncpy ((dst), (src), (size)); \
855 sink (a, (dst), (src)); \
856 } \
857 } while (0)
858
859 ptrdiff_t i;
860
861 i = SR (0, 1);
862 T ("0123", a, a + i, 0);
863 T ("0123", a, a + i, 1);
864 /* Offset in the range [0, i] is represented as a PHI (&a, &a + i)
865 that the implementation isn't equipped to handle yet. */
866 T ("0123", a, a + i, 2); /* { dg-warning "accessing 2 bytes at offsets 0 and \\\[0, 1] may overlap 1 byte at offset 1" "strncpy" { xfail *-*-* } } */
867
868 i = SR (1, 5);
869 T ("0123", a, a + i, 0);
870 T ("0123", a, a + i, 1);
871 T ("0123", a, a + i, 2); /* { dg-warning "accessing 2 bytes at offsets 0 and \\\[1, 5] may overlap 1 byte at offset 1" "strncpy" } */
872 T ("0123", a, a + i, 3); /* { dg-warning "accessing 3 bytes at offsets 0 and \\\[1, 5] may overlap up to 2 bytes at offset \\\[1, 2]" "strncpy" } */
873 T ("0123", a, a + i, 4); /* { dg-warning "accessing 4 bytes at offsets 0 and \\\[1, 5] may overlap up to 3 bytes at offset \\\[1, 3]" "strncpy" } */
874 T ("0123", a, a + i, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[1, 5] may overlap up to 4 bytes at offset \\\[1, 4]" "strncpy" } */
875
876 i = SR (2, 5);
877 T ("0123", a, a + i, 0);
878 T ("0123", a, a + i, 1);
879 T ("0123", a, a + i, 2);
880 T ("0123", a, a + i, 3); /* { dg-warning "accessing 3 bytes at offsets 0 and \\\[2, 5] may overlap 1 byte at offset 2" "strncpy" } */
881 T ("0123", a, a + i, 4); /* { dg-warning "accessing 4 bytes at offsets 0 and \\\[2, 5] may overlap up to 2 bytes at offset \\\[2, 3]" "strncpy" } */
882 T ("0123", a, a + i, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[2, 5] may overlap up to 3 bytes at offset \\\[2, 4]" "strncpy" } */
883 /* When i == 5 the following overlaps at least 1 byte: the nul at a[5]
884 (if a + 5 is the empty string). If a + 5 is not empty then it overlaps
885 it plus as many non-nul characters after it, up to the total of 6. */
886 T ("0123", a, a + i, 6); /* { dg-warning "accessing 6 bytes at offsets 0 and \\\[2, 5] overlaps between 1 and 3 bytes at offset \\\[2, 5]" "strncpy" } */
887
888 i = SR (3, 5);
889 T ("0123", a, a + i, 0);
890 T ("0123", a, a + i, 1);
891 T ("0123", a, a + i, 2);
892 T ("0123", a, a + i, 3);
893 T ("0123", a, a + i, 4); /* { dg-warning "accessing 4 bytes at offsets 0 and \\\[3, 5] may overlap 1 byte at offset 3" "strncpy" } */
894 T ("0123", a, a + i, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[3, 5] may overlap up to 2 bytes at offset \\\[3, 4]" "strncpy" } */
895
896 /* The following copy overlaps at most 2 bytes. When i == 3 it overlaps
897 the 2 bytes at "3", when i == 4 just the final nul. When i == 5 it
898 also overlaps 1 byte, the nul at a[5]. Although the overlap offset
899 range suggests the overlap is up to three bytes, it correctly reflects
900 the union of the two cases. */
901 T ("0123", a, a + i, 6); /* { dg-warning "accessing 6 bytes at offsets 0 and \\\[3, 5] overlaps between 1 and 2 bytes at offset \\\[3, 5]" "strncpy" } */
902
903 i = SR (4, 5);
904 T ("0123", a, a + i, 0);
905 T ("0123", a, a + i, 1);
906 T ("0123", a, a + i, 2);
907 T ("0123", a, a + i, 3);
908 T ("0123", a, a + i, 4);
909 T ("0123", a, a + i, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[4, 5] may overlap 1 byte at offset 4" "strncpy" } */
910 /* Regardless of the value of i, the following overlaps exactlty
911 one byte: the nul at a[4]. There is no overlap at a[5] because
912 the source is not read past the nul so the offset below isn't
913 entirely correct. */
914 T ("0123", a, a + i, 6); /* { dg-warning "accessing 6 bytes at offsets 0 and \\\[4, 5] overlaps 1 byte at offset \\\[4, 5]" "strncpy" } */
915
916 /* Verify offset and size both in some range. The strncpy checking
917 is more strict than that of memcpy and triggers even when the
918 overlap is possible but not inevitable. The following overlaps
919 like so ('*' denotes the terminating NUL, '.' the appended NUL
920 that's not copied from the source):
921 a: 01234567* (also indicates offset)
922 i = 4: 4567 none
923 4567* overlaps 1 at offset 4
924 4567*. overlaps 2 at offset 4
925 i = 5: 567* none
926 567*. none
927 567*.. overlaps 1 at offset 5 */
928 T ("01234567", a, a + i, UR (4, 6)); /* { dg-warning "accessing between 4 and 6 bytes at offsets 0 and \\\[4, 5] may overlap up to 2 bytes at offset \\\[4, 5]" "strncpy" } */
929
930 /* Ditto for objects of unknown sizes. */
931 T ("01234567", d, d + i, UR (4, 6)); /* { dg-warning "accessing between 4 and 6 bytes at offsets 0 and \\\[4, 5] may overlap up to 2 bytes at offset \\\[4, 5]" "strncpy" } */
932
933 T ("01234567", a, a + i, UR (6, 7)); /* { dg-warning "accessing between 6 and 7 bytes at offsets 0 and \\\[4, 5] overlaps between 1 and 3 bytes at offset \\\[4, 5]" "strncpy" } */
934
935 /* The following overlaps except in the unlikely case that value ()
936 is zero, so it's diagnosed. */
937 T ("012", a, a, n); /* { dg-warning "\\\[-Wrestrict]" "strncpy" } */
938 }
939
940
941 /* Exercise strncpy with destination and source of unknown length. */
942
943 void test_strncpy_var (char *d, const char *s, size_t n)
944 {
945 #undef T
946 #define T(dst, src, size) do { \
947 if (!LINE || LINE == __LINE__) { \
948 char *pd = (dst); \
949 const char *ps = (src); \
950 strncpy (pd, ps, (size)); \
951 sink (pd, ps); \
952 } \
953 } while (0)
954
955 T (d, s, 1);
956 T (d, s, n);
957
958 T (d, d, 1); /* { dg-warning "\\\[-Wrestrict" "strncpy" } */
959 T (d, d, n); /* { dg-warning "\\\[-Wrestrict" "strncpy" } */
960
961 T (d, d + 1, 1);
962 T (d, d + 1, 2); /* { dg-warning "\\\[-Wrestrict" "strncpy" } */
963 T (d + 1, d, 1);
964 T (d + 1, d, 2); /* { dg-warning "\\\[-Wrestrict" "strncpy" } */
965 }
966
967 struct MemberArrays
968 {
969 char a[7];
970 char b[8];
971 char c[9];
972 };
973
974 void test_strncpy_strcpy_var (struct MemberArrays *ar, const char *s)
975 {
976 /* The following is safe and should not trigger a warning. */
977 strncpy (ar->b, s, sizeof ar->b - 1);
978 ar->b[sizeof ar->b - 1] = '\0';
979 strcpy (ar->a, ar->b);
980 sink (ar);
981
982 /* The following is not as safe (it might overflow ar->a) but there
983 is no overlap so it also shouldn't trigger -Wrestrict. */
984 strncpy (ar->c, s, sizeof ar->c - 1);
985 ar->c[sizeof ar->c - 1] = '\0';
986 strcpy (ar->a, ar->c);
987 sink (ar);
988 }