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.
4 { dg-options "-O2 -Wattributes -Wstringop-overflow -ftrack-macro-expansion=0" } */
6 typedef __SIZE_TYPE__
size_t;
7 typedef __builtin_va_list
va_list;
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);
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);
26 int strcmp (const char*, const char*);
27 int strncmp (const char*, const char*, size_t);
29 char* stpcpy (char*, const char*);
30 char* stpncpy (char*, const char*, size_t);
32 char* strcat (char*, const char*);
33 char* strncat (char*, const char*, size_t);
35 char* strcpy (char*, const char*);
36 char* strncpy (char*, const char*, size_t);
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);
48 #define NONSTRING __attribute__ ((nonstring))
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. */
54 char arr
[4] NONSTRING
;
62 char arr
[4] NONSTRING
;
69 #define T(call) sink (0, call)
71 void test_printf (struct MemArrays
*p
)
74 T (printf (arr
)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
77 T (printf (parr
)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
80 T (printf (p
->arr
)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
84 void test_puts (struct MemArrays
*p
)
87 T (puts (arr
)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
90 T (puts (parr
)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
93 T (puts (p
->arr
)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
97 void test_snprintf (char *d
, size_t n
, struct MemArrays
*p
)
99 T (snprintf (d
, n
, str
));
100 T (snprintf (d
, n
, arr
)); /* { dg-warning "argument 3 declared attribute .nonstring." } */
102 T (snprintf (d
, n
, ptr
));
103 T (snprintf (d
, n
, parr
)); /* { dg-warning "argument 3 declared attribute .nonstring." } */
105 T (snprintf (d
, n
, p
->str
));
106 T (snprintf (d
, n
, p
->arr
)); /* { dg-warning "argument 3 declared attribute .nonstring." } */
110 void test_sprintf (char *d
, struct MemArrays
*p
)
112 T (sprintf (d
, str
));
113 T (sprintf (d
, arr
)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
115 T (sprintf (d
, ptr
));
116 T (sprintf (d
, parr
)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
118 T (sprintf (d
, p
->str
));
119 T (sprintf (d
, p
->arr
)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
123 void test_vsnprintf (char *d
, size_t n
, struct MemArrays
*p
, va_list va
)
125 T (vsnprintf (d
, n
, str
, va
));
126 T (vsnprintf (d
, n
, arr
, va
)); /* { dg-warning "argument 3 declared attribute .nonstring." } */
128 T (vsnprintf (d
, n
, ptr
, va
));
129 T (vsnprintf (d
, n
, parr
, va
)); /* { dg-warning "argument 3 declared attribute .nonstring." } */
131 T (vsnprintf (d
, n
, p
->str
, va
));
132 T (vsnprintf (d
, n
, p
->arr
, va
)); /* { dg-warning "argument 3 declared attribute .nonstring." } */
136 void test_vsprintf (char *d
, struct MemArrays
*p
, va_list va
)
138 T (vsprintf (d
, str
, va
));
139 T (vsprintf (d
, arr
, va
)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
141 T (vsprintf (d
, ptr
, va
));
142 T (vsprintf (d
, parr
, va
)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
144 T (vsprintf (d
, p
->str
, va
));
145 T (vsprintf (d
, p
->arr
, va
)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
149 void test_strcmp (struct MemArrays
*p
)
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." } */
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." } */
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." } */
165 void test_strncmp_warn (struct MemArrays
*p
)
167 enum { N
= sizeof arr
};
168 T (strncmp (str
, arr
, N
));
169 T (strncmp (arr
, str
, N
));
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" } */
174 T (strncmp (str
, parr
, N
+ 1));
175 T (strncmp (parr
, str
, N
+ 1));
177 T (strncmp (p
->str
, p
->arr
, N
));
178 T (strncmp (p
->arr
, p
->str
, N
));
179 T (strncmp (p
->parr
, p
->str
, N
));
181 T (strncmp (p
->str
, p
->arr
, N
));
182 T (strncmp (p
->arr
, p
->str
, N
));
183 T (strncmp (p
->parr
, p
->str
, N
));
187 void test_strncmp_nowarn (struct MemArrays
*p
, size_t n
)
189 T (strncmp (str
, str
, n
));
190 T (strncmp (str
, arr
, n
));
191 T (strncmp (arr
, str
, n
));
193 T (strncmp (str
, ptr
, n
));
194 T (strncmp (str
, parr
, n
));
195 T (strncmp (parr
, str
, n
));
197 T (strncmp (p
->str
, p
->arr
, n
));
198 T (strncmp (p
->arr
, p
->str
, n
));
199 T (strncmp (p
->parr
, p
->str
, n
));
203 void test_stpcpy (struct MemArrays
*p
)
205 T (stpcpy (str
, str
));
206 T (stpcpy (str
, arr
)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
207 T (stpcpy (arr
, str
));
209 T (stpcpy (str
, ptr
));
210 T (stpcpy (str
, parr
)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
211 T (stpcpy (parr
, str
));
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
));
219 void test_stpncpy_nowarn (struct MemArrays
*p
, unsigned n
)
221 T (stpncpy (str
, str
, n
));
222 T (stpncpy (str
, arr
, n
));
223 T (stpncpy (arr
, str
, n
));
225 T (stpncpy (str
, ptr
, n
));
226 T (stpncpy (str
, parr
, n
));
227 T (stpncpy (parr
, str
, n
));
229 T (stpncpy (p
->str
, p
->arr
, n
));
230 T (stpncpy (p
->arr
, p
->str
, n
));
231 T (stpncpy (p
->parr
, p
->str
, n
));
235 void test_stpncpy_warn (struct MemArrays
*p
, unsigned n
)
237 enum { N
= sizeof arr
};
239 T (stpncpy (str
, str
, N
));
240 T (stpncpy (str
, arr
, N
));
241 T (stpncpy (arr
, str
, N
));
243 T (stpncpy (str
, ptr
, N
));
244 T (stpncpy (str
, parr
, N
));
245 T (stpncpy (parr
, str
, N
));
247 T (stpncpy (p
->str
, p
->arr
, N
));
248 T (stpncpy (p
->arr
, p
->str
, N
));
249 T (stpncpy (p
->parr
, p
->str
, N
));
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 " } */
255 T (stpncpy (ptr
, ptr
, N
+ 1));
256 T (stpncpy (ptr
, parr
, N
+ 1));
257 T (stpncpy (parr
, str
, N
+ 1));
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));
265 void test_strcat (struct MemArrays
*p
)
267 T (strcat (str
, str
));
268 T (strcat (str
, arr
)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
269 T (strcat (arr
, str
));
271 T (strcat (str
, ptr
));
272 T (strcat (str
, parr
)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
273 T (strcat (parr
, str
));
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
));
281 void test_strncat (struct MemArrays
*p
, unsigned n
)
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
));
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
));
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
));
297 void test_strcpy (struct MemArrays
*p
)
299 T (strcpy (str
, str
));
300 T (strcpy (str
, arr
)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
301 T (strcpy (arr
, str
));
303 T (strcpy (str
, ptr
));
304 T (strcpy (str
, parr
)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
305 T (strcpy (parr
, str
));
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
));
313 void test_strncpy (struct MemArrays
*p
, unsigned n
)
315 T (strncpy (str
, str
, n
));
316 T (strncpy (str
, arr
, n
));
317 T (strncpy (arr
, str
, n
));
319 T (strncpy (str
, ptr
, n
));
320 T (strncpy (str
, parr
, n
));
321 T (strncpy (parr
, str
, n
));
323 T (strncpy (p
->str
, p
->arr
, n
));
324 T (strncpy (p
->arr
, p
->str
, n
));
325 T (strncpy (p
->parr
, p
->str
, n
));
329 void test_strchr (struct MemArrays
*p
, int c
)
332 T (strchr (arr
, c
)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
335 T (strchr (parr
, c
)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
337 T (strchr (p
->str
, c
));
338 T (strchr (p
->arr
, c
)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
342 void test_strdup (struct MemArrays
*p
)
345 T (strdup (arr
)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
348 T (strdup (parr
)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
351 T (strdup (p
->arr
)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
355 void test_stnrdup_nowarn (struct MemArrays
*p
, size_t n
)
357 T (strndup (str
, n
));
358 T (strndup (arr
, n
));
360 T (strndup (ptr
, n
));
361 T (strndup (parr
, n
));
363 T (strndup (p
->str
, n
));
364 T (strndup (p
->arr
, n
));
368 void test_stnrdup_warn (struct MemArrays
*p
)
370 enum { N
= sizeof arr
};
372 T (strndup (str
, N
));
373 T (strndup (arr
, N
));
375 T (strndup (ptr
, N
));
376 T (strndup (parr
, N
));
378 T (strndup (p
->str
, N
));
379 T (strndup (p
->arr
, N
));
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));
389 void test_strlen (struct MemArrays
*p
, char *s NONSTRING
, size_t n
)
392 T (strlen (arr
)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
395 T (strlen (parr
)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
398 T (strlen (p
->arr
)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
400 T (strlen (s
)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
407 char a
[] __attribute__ ((nonstring
)) = { 1, 2, 3 };
409 T (strlen (a
)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
413 char a
[] __attribute__ ((nonstring
)) = { 1, 2, 3, 4 };
420 char *p
__attribute__ ((nonstring
));
421 p
= (char *)__builtin_malloc (n
);
422 __builtin_memset (p
, '*', n
);
424 T (strlen (p
)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
432 void test_strnlen (struct MemArrays
*p
, size_t n
)
434 T (strnlen (str
, n
));
435 T (strnlen (arr
, n
));
437 T (strnlen (ptr
, n
));
438 T (strnlen (parr
, n
));
440 T (strnlen (p
->str
, n
));
441 T (strnlen (p
->arr
, n
));
445 /* Verify no warnings are issued for raw mempory functions. */
447 void test_mem_functions (struct MemArrays
*p
, int c
, size_t n
)
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
));
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
));
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
));
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
));