1 /* Test exercising buffer overflow warnings emitted for raw memory and
2 string manipulation builtins involving ranges of sizes and strings
3 of varying lengths. */
4 /* { dg-do compile } */
5 /* { dg-options "-O2 -ftrack-macro-expansion=0" } */
6
7 #define INT_MAX __INT_MAX__
8 #define PTRDIFF_MAX __PTRDIFF_MAX__
9 #define SIZE_MAX __SIZE_MAX__
10
11 typedef __PTRDIFF_TYPE__ ptrdiff_t;
12 typedef __SIZE_TYPE__ size_t;
13
14 static const size_t ssize_max = SIZE_MAX / 2;
15 static const size_t size_max = SIZE_MAX;
16
17 extern signed char schar_val;
18 extern signed short sshrt_val;
19 extern signed int sint_val;
20 extern signed long slong_val;
21 extern unsigned char uchar_val;
22 extern unsigned short ushrt_val;
23 extern unsigned int uint_val;
24 extern unsigned long ulong_val;
25
26 #define memcpy(d, s, n) (memcpy ((d), (s), (n)), sink ((d)))
27 extern void* (memcpy)(void*, const void*, size_t);
28
29 #define mempcpy(d, s, n) (mempcpy ((d), (s), (n)), sink ((d)))
30 extern void* (mempcpy)(void*, const void*, size_t);
31
32 #define memset(d, c, n) (memset ((d), (c), (n)), sink ((d)))
33 extern void* (memset)(void*, int, size_t);
34
35 #define bzero(d, n) (bzero ((d), (n)), sink ((d)))
36 extern void (bzero)(void*, size_t);
37
38 #define strcat(d, s) (strcat ((d), (s)), sink ((d)))
39 extern char* (strcat)(char*, const char*);
40
41 #define strncat(d, s, n) (strncat ((d), (s), (n)), sink ((d)))
42 extern char* (strncat)(char*, const char*, size_t);
43
44 #define strcpy(d, s) (strcpy ((d), (s)), sink ((d)))
45 extern char* (strcpy)(char*, const char*);
46
47 #define strncpy(d, s, n) (strncpy ((d), (s), (n)), sink ((d)))
48 extern char* (strncpy)(char*, const char*, size_t);
49
50 void sink (void*);
51
52 /* Function to "generate" a random number each time it's called. Declared
53 (but not defined) and used to prevent GCC from making assumptions about
54 their values based on the variables uses in the tested expressions. */
55 size_t random_unsigned_value (void);
56 ptrdiff_t random_signed_value (void);
57
58 /* Return a random unsigned value between MIN and MAX. */
59
60 static inline size_t
unsigned_range(size_t min,size_t max)61 unsigned_range (size_t min, size_t max)
62 {
63 const size_t val = random_unsigned_value ();
64 return val < min || max < val ? min : val;
65 }
66
67 /* Return a random signed value between MIN and MAX. */
68
69 static inline ptrdiff_t
signed_range(ptrdiff_t min,ptrdiff_t max)70 signed_range (ptrdiff_t min, ptrdiff_t max)
71 {
72 const ptrdiff_t val = random_signed_value ();
73 return val < min || max < val ? min : val;
74 }
75
76 /* For brevity. */
77 #define UR(min, max) unsigned_range (min, max)
78 #define SR(min, max) signed_range (min, max)
79
80 /* Return a pointer to constant string whose length is at least MINLEN
81 and at most 10. */
82 #define S(minlen) \
83 (minlen == random_unsigned_value () \
84 ? "0123456789" + 10 - minlen : "0123456789")
85
86 /* Test memcpy with a number of bytes bounded by a known range. */
87
test_memcpy_range(void * d,const void * s)88 void test_memcpy_range (void *d, const void *s)
89 {
90 char buf[5];
91
92 memcpy (buf, s, UR (0, 5));
93 memcpy (buf, s, UR (1, 5));
94 memcpy (buf, s, UR (2, 5));
95 memcpy (buf, s, UR (3, 5));
96 memcpy (buf, s, UR (4, 5));
97
98 memcpy (buf, s, UR (6, 7)); /* { dg-warning "writing between 6 and 7 bytes into a region of size 5 overflows the destination" } */
99
100 memcpy (buf + 5, s, UR (1, 2)); /* { dg-warning "writing between 1 and 2 bytes into a region of size 0 overflows the destination" } */
101
102 memcpy (buf + size_max, s, UR (1, 2)); /* { dg-warning "writing between 1 and 2 bytes into a region of size 0 overflows the destination" "excessive pointer offset" { xfail *-*-* } } */
103
104 memcpy (buf, s, UR (ssize_max, size_max)); /* { dg-warning "writing \[0-9\]+ or more bytes into a region of size 5 overflows the destination" } */
105 memcpy (buf, s, UR (ssize_max + 1, size_max)); /* { dg-warning "specified size between \[0-9\]+ and \[0-9\]+ exceeds maximum object size" } */
106 memcpy (buf, s, UR (size_max - 1, size_max)); /* { dg-warning "specified size between \[0-9\]+ and \[0-9\]+ exceeds maximum object size" } */
107
108 /* Exercise memcpy into a destination of unknown size with excessive
109 number of bytes. */
110 memcpy (d, s, UR (ssize_max, size_max));
111 memcpy (d, s, UR (ssize_max + 1, size_max)); /* { dg-warning "specified size between \[0-9\]+ and \[0-9\]+ exceeds maximum object size" } */
112
113 memcpy (buf, s, SR (-1, 1));
114 memcpy (buf, s, SR (-3, 2));
115 memcpy (buf, s, SR (-5, 3));
116 memcpy (buf, s, SR (-7, 4));
117 memcpy (buf, s, SR (-9, 5));
118 memcpy (buf, s, SR (-11, 6));
119
120 memcpy (d, s, SR (-1, 1));
121 memcpy (d, s, SR (-3, 2));
122 memcpy (d, s, SR (-5, 3));
123 memcpy (d, s, SR (-7, 4));
124 memcpy (d, s, SR (-9, 5));
125 memcpy (d, s, SR (-11, 6));
126
127 memcpy (buf, s, SR (-2, -1)); /* { dg-warning "specified size between \[0-9\]+ and \[0-9\]+ exceeds maximum object size" } */
128 memcpy (d, s, SR (-2, -1)); /* { dg-warning "specified size between \[0-9\]+ and \[0-9\]+ exceeds maximum object size" } */
129
130 /* Even though the following calls are bounded by the range of N's
131 type they must not cause a warning for obvious reasons. */
132 memcpy (buf, s, schar_val);
133 memcpy (buf, s, sshrt_val);
134 memcpy (buf, s, sint_val);
135 memcpy (buf, s, slong_val);
136
137 memcpy (buf, s, uchar_val);
138 memcpy (buf, s, ushrt_val);
139 memcpy (buf, s, uint_val);
140 memcpy (buf, s, ulong_val);
141
142 memcpy (buf, s, schar_val + 1);
143 memcpy (buf, s, sshrt_val + 2);
144 memcpy (buf, s, sint_val + 3);
145 memcpy (buf, s, slong_val + 4);
146
147 memcpy (d, s, uchar_val + 5);
148 memcpy (d, s, ushrt_val + 6);
149 memcpy (d, s, uint_val + 7);
150 memcpy (d, s, ulong_val + 8);
151
152 memcpy (d, s, schar_val);
153 memcpy (d, s, sshrt_val);
154 memcpy (d, s, sint_val);
155 memcpy (d, s, slong_val);
156
157 memcpy (d, s, uchar_val);
158 memcpy (d, s, ushrt_val);
159 memcpy (d, s, uint_val);
160 memcpy (d, s, ulong_val);
161
162 memcpy (d, s, schar_val + 1);
163 memcpy (d, s, sshrt_val + 2);
164 memcpy (d, s, sint_val + 3);
165 memcpy (d, s, slong_val + 4);
166
167 memcpy (d, s, uchar_val + 5);
168 memcpy (d, s, ushrt_val + 6);
169 memcpy (d, s, uint_val + 7);
170 memcpy (d, s, ulong_val + 8);
171 }
172
173 /* Test mempcpy with a number of bytes bounded by a known range. */
174
test_mempcpy_range(void * d,const void * s)175 void test_mempcpy_range (void *d, const void *s)
176 {
177 char buf[5];
178
179 mempcpy (buf, s, UR (0, 5));
180 mempcpy (buf, s, UR (1, 5));
181 mempcpy (buf, s, UR (2, 5));
182 mempcpy (buf, s, UR (3, 5));
183 mempcpy (buf, s, UR (4, 5));
184
185 mempcpy (buf, s, UR (6, 7)); /* { dg-warning "writing between 6 and 7 bytes into a region of size 5 overflows the destination" } */
186
187 mempcpy (buf, s, UR (6, 7)); /* { dg-warning "writing between 6 and 7 bytes into a region of size 5 overflows the destination" } */
188
189 mempcpy (buf, s, UR (ssize_max, size_max)); /* { dg-warning "writing \[0-9\]+ or more bytes into a region of size 5 overflows the destination" } */
190 mempcpy (buf, s, UR (ssize_max + 1, size_max)); /* { dg-warning "specified size between \[0-9\]+ and \[0-9\]+ exceeds maximum object size" } */
191 mempcpy (buf, s, UR (size_max - 1, size_max)); /* { dg-warning "specified size between \[0-9\]+ and \[0-9\]+ exceeds maximum object size" } */
192
193 /* Exercise mempcpy into a destination of unknown size with excessive
194 number of bytes. */
195 mempcpy (d, s, UR (ssize_max, size_max));
196 mempcpy (d, s, UR (ssize_max + 1, size_max)); /* { dg-warning "specified size between \[0-9\]+ and \[0-9\]+ exceeds maximum object size" } */
197 }
198
199 /* Test memset with a number of bytes bounded by a known range. */
200
test_memset_range(void * d)201 void test_memset_range (void *d)
202 {
203 char buf[5];
204
205 memset (buf, 0, UR (0, 5));
206 memset (buf, 0, UR (1, 5));
207 memset (buf, 0, UR (2, 5));
208 memset (buf, 0, UR (3, 5));
209 memset (buf, 0, UR (4, 5));
210
211 memset (buf, 0, UR (6, 7)); /* { dg-warning "writing between 6 and 7 bytes into a region of size 5 overflows the destination" } */
212
213 memset (buf, 0, UR (6, 7)); /* { dg-warning "writing between 6 and 7 bytes into a region of size 5 overflows the destination" } */
214
215 memset (buf, 0, UR (ssize_max, size_max)); /* { dg-warning "writing \[0-9\]+ or more bytes into a region of size 5 overflows the destination" } */
216 memset (buf, 0, UR (ssize_max + 1, size_max)); /* { dg-warning "specified size between \[0-9\]+ and \[0-9\]+ exceeds maximum object size" } */
217 memset (buf, 0, UR (size_max - 1, size_max)); /* { dg-warning "specified size between \[0-9\]+ and \[0-9\]+ exceeds maximum object size" } */
218
219 /* Exercise memset into a destination of unknown size with excessive
220 number of bytes. */
221 memset (d, 0, UR (ssize_max, size_max));
222 memset (d, 0, UR (ssize_max + 1, size_max)); /* { dg-warning "specified size between \[0-9\]+ and \[0-9\]+ exceeds maximum object size" } */
223 }
224
225 /* Test bzero with a number of bytes bounded by a known range. */
226
test_bzero_range(void * d)227 void test_bzero_range (void *d)
228 {
229 char buf[5];
230
231 bzero (buf, UR (0, 5));
232 bzero (buf, UR (1, 5));
233 bzero (buf, UR (2, 5));
234 bzero (buf, UR (3, 5));
235 bzero (buf, UR (4, 5));
236
237 bzero (buf, UR (6, 7)); /* { dg-warning "writing between 6 and 7 bytes into a region of size 5 overflows the destination" } */
238
239 bzero (buf, UR (6, 7)); /* { dg-warning "writing between 6 and 7 bytes into a region of size 5 overflows the destination" } */
240
241 bzero (buf, UR (ssize_max, size_max)); /* { dg-warning "writing \[0-9\]+ or more bytes into a region of size 5 overflows the destination" } */
242 bzero (buf, UR (ssize_max + 1, size_max)); /* { dg-warning "specified size between \[0-9\]+ and \[0-9\]+ exceeds maximum object size" } */
243 bzero (buf, UR (size_max - 1, size_max)); /* { dg-warning "specified size between \[0-9\]+ and \[0-9\]+ exceeds maximum object size" } */
244
245 /* Exercise bzero into a destination of unknown size with excessive
246 number of bytes. */
247 bzero (d, UR (ssize_max, size_max));
248 bzero (d, UR (ssize_max + 1, size_max)); /* { dg-warning "specified size between \[0-9\]+ and \[0-9\]+ exceeds maximum object size" } */
249 }
250
251 /* Test strcat with an argument referencing a non-constant string of
252 lengths in a known range. */
253
test_strcat_range(void)254 void test_strcat_range (void)
255 {
256 char buf[5] = "";
257
258 strcat (buf, S (0));
259 strcat (buf, S (1));
260 strcat (buf, S (2));
261 strcat (buf, S (3));
262 strcat (buf, S (4));
263 strcat (buf, S (5)); /* { dg-warning "writing between 6 and 11 bytes into a region of size 5 " } */
264
265 {
266 /* The implementation of the warning isn't smart enough to determine
267 the length of the string in the buffer so it assumes it's empty
268 and issues the warning basically for the same cases as strcat. */
269 char buf2[5] = "12";
270 strcat (buf2, S (4)); /* { dg-warning "writing 5 bytes into a region of size 3" "strcat to a non-empty string" { xfail *-*-* } } */
271 }
272 }
273
274 /* Verify that strcpy with an unknown source string doesn't cause
275 warnings unless the destination has zero size. */
276
test_strcpy(const char * src)277 void test_strcpy (const char *src)
278 {
279 struct A { char a[2]; char b[3]; } a;
280
281 strcpy (a.a, src);
282 strcpy (a.a + 1, src);
283
284 /* There must be enough room in the destination for the terminating
285 nul, otherwise verify that a warning is issued.
286 The following works as expected with __builtin___strcpy_chk and
287 __builtin_object_size because they see that the offset is from
288 the a.a array. When optimization is enabled, it isn't detected
289 by __bultin_strcpy (when __builtin_object_size isn't called
290 explicitly) because by the time it's seen the offset has been
291 transformed to one from the beginning of the whole object, i.e.,
292 as if it had been written as (char*)&a + 2 . Then the destination
293 size is taken to be the rest of the whole object. It is detected
294 by __builtin_strcpy when optimization is not enabled because then
295 the &a.a + 2 expression is preserved. But without optimization
296 an ordinary call to strcpy isn't transformed to __builtin_strcpy
297 and so it can't be detected here (since the rest of the test
298 relies on optimization). */
299 strcpy (a.a + 2, src); /* { dg-warning "writing at least 1 byte into a region of size 0 " "strcpy into empty substring" { xfail *-*-* } } */
300
301 /* This does work. */
302 strcpy (a.a + 5, src); /* { dg-warning "writing 1 or more bytes into a region of size 0 " } */
303
304 /* As does this. */
305 strcpy (a.a + 17, src); /* { dg-warning "writing 1 or more bytes into a region of size 0 " } */
306 }
307
308 /* Test strcpy with a non-constant source string of length in a known
309 range. */
310
test_strcpy_range(void)311 void test_strcpy_range (void)
312 {
313 char buf[5];
314
315 strcpy (buf, S (0));
316 strcpy (buf, S (1));
317 strcpy (buf, S (2));
318 strcpy (buf, S (4));
319 strcpy (buf, S (5)); /* { dg-warning "writing between 6 and 11 bytes into a region of size 5 " } */
320 strcpy (buf, S (6)); /* { dg-warning "writing between 7 and 11 bytes" } */
321 strcpy (buf, S (7)); /* { dg-warning "writing between 8 and 11 bytes" } */
322 strcpy (buf, S (8)); /* { dg-warning "writing between 9 and 11 bytes" } */
323 strcpy (buf, S (9)); /* { dg-warning "writing between 10 and 11 bytes" } */
324 strcpy (buf, S (10)); /* { dg-warning "writing 11 bytes" } */
325
326 strcpy (buf + 5, S (0)); /* { dg-warning "writing between 1 and 11 bytes" } */
327
328 strcpy (buf + 17, S (0)); /* { dg-warning "writing between 1 and 11 bytes " } */
329 }
330
331 /* Test strncat with an argument referencing a non-constant string of
332 lengths in a known range. */
333
test_strncat_range(void)334 void test_strncat_range (void)
335 {
336 char buf[5] = "";
337
338 strncat (buf, S (0), 0);
339 strncat (buf, S (0), 1);
340 strncat (buf, S (0), 2);
341 strncat (buf, S (0), 3);
342 strncat (buf, S (0), 4);
343
344 strncat (buf + 5, S (0), 0);
345
346 strncat (buf + 5, S (0), 1); /* { dg-warning "specified bound 1 exceeds destination size 0" } */
347 strncat (buf + 5, S (1), 1); /* { dg-warning "specified bound 1 exceeds destination size 0" } */
348
349 /* Strncat always appends a terminating null after copying the N
350 characters so the following triggers a warning pointing out
351 that specifying sizeof(buf) as the upper bound may cause
352 the nul to overflow the destination. */
353 strncat (buf, S (0), 5); /* { dg-warning "specified bound 5 equals destination size" } */
354 strncat (buf, S (0), 6); /* { dg-warning "specified bound 6 exceeds destination size 5" } */
355
356 strncat (buf, S (1), 0);
357 strncat (buf, S (1), 1);
358 strncat (buf, S (1), 2);
359 strncat (buf, S (1), 3);
360 strncat (buf, S (1), 4);
361 strncat (buf, S (1), 5); /* { dg-warning "specified bound 5 equals destination size" } */
362 strncat (buf, S (1), 6); /* { dg-warning "specified bound 6 exceeds destination size 5" } */
363 strncat (buf, S (2), 6); /* { dg-warning "specified bound 6 exceeds destination size 5" } */
364
365 /* The following could just as well say "writing 6 bytes into a region
366 of size 5. Either would be correct and probably equally as clear
367 in this case. But when the length of the source string is not known
368 at all then the bound warning seems clearer. */
369 strncat (buf, S (5), 6); /* { dg-warning "specified bound 6 exceeds destination size 5" } */
370 strncat (buf, S (7), 6); /* { dg-warning "specified bound 6 exceeds destination size 5" } */
371
372 {
373 /* The implementation of the warning isn't smart enough to determine
374 the length of the string in the buffer so it assumes it's empty
375 and issues the warning basically for the same cases as strncpy. */
376 char buf2[5] = "12";
377 strncat (buf2, S (4), 4); /* { dg-warning "writing 5 bytes into a region of size 3" "strncat to a non-empty string" { xfail *-*-* } } */
378 }
379 }
380
381 /* Test strncat_chk with an argument referencing a non-constant string
382 of lengths in a known range. */
383
test_strncat_chk_range(char * d)384 void test_strncat_chk_range (char *d)
385 {
386 char buf[5] = "";
387
388 #define strncat_chk(d, s, n) \
389 __builtin___strncat_chk ((d), (s), (n), __builtin_object_size (d, 1));
390
391 strncat_chk (buf, S (0), 1);
392 strncat_chk (buf, S (0), 2);
393 strncat_chk (buf, S (0), 3);
394 strncat_chk (buf, S (0), 4);
395 strncat_chk (buf, S (0), 5); /* { dg-warning "specified bound 5 equals destination size" } */
396
397 strncat_chk (buf, S (5), 1);
398 strncat_chk (buf, S (5), 2);
399 strncat_chk (buf, S (5), 3);
400 strncat_chk (buf, S (5), 4);
401 strncat_chk (buf, S (5), 5); /* { dg-warning "specified bound 5 equals destination size" } */
402
403 strncat_chk (buf, S (5), 10); /* { dg-warning "specified bound \[0-9\]+ exceeds destination size 5" } */
404
405 strncat_chk (d, S (5), size_max); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size " } */
406 }
407
408 /* Test strncpy with a non-constant source string of length in a known
409 range and a constant number of bytes. */
410
test_strncpy_string_range(char * d)411 void test_strncpy_string_range (char *d)
412 {
413 char buf[5];
414
415 strncpy (buf, S (0), 0);
416 strncpy (buf, S (0), 1);
417 strncpy (buf, S (0), 2);
418 strncpy (buf, S (0), 3);
419 strncpy (buf, S (0), 4);
420 strncpy (buf, S (0), 5);
421 strncpy (buf, S (0), 6); /* { dg-warning "writing 6 bytes into a region of size 5 " } */
422
423 strncpy (buf, S (6), 4);
424 strncpy (buf, S (7), 5);
425 strncpy (buf, S (8), 6); /* { dg-warning "writing 6 bytes into a region of size 5 " } */
426
427 strncpy (buf, S (1), ssize_max - 1); /* { dg-warning "writing \[0-9\]+ bytes into a region of size 5" } */
428 strncpy (buf, S (2), ssize_max); /* { dg-warning "writing \[0-9\]+ bytes into a region of size 5" } */
429 strncpy (buf, S (3), ssize_max + 1); /* { dg-warning "specified size \[0-9\]+ exceeds maximum object size" } */
430 strncpy (buf, S (4), size_max); /* { dg-warning "specified size \[0-9\]+ exceeds maximum object size" } */
431
432 /* Exercise strncpy into a destination of unknown size with a valid
433 and invalid constant number of bytes. */
434 strncpy (d, S (1), ssize_max - 1);
435 strncpy (d, S (2), ssize_max);
436 strncpy (d, S (3), ssize_max + 1); /* { dg-warning "specified size \[0-9\]+ exceeds maximum object size" } */
437 strncpy (d, S (4), size_max); /* { dg-warning "specified size \[0-9\]+ exceeds maximum object size" } */
438 }
439
440 /* Test strncpy with a non-constant source string of length in a known
441 range and a non-constant number of bytes also in a known range. */
442
test_strncpy_string_count_range(char * dst,const char * src)443 void test_strncpy_string_count_range (char *dst, const char *src)
444 {
445 char buf[5];
446
447 strncpy (buf, S (0), UR (0, 1));
448 strncpy (buf, S (0), UR (0, 2));
449 strncpy (buf, S (0), UR (0, 3));
450 strncpy (buf, S (0), UR (0, 4));
451 strncpy (buf, S (0), UR (0, 5));
452 strncpy (buf, S (0), UR (0, 6));
453 strncpy (buf, S (0), UR (1, 6));
454 strncpy (buf, S (0), UR (2, 6));
455 strncpy (buf, S (0), UR (3, 6));
456 strncpy (buf, S (0), UR (4, 6));
457 strncpy (buf, S (0), UR (5, 6));
458
459 strncpy (buf, S (9), UR (0, 1));
460 strncpy (buf, S (8), UR (0, 2));
461 strncpy (buf, S (7), UR (0, 3));
462 strncpy (buf, S (6), UR (0, 4));
463 strncpy (buf, S (8), UR (0, 5));
464 strncpy (buf, S (7), UR (0, 6));
465 strncpy (buf, S (6), UR (1, 6));
466 strncpy (buf, S (5), UR (2, 6));
467 strncpy (buf, S (9), UR (3, 6));
468 strncpy (buf, S (8), UR (4, 6));
469 strncpy (buf, S (7), UR (5, 6));
470
471 strncpy (buf, S (0), UR (6, 7)); /* { dg-warning "writing between 6 and 7 bytes into a region of size 5 " } */
472 strncpy (buf, S (1), UR (7, 8)); /* { dg-warning "writing between 7 and 8 bytes into a region of size 5 " } */
473 strncpy (buf, S (2), UR (ssize_max, ssize_max + 1)); /* { dg-warning "writing \[0-9\]+ or more bytes into a region of size 5 " } */
474
475 strncpy (buf, S (2), UR (ssize_max + 1, ssize_max + 2)); /* { dg-warning "specified size between \[0-9\]+ and \[0-9\]+ exceeds maximum object size" } */
476
477 strncpy (buf + 5, S (0), UR (0, 1));
478 strncpy (buf + 5, S (1), UR (0, 1));
479 strncpy (buf + 5, S (0), UR (1, 2)); /* { dg-warning "writing between 1 and 2 bytes into a region of size 0 " } */
480 strncpy (buf + 5, S (1), UR (1, 2)); /* { dg-warning "writing between 1 and 2 bytes into a region of size 0 " } */
481
482 strncpy (buf, src, UR (0, 1));
483 strncpy (buf, src, UR (0, 2));
484 strncpy (buf, src, UR (0, 3));
485 strncpy (buf, src, UR (0, 4));
486 strncpy (buf, src, UR (0, 5));
487 strncpy (buf, src, UR (0, 6));
488 strncpy (buf, src, UR (1, 6));
489 strncpy (buf, src, UR (2, 6));
490 strncpy (buf, src, UR (3, 6));
491 strncpy (buf, src, UR (4, 6));
492 strncpy (buf, src, UR (5, 6));
493 strncpy (buf, src, UR (6, 7)); /* { dg-warning "writing between 6 and 7 bytes into a region of size 5 " } */
494
495 /* Exercise strncpy into a destination of unknown size with a valid
496 and invalid constant number of bytes. */
497 strncpy (dst, S (0), UR (5, 6));
498 strncpy (dst, S (1), UR (6, 7));
499 strncpy (dst, S (2), UR (7, 8));
500
501 strncpy (dst, S (3), UR (ssize_max, ssize_max + 1));
502
503 strncpy (dst, S (4), UR (ssize_max + 1, ssize_max + 2)); /* { dg-warning "specified size between \[0-9\]+ and \[0-9\]+ exceeds maximum object size" } */
504 }
505