131
|
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" } */
|
|
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" } */
|
|
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." "pr86688" { xfail *-*-* } } */
|
|
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 }
|