1 /* Test to exercise warnings when an array declared with attribute "nonstring"
2 is passed to a function that expects a nul-terminated string as an argument.
3 { dg-do compile }
4 { dg-options "-O2 -Wattributes -Wstringop-overflow -ftrack-macro-expansion=0" } */
5
6 typedef __SIZE_TYPE__ size_t;
7 typedef __builtin_va_list va_list;
8
9 #if __cplusplus
10 extern "C" {
11 #endif
12
13 void* memchr (const void*, int, size_t);
14 int memcmp (const void*, const void*, size_t);
15 void* memcpy (void*, const void*, size_t);
16 void* memmove (void*, const void*, size_t);
17
18 int printf (const char*, ...);
19 int puts (const char*);
20 int puts_unlocked (const char*);
21 int sprintf (char*, const char*, ...);
22 int snprintf (char*, size_t, const char*, ...);
23 int vsprintf (char*, const char*, va_list);
24 int vsnprintf (char*, size_t, const char*, va_list);
25
26 int strcmp (const char*, const char*);
27 int strncmp (const char*, const char*, size_t);
28
29 char* stpcpy (char*, const char*);
30 char* stpncpy (char*, const char*, size_t);
31
32 char* strcat (char*, const char*);
33 char* strncat (char*, const char*, size_t);
34
35 char* strcpy (char*, const char*);
36 char* strncpy (char*, const char*, size_t);
37
38 char* strchr (const char*, int);
39 char* strdup (const char*);
40 size_t strlen (const char*);
41 size_t strnlen (const char*, size_t);
42 char* strndup (const char*, size_t);
43
44 #if __cplusplus
45 } /* extern "C" */
46 #endif
47
48 #define NONSTRING __attribute__ ((nonstring))
49
50 /* STR needs to be bigger than ARR to trigger warnings, otherwise
51 since STR must be a string, using both in a string function
52 can be assumed to be safe even if ARR isn't nul-terminated. */
53 char str[5];
54 char arr[4] NONSTRING;
55
56 char *ptr;
57 char *parr NONSTRING;
58
59 struct MemArrays
60 {
61 char str[5];
62 char arr[4] NONSTRING;
63 char *parr NONSTRING;
64 };
65
66 void sink (int, ...);
67
68
69 #define T(call) sink (0, call)
70
71 void test_printf (struct MemArrays *p)
72 {
73 T (printf (str));
74 T (printf (arr)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
75
76 T (printf (ptr));
77 T (printf (parr)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
78
79 T (printf (p->str));
80 T (printf (p->arr)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
81 }
82
83
84 void test_puts (struct MemArrays *p)
85 {
86 T (puts (str));
87 T (puts (arr)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
88
89 T (puts (ptr));
90 T (puts (parr)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
91
92 T (puts (p->str));
93 T (puts (p->arr)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
94 }
95
96
97 void test_snprintf (char *d, size_t n, struct MemArrays *p)
98 {
99 T (snprintf (d, n, str));
100 T (snprintf (d, n, arr)); /* { dg-warning "argument 3 declared attribute .nonstring." } */
101
102 T (snprintf (d, n, ptr));
103 T (snprintf (d, n, parr)); /* { dg-warning "argument 3 declared attribute .nonstring." } */
104
105 T (snprintf (d, n, p->str));
106 T (snprintf (d, n, p->arr)); /* { dg-warning "argument 3 declared attribute .nonstring." } */
107 }
108
109
110 void test_sprintf (char *d, struct MemArrays *p)
111 {
112 T (sprintf (d, str));
113 T (sprintf (d, arr)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
114
115 T (sprintf (d, ptr));
116 T (sprintf (d, parr)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
117
118 T (sprintf (d, p->str));
119 T (sprintf (d, p->arr)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
120 }
121
122
123 void test_vsnprintf (char *d, size_t n, struct MemArrays *p, va_list va)
124 {
125 T (vsnprintf (d, n, str, va));
126 T (vsnprintf (d, n, arr, va)); /* { dg-warning "argument 3 declared attribute .nonstring." } */
127
128 T (vsnprintf (d, n, ptr, va));
129 T (vsnprintf (d, n, parr, va)); /* { dg-warning "argument 3 declared attribute .nonstring." } */
130
131 T (vsnprintf (d, n, p->str, va));
132 T (vsnprintf (d, n, p->arr, va)); /* { dg-warning "argument 3 declared attribute .nonstring." } */
133 }
134
135
136 void test_vsprintf (char *d, struct MemArrays *p, va_list va)
137 {
138 T (vsprintf (d, str, va));
139 T (vsprintf (d, arr, va)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
140
141 T (vsprintf (d, ptr, va));
142 T (vsprintf (d, parr, va)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
143
144 T (vsprintf (d, p->str, va));
145 T (vsprintf (d, p->arr, va)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
146 }
147
148
149 void test_strcmp (struct MemArrays *p)
150 {
151 T (strcmp (str, str));
152 T (strcmp (str, arr)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
153 T (strcmp (arr, str)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
154
155 T (strcmp (str, ptr));
156 T (strcmp (str, parr)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
157 T (strcmp (parr, str)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
158
159 T (strcmp (p->str, p->arr)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
160 T (strcmp (p->arr, p->str)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
161 T (strcmp (p->parr, p->str)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
162 }
163
164
165 void test_strncmp_warn (struct MemArrays *p)
166 {
167 enum { N = sizeof arr };
168 T (strncmp (str, arr, N));
169 T (strncmp (arr, str, N));
170
171 T (strncmp (str, arr, N + 1)); /* { dg-warning "argument 2 declared attribute .nonstring. is smaller than the specified bound 5" } */
172 T (strncmp (arr, str, N + 1)); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound 5" } */
173
174 T (strncmp (str, parr, N + 1));
175 T (strncmp (parr, str, N + 1));
176
177 T (strncmp (p->str, p->arr, N));
178 T (strncmp (p->arr, p->str, N));
179 T (strncmp (p->parr, p->str, N));
180
181 T (strncmp (p->str, p->arr, N));
182 T (strncmp (p->arr, p->str, N));
183 T (strncmp (p->parr, p->str, N));
184 }
185
186
187 void test_strncmp_nowarn (struct MemArrays *p, size_t n)
188 {
189 T (strncmp (str, str, n));
190 T (strncmp (str, arr, n));
191 T (strncmp (arr, str, n));
192
193 T (strncmp (str, ptr, n));
194 T (strncmp (str, parr, n));
195 T (strncmp (parr, str, n));
196
197 T (strncmp (p->str, p->arr, n));
198 T (strncmp (p->arr, p->str, n));
199 T (strncmp (p->parr, p->str, n));
200 }
201
202
203 void test_stpcpy (struct MemArrays *p)
204 {
205 T (stpcpy (str, str));
206 T (stpcpy (str, arr)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
207 T (stpcpy (arr, str));
208
209 T (stpcpy (str, ptr));
210 T (stpcpy (str, parr)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
211 T (stpcpy (parr, str));
212
213 T (stpcpy (p->str, p->arr)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
214 T (stpcpy (p->arr, p->str));
215 T (stpcpy (p->parr, p->str));
216 }
217
218
219 void test_stpncpy_nowarn (struct MemArrays *p, unsigned n)
220 {
221 T (stpncpy (str, str, n));
222 T (stpncpy (str, arr, n));
223 T (stpncpy (arr, str, n));
224
225 T (stpncpy (str, ptr, n));
226 T (stpncpy (str, parr, n));
227 T (stpncpy (parr, str, n));
228
229 T (stpncpy (p->str, p->arr, n));
230 T (stpncpy (p->arr, p->str, n));
231 T (stpncpy (p->parr, p->str, n));
232 }
233
234
235 void test_stpncpy_warn (struct MemArrays *p, unsigned n)
236 {
237 enum { N = sizeof arr };
238
239 T (stpncpy (str, str, N));
240 T (stpncpy (str, arr, N));
241 T (stpncpy (arr, str, N));
242
243 T (stpncpy (str, ptr, N));
244 T (stpncpy (str, parr, N));
245 T (stpncpy (parr, str, N));
246
247 T (stpncpy (p->str, p->arr, N));
248 T (stpncpy (p->arr, p->str, N));
249 T (stpncpy (p->parr, p->str, N));
250
251 T (stpncpy (ptr, str, N + 1));
252 T (stpncpy (ptr, arr, N + 1)); /* { dg-warning "argument 2 declared attribute .nonstring. is smaller than the specified bound 5" } */
253 T (stpncpy (arr, str, N + 1)); /* { dg-warning "writing 5 bytes into a region of size 4 overflows " } */
254
255 T (stpncpy (ptr, ptr, N + 1));
256 T (stpncpy (ptr, parr, N + 1));
257 T (stpncpy (parr, str, N + 1));
258
259 T (stpncpy (ptr, p->arr, N + 1)); /* { dg-warning "argument 2 declared attribute .nonstring. is smaller" } */
260 T (stpncpy (p->arr, p->str, N + 1)); /* { dg-warning "writing 5 bytes into a region of size 4 overflows " } */
261 T (stpncpy (p->parr, p->str, N + 1));
262 }
263
264
265 void test_strcat (struct MemArrays *p)
266 {
267 T (strcat (str, str));
268 T (strcat (str, arr)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
269 T (strcat (arr, str));
270
271 T (strcat (str, ptr));
272 T (strcat (str, parr)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
273 T (strcat (parr, str));
274
275 T (strcat (p->str, p->arr)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
276 T (strcat (p->arr, p->str));
277 T (strcat (p->parr, p->str));
278 }
279
280
281 void test_strncat (struct MemArrays *p, unsigned n)
282 {
283 T (strncat (str, str, n));
284 T (strncat (str, arr, n)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
285 T (strncat (arr, str, n));
286
287 T (strncat (str, ptr, n));
288 T (strncat (str, parr, n)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
289 T (strncat (parr, str, n));
290
291 T (strncat (p->str, p->arr, n)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
292 T (strncat (p->arr, p->str, n));
293 T (strncat (p->parr, p->str, n));
294 }
295
296
297 void test_strcpy (struct MemArrays *p)
298 {
299 T (strcpy (str, str));
300 T (strcpy (str, arr)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
301 T (strcpy (arr, str));
302
303 T (strcpy (str, ptr));
304 T (strcpy (str, parr)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
305 T (strcpy (parr, str));
306
307 T (strcpy (p->str, p->arr)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
308 T (strcpy (p->arr, p->str));
309 T (strcpy (p->parr, p->str));
310 }
311
312
313 void test_strncpy (struct MemArrays *p, unsigned n)
314 {
315 T (strncpy (str, str, n));
316 T (strncpy (str, arr, n));
317 T (strncpy (arr, str, n));
318
319 T (strncpy (str, ptr, n));
320 T (strncpy (str, parr, n));
321 T (strncpy (parr, str, n));
322
323 T (strncpy (p->str, p->arr, n));
324 T (strncpy (p->arr, p->str, n));
325 T (strncpy (p->parr, p->str, n));
326 }
327
328
329 void test_strchr (struct MemArrays *p, int c)
330 {
331 T (strchr (str, c));
332 T (strchr (arr, c)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
333
334 T (strchr (ptr, c));
335 T (strchr (parr, c)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
336
337 T (strchr (p->str, c));
338 T (strchr (p->arr, c)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
339 }
340
341
342 void test_strdup (struct MemArrays *p)
343 {
344 T (strdup (str));
345 T (strdup (arr)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
346
347 T (strdup (ptr));
348 T (strdup (parr)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
349
350 T (strdup (p->str));
351 T (strdup (p->arr)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
352 }
353
354
355 void test_stnrdup_nowarn (struct MemArrays *p, size_t n)
356 {
357 T (strndup (str, n));
358 T (strndup (arr, n));
359
360 T (strndup (ptr, n));
361 T (strndup (parr, n));
362
363 T (strndup (p->str, n));
364 T (strndup (p->arr, n));
365 }
366
367
368 void test_stnrdup_warn (struct MemArrays *p)
369 {
370 enum { N = sizeof arr };
371
372 T (strndup (str, N));
373 T (strndup (arr, N));
374
375 T (strndup (ptr, N));
376 T (strndup (parr, N));
377
378 T (strndup (p->str, N));
379 T (strndup (p->arr, N));
380
381
382 T (strndup (arr, N + 1)); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound 5|specified bound 5 exceeds source size 4" } */
383 T (strndup (parr, N + 1));
384 T (strndup (p->arr, N + 1)); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound 5|specified bound 5 exceeds source size 4" } */
385 T (strndup (p->parr, N + 1));
386 }
387
388
389 void test_strlen (struct MemArrays *p, char *s NONSTRING, size_t n)
390 {
391 T (strlen (str));
392 T (strlen (arr)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
393
394 T (strlen (ptr));
395 T (strlen (parr)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
396
397 T (strlen (p->str));
398 T (strlen (p->arr)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
399
400 T (strlen (s)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
401 {
402 strcpy (s, "123");
403 T (strlen (s));
404 }
405
406 {
407 char a[] __attribute__ ((nonstring)) = { 1, 2, 3 };
408
409 T (strlen (a)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
410 }
411
412 {
413 char a[] __attribute__ ((nonstring)) = { 1, 2, 3, 4 };
414
415 strcpy (a, "12");
416 T (strlen (a));
417 }
418
419 {
420 char *p __attribute__ ((nonstring));
421 p = (char *)__builtin_malloc (n);
422 __builtin_memset (p, '*', n);
423
424 T (strlen (p)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
425
426 strcpy (p, "12345");
427 T (strlen (p));
428 }
429 }
430
431
432 void test_strnlen (struct MemArrays *p, size_t n)
433 {
434 T (strnlen (str, n));
435 T (strnlen (arr, n));
436
437 T (strnlen (ptr, n));
438 T (strnlen (parr, n));
439
440 T (strnlen (p->str, n));
441 T (strnlen (p->arr, n));
442 }
443
444
445 /* Verify no warnings are issued for raw mempory functions. */
446
447 void test_mem_functions (struct MemArrays *p, int c, size_t n)
448 {
449 T (memchr (arr, c, n));
450 T (memchr (parr, c, n));
451 T (memchr (p->arr, c, n));
452 T (memchr (p->parr, c, n));
453
454 T (memcmp (str, arr, n));
455 T (memcmp (arr, str, n));
456 T (memcmp (str, parr, n));
457 T (memcmp (parr, str, n));
458 T (memcmp (p->str, p->arr, n));
459 T (memcmp (p->arr, p->str, n));
460 T (memcmp (p->parr, p->str, n));
461
462 T (memcpy (str, arr, n));
463 T (memcpy (arr, str, n));
464 T (memcpy (str, parr, n));
465 T (memcpy (parr, str, n));
466 T (memcpy (p->str, p->arr, n));
467 T (memcpy (p->arr, p->str, n));
468 T (memcpy (p->parr, p->str, n));
469
470 T (memmove (str, arr, n));
471 T (memmove (arr, str, n));
472 T (memmove (str, parr, n));
473 T (memmove (parr, str, n));
474 T (memmove (p->str, p->arr, n));
475 T (memmove (p->arr, p->str, n));
476 T (memmove (p->parr, p->str, n));
477 }