Clang Project

clang_source_code/test/Sema/format-strings.c
1// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs %s
2// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs -fno-signed-char %s
3
4#include <stdarg.h>
5#include <stddef.h>
6#define __need_wint_t
7#include <stddef.h> // For wint_t and wchar_t
8
9typedef struct _FILE FILE;
10int fprintf(FILE *, const char *restrict, ...);
11int printf(const char *restrict, ...); // expected-note{{passing argument to parameter here}}
12int snprintf(char *restrict, size_t, const char *restrict, ...);
13int sprintf(char *restrict, const char *restrict, ...);
14int vasprintf(char **, const char *, va_list);
15int asprintf(char **, const char *, ...);
16int vfprintf(FILE *, const char *restrict, va_list);
17int vprintf(const char *restrict, va_list);
18int vsnprintf(char *, size_t, const char *, va_list);
19int vsprintf(char *restrict, const char *restrict, va_list); // expected-note{{passing argument to parameter here}}
20
21int vscanf(const char *restrict format, va_list arg);
22
23char * global_fmt;
24
25void check_string_literal( FILE* fp, const char* s, char *buf, ... ) {
26
27  char * b;
28  va_list ap;
29  va_start(ap,buf);
30
31  printf(s); // expected-warning {{format string is not a string literal}}
32  // expected-note@-1{{treat the string as an argument to avoid this}}
33  vprintf(s,ap); // expected-warning {{format string is not a string literal}}
34  fprintf(fp,s); // expected-warning {{format string is not a string literal}}
35  // expected-note@-1{{treat the string as an argument to avoid this}}
36  vfprintf(fp,s,ap); // expected-warning {{format string is not a string literal}}
37  asprintf(&b,s); // expected-warning {{format string is not a string lit}}
38  // expected-note@-1{{treat the string as an argument to avoid this}}
39  vasprintf(&b,s,ap); // expected-warning {{format string is not a string literal}}
40  sprintf(buf,s); // expected-warning {{format string is not a string literal}}
41  // expected-note@-1{{treat the string as an argument to avoid this}}
42  snprintf(buf,2,s); // expected-warning {{format string is not a string lit}}
43  // expected-note@-1{{treat the string as an argument to avoid this}}
44  __builtin___sprintf_chk(buf,0,-1,s); // expected-warning {{format string is not a string literal}}
45  // expected-note@-1{{treat the string as an argument to avoid this}}
46  __builtin___snprintf_chk(buf,2,0,-1,s); // expected-warning {{format string is not a string lit}}
47  // expected-note@-1{{treat the string as an argument to avoid this}}
48  vsprintf(buf,s,ap); // expected-warning {{format string is not a string lit}}
49  vsnprintf(buf,2,s,ap); // expected-warning {{format string is not a string lit}}
50  vsnprintf(buf,2,global_fmt,ap); // expected-warning {{format string is not a string literal}}
51  __builtin___vsnprintf_chk(buf,2,0,-1,s,ap); // expected-warning {{format string is not a string lit}}
52  __builtin___vsnprintf_chk(buf,2,0,-1,global_fmt,ap); // expected-warning {{format string is not a string literal}}
53
54  vscanf(s, ap); // expected-warning {{format string is not a string literal}}
55
56  const char *const fmt = "%d"; // FIXME -- defined here
57  printf(fmt, 1, 2); // expected-warning{{data argument not used}}
58
59  // rdar://6079877
60  printf("abc"
61         "%*d", 1, 1); // no-warning
62  printf("abc\
63def"
64         "%*d", 1, 1); // no-warning
65         
66  // <rdar://problem/6079850>, allow 'unsigned' (instead of 'int') to be used for both
67  // the field width and precision.  This deviates from C99, but is reasonably safe
68  // and is also accepted by GCC.
69  printf("%*d", (unsigned) 1, 1); // no-warning  
70}
71
72// When calling a non-variadic format function (vprintf, vscanf, NSLogv, ...),
73// warn only if the format string argument is a parameter that is not itself
74// declared as a format string with compatible format.
75__attribute__((__format__ (__printf__, 2, 4)))
76void check_string_literal2( FILE* fp, const char* s, char *buf, ... ) {
77  char * b;
78  va_list ap;
79  va_start(ap,buf);
80
81  printf(s); // expected-warning {{format string is not a string literal}}
82  // expected-note@-1{{treat the string as an argument to avoid this}}
83  vprintf(s,ap); // no-warning
84  fprintf(fp,s); // expected-warning {{format string is not a string literal}}
85  // expected-note@-1{{treat the string as an argument to avoid this}}
86  vfprintf(fp,s,ap); // no-warning
87  asprintf(&b,s); // expected-warning {{format string is not a string lit}}
88  // expected-note@-1{{treat the string as an argument to avoid this}}
89  vasprintf(&b,s,ap); // no-warning
90  sprintf(buf,s); // expected-warning {{format string is not a string literal}}
91  // expected-note@-1{{treat the string as an argument to avoid this}}
92  snprintf(buf,2,s); // expected-warning {{format string is not a string lit}}
93  // expected-note@-1{{treat the string as an argument to avoid this}}
94  __builtin___vsnprintf_chk(buf,2,0,-1,s,ap); // no-warning
95
96  vscanf(s, ap); // expected-warning {{format string is not a string literal}}
97}
98
99void check_conditional_literal(const char* s, int i) {
100  printf(i == 1 ? "yes" : "no"); // no-warning
101  printf(i == 0 ? (i == 1 ? "yes" : "no") : "dont know"); // no-warning
102  printf(i == 0 ? (i == 1 ? s : "no") : "dont know"); // expected-warning{{format string is not a string literal}}
103  // expected-note@-1{{treat the string as an argument to avoid this}}
104  printf("yes" ?: "no %d", 1); // expected-warning{{data argument not used by format string}}
105  printf(0 ? "yes %s" : "no %d", 1); // no-warning
106  printf(0 ? "yes %d" : "no %s", 1); // expected-warning{{format specifies type 'char *'}}
107
108  printf(0 ? "yes" : "no %d", 1); // no-warning
109  printf(0 ? "yes %d" : "no", 1); // expected-warning{{data argument not used by format string}}
110  printf(1 ? "yes" : "no %d", 1); // expected-warning{{data argument not used by format string}}
111  printf(1 ? "yes %d" : "no", 1); // no-warning
112  printf(i ? "yes" : "no %d", 1); // no-warning
113  printf(i ? "yes %s" : "no %d", 1); // expected-warning{{format specifies type 'char *'}}
114  printf(i ? "yes" : "no %d", 1, 2); // expected-warning{{data argument not used by format string}}
115
116  printf(i ? "%*s" : "-", i, s); // no-warning
117  printf(i ? "yes" : 0 ? "no %*d" : "dont know %d", 1, 2); // expected-warning{{data argument not used by format string}}
118  printf(i ? "%i\n" : "%i %s %s\n", i, s); // expected-warning{{more '%' conversions than data arguments}}
119}
120
121void check_writeback_specifier()
122{
123  int x;
124  char *b;
125  printf("%n", b); // expected-warning{{format specifies type 'int *' but the argument has type 'char *'}}
126  printf("%n", &x); // no-warning
127
128  printf("%hhn", (signed char*)0); // no-warning
129  printf("%hhn", (char*)0); // no-warning
130  printf("%hhn", (unsigned char*)0); // no-warning
131  printf("%hhn", (int*)0); // expected-warning{{format specifies type 'signed char *' but the argument has type 'int *'}}
132
133  printf("%hn", (short*)0); // no-warning
134  printf("%hn", (unsigned short*)0); // no-warning
135  printf("%hn", (int*)0); // expected-warning{{format specifies type 'short *' but the argument has type 'int *'}}
136
137  printf("%n", (int*)0); // no-warning
138  printf("%n", (unsigned int*)0); // no-warning
139  printf("%n", (char*)0); // expected-warning{{format specifies type 'int *' but the argument has type 'char *'}}
140
141  printf("%ln", (long*)0); // no-warning
142  printf("%ln", (unsigned long*)0); // no-warning
143  printf("%ln", (int*)0); // expected-warning{{format specifies type 'long *' but the argument has type 'int *'}}
144
145  printf("%lln", (long long*)0); // no-warning
146  printf("%lln", (unsigned long long*)0); // no-warning
147  printf("%lln", (int*)0); // expected-warning{{format specifies type 'long long *' but the argument has type 'int *'}}
148
149  printf("%qn", (long long*)0); // no-warning
150  printf("%qn", (unsigned long long*)0); // no-warning
151  printf("%qn", (int*)0); // expected-warning{{format specifies type 'long long *' but the argument has type 'int *'}}
152
153  printf("%Ln", 0); // expected-warning{{length modifier 'L' results in undefined behavior or no effect with 'n' conversion specifier}}
154  // expected-note@-1{{did you mean to use 'll'?}}
155}
156
157void check_invalid_specifier(FILE* fp, char *buf)
158{
159  printf("%s%lb%d","unix",10,20); // expected-warning {{invalid conversion specifier 'b'}} expected-warning {{data argument not used by format string}}
160  fprintf(fp,"%%%l"); // expected-warning {{incomplete format specifier}}
161  sprintf(buf,"%%%%%ld%d%d", 1, 2, 3); // expected-warning{{format specifies type 'long' but the argument has type 'int'}}
162  snprintf(buf, 2, "%%%%%ld%;%d", 1, 2, 3); // expected-warning{{format specifies type 'long' but the argument has type 'int'}} expected-warning {{invalid conversion specifier ';'}} expected-warning {{data argument not used by format string}}
163}
164
165void check_null_char_string(char* b)
166{
167  printf("\0this is bogus%d",1); // expected-warning {{string contains '\0'}}
168  snprintf(b,10,"%%%%%d\0%d",1,2); // expected-warning {{string contains '\0'}}
169  printf("%\0d",1); // expected-warning {{string contains '\0'}}
170}
171
172void check_empty_format_string(char* buf, ...)
173{
174  va_list ap;
175  va_start(ap,buf);
176  vprintf("",ap); // expected-warning {{format string is empty}}
177  sprintf(buf, "", 1); // expected-warning {{format string is empty}}
178  
179  // Don't warn about empty format strings when there are no data arguments.
180  // This can arise from macro expansions and non-standard format string
181  // functions.
182  sprintf(buf, ""); // no-warning
183}
184
185void check_wide_string(char* b, ...)
186{
187  va_list ap;
188  va_start(ap,b);
189
190  printf(L"foo %d",2); // expected-warning {{incompatible pointer types}}, expected-warning {{should not be a wide string}}
191  vsprintf(b,L"bar %d",ap); // expected-warning {{incompatible pointer types}}, expected-warning {{should not be a wide string}}
192}
193
194void check_asterisk_precision_width(int x) {
195  printf("%*d"); // expected-warning {{'*' specified field width is missing a matching 'int' argument}}
196  printf("%.*d"); // expected-warning {{'.*' specified field precision is missing a matching 'int' argument}}
197  printf("%*d",12,x); // no-warning
198  printf("%*d","foo",x); // expected-warning {{field width should have type 'int', but argument has type 'char *'}}
199  printf("%.*d","foo",x); // expected-warning {{field precision should have type 'int', but argument has type 'char *'}}
200}
201
202void __attribute__((format(printf,1,3))) myprintf(const char*, int blah, ...);
203
204void test_myprintf() {
205  myprintf("%d", 17, 18); // okay
206}
207
208void test_constant_bindings(void) {
209  const char * const s1 = "hello";
210  const char s2[] = "hello";
211  const char *s3 = "hello";
212  char * const s4 = "hello";
213  extern const char s5[];
214  
215  printf(s1); // no-warning
216  printf(s2); // no-warning
217  printf(s3); // expected-warning{{not a string literal}}
218  // expected-note@-1{{treat the string as an argument to avoid this}}
219  printf(s4); // expected-warning{{not a string literal}}
220  // expected-note@-1{{treat the string as an argument to avoid this}}
221  printf(s5); // expected-warning{{not a string literal}}
222  // expected-note@-1{{treat the string as an argument to avoid this}}
223}
224
225
226// Test what happens when -Wformat-security only.
227#pragma GCC diagnostic ignored "-Wformat-nonliteral"
228#pragma GCC diagnostic warning "-Wformat-security"
229
230void test9(char *P) {
231  int x;
232  printf(P);   // expected-warning {{format string is not a string literal (potentially insecure)}}
233  // expected-note@-1{{treat the string as an argument to avoid this}}
234  printf(P, 42);
235}
236
237void torture(va_list v8) {
238  vprintf ("%*.*d", v8);  // no-warning
239  
240}
241
242void test10(int x, float f, int i, long long lli) {
243  printf("%s"); // expected-warning{{more '%' conversions than data arguments}}
244  printf("%@", 12); // expected-warning{{invalid conversion specifier '@'}}
245  printf("\0"); // expected-warning{{format string contains '\0' within the string body}}
246  printf("xs\0"); // expected-warning{{format string contains '\0' within the string body}}
247  printf("%*d\n"); // expected-warning{{'*' specified field width is missing a matching 'int' argument}}
248  printf("%*.*d\n", x); // expected-warning{{'.*' specified field precision is missing a matching 'int' argument}}
249  printf("%*d\n", f, x); // expected-warning{{field width should have type 'int', but argument has type 'double'}}
250  printf("%*.*d\n", x, f, x); // expected-warning{{field precision should have type 'int', but argument has type 'double'}}
251  printf("%**\n"); // expected-warning{{invalid conversion specifier '*'}}
252  printf("%d%d\n", x); // expected-warning{{more '%' conversions than data arguments}}
253  printf("%d\n", x, x); // expected-warning{{data argument not used by format string}}
254  printf("%W%d\n", x, x); // expected-warning{{invalid conversion specifier 'W'}}  expected-warning {{data argument not used by format string}}
255  printf("%"); // expected-warning{{incomplete format specifier}}
256  printf("%.d", x); // no-warning
257  printf("%.", x);  // expected-warning{{incomplete format specifier}}
258  printf("%f", 4); // expected-warning{{format specifies type 'double' but the argument has type 'int'}}
259  printf("%qd", lli); // no-warning
260  printf("%qd", x); // expected-warning{{format specifies type 'long long' but the argument has type 'int'}}
261  printf("%qp", (void *)0); // expected-warning{{length modifier 'q' results in undefined behavior or no effect with 'p' conversion specifier}}
262  printf("hhX %hhX", (unsigned char)10); // no-warning
263  printf("llX %llX", (long long) 10); // no-warning
264  // This is fine, because there is an implicit conversion to an int.
265  printf("%d", (unsigned char) 10); // no-warning
266  printf("%d", (long long) 10); // expected-warning{{format specifies type 'int' but the argument has type 'long long'}}
267  printf("%Lf\n", (long double) 1.0); // no-warning
268  printf("%f\n", (long double) 1.0); // expected-warning{{format specifies type 'double' but the argument has type 'long double'}}
269  // The man page says that a zero precision is okay.
270  printf("%.0Lf", (long double) 1.0); // no-warning
271  printf("%c\n", "x"); // expected-warning{{format specifies type 'int' but the argument has type 'char *'}}
272  printf("%c\n", 1.23); // expected-warning{{format specifies type 'int' but the argument has type 'double'}}
273  printf("Format %d, is %! %f", 1, 4.4); // expected-warning{{invalid conversion specifier '!'}}
274}
275
276typedef unsigned char uint8_t;
277
278void should_understand_small_integers() {
279  printf("%hhu", (short) 10); // expected-warning{{format specifies type 'unsigned char' but the argument has type 'short'}}
280  printf("%hu\n", (unsigned char) 1); // expected-warning{{format specifies type 'unsigned short' but the argument has type 'unsigned char'}}
281  printf("%hu\n", (uint8_t)1); // expected-warning{{format specifies type 'unsigned short' but the argument has type 'uint8_t'}}
282}
283
284void test11(void *p, char *s) {
285  printf("%p", p); // no-warning
286  printf("%p", 123); // expected-warning{{format specifies type 'void *' but the argument has type 'int'}}
287  printf("%.4p", p); // expected-warning{{precision used with 'p' conversion specifier, resulting in undefined behavior}}
288  printf("%+p", p); // expected-warning{{flag '+' results in undefined behavior with 'p' conversion specifier}}
289  printf("% p", p); // expected-warning{{flag ' ' results in undefined behavior with 'p' conversion specifier}}
290  printf("%0p", p); // expected-warning{{flag '0' results in undefined behavior with 'p' conversion specifier}}
291  printf("%s", s); // no-warning
292  printf("%+s", p); // expected-warning{{flag '+' results in undefined behavior with 's' conversion specifier}}
293  printf("% s", p); // expected-warning{{flag ' ' results in undefined behavior with 's' conversion specifier}}
294  printf("%0s", p); // expected-warning{{flag '0' results in undefined behavior with 's' conversion specifier}}
295}
296
297void test12(char *b) {
298  unsigned char buf[4];
299  printf ("%.4s\n", buf); // no-warning
300  printf ("%.4s\n", &buf); // expected-warning{{format specifies type 'char *' but the argument has type 'unsigned char (*)[4]'}}
301  
302  // Verify that we are checking asprintf
303  asprintf(&b, "%d", "asprintf"); // expected-warning{{format specifies type 'int' but the argument has type 'char *'}}
304}
305
306void test13(short x) {
307  char bel = 007;
308  printf("bel: '0%hhd'\n", bel); // no-warning
309  printf("x: '0%hhd'\n", x); // expected-warning {{format specifies type 'char' but the argument has type 'short'}}
310}
311
312typedef struct __aslclient *aslclient;
313typedef struct __aslmsg *aslmsg;
314int asl_log(aslclient asl, aslmsg msg, int level, const char *format, ...) __attribute__((__format__ (__printf__, 4, 5)));
315void test_asl(aslclient asl) {
316  // Test case from <rdar://problem/7341605>.
317  asl_log(asl, 0, 3, "Error: %m"); // no-warning
318  asl_log(asl, 0, 3, "Error: %W"); // expected-warning{{invalid conversion specifier 'W'}}
319}
320
321// <rdar://problem/7595366>
322typedef enum { A } int_t;
323void f0(int_t x) { printf("%d\n", x); }
324
325// Unicode test cases.  These are possibly specific to Mac OS X.  If so, they should
326// eventually be moved into a separate test.
327
328void test_unicode_conversions(wchar_t *s) {
329  printf("%S", s); // no-warning
330  printf("%s", s); // expected-warning{{format specifies type 'char *' but the argument has type 'wchar_t *'}}
331  printf("%C", s[0]); // no-warning
332  printf("%c", s[0]);
333  // FIXME: This test reports inconsistent results. On Windows, '%C' expects
334  // 'unsigned short'.
335  // printf("%C", 10);
336  printf("%S", "hello"); // expected-warning{{but the argument has type 'char *'}}
337}
338
339// Mac OS X supports positional arguments in format strings.
340// This is an IEEE extension (IEEE Std 1003.1).
341// FIXME: This is probably not portable everywhere.
342void test_positional_arguments() {
343  printf("%0$", (int)2); // expected-warning{{position arguments in format strings start counting at 1 (not 0)}}
344  printf("%1$*0$d", (int) 2); // expected-warning{{position arguments in format strings start counting at 1 (not 0)}}
345  printf("%1$d", (int) 2); // no-warning
346  printf("%1$d", (int) 2, 2); // expected-warning{{data argument not used by format string}}
347  printf("%1$d%1$f", (int) 2); // expected-warning{{format specifies type 'double' but the argument has type 'int'}}
348  printf("%1$2.2d", (int) 2); // no-warning
349  printf("%2$*1$.2d", (int) 2, (int) 3); // no-warning
350  printf("%2$*8$d", (int) 2, (int) 3); // expected-warning{{specified field width is missing a matching 'int' argument}}
351  printf("%%%1$d", (int) 2); // no-warning
352  printf("%1$d%%", (int) 2); // no-warning
353}
354
355// PR 6697 - Handle format strings where the data argument is not adjacent to the format string
356void myprintf_PR_6697(const char *format, int x, ...) __attribute__((__format__(printf,1, 3)));
357void test_pr_6697() {
358  myprintf_PR_6697("%s\n", 1, "foo"); // no-warning
359  myprintf_PR_6697("%s\n", 1, (int)0); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}}
360  // FIXME: Not everything should clearly support positional arguments,
361  // but we need a way to identify those cases.
362  myprintf_PR_6697("%1$s\n", 1, "foo"); // no-warning
363  myprintf_PR_6697("%2$s\n", 1, "foo"); // expected-warning{{data argument position '2' exceeds the number of data arguments (1)}}
364  myprintf_PR_6697("%18$s\n", 1, "foo"); // expected-warning{{data argument position '18' exceeds the number of data arguments (1)}}
365  myprintf_PR_6697("%1$s\n", 1, (int) 0); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}}
366}
367
368void rdar8026030(FILE *fp) {
369  fprintf(fp, "\%"); // expected-warning{{incomplete format specifier}}
370}
371
372void bug7377_bad_length_mod_usage() {
373  // Bad length modifiers
374  printf("%hhs", "foo"); // expected-warning{{length modifier 'hh' results in undefined behavior or no effect with 's' conversion specifier}}
375  printf("%1$zp", (void *)0); // expected-warning{{length modifier 'z' results in undefined behavior or no effect with 'p' conversion specifier}}
376  printf("%ls", L"foo"); // no-warning
377  printf("%#.2Lf", (long double)1.234); // no-warning
378
379  // Bad flag usage
380  printf("%#p", (void *) 0); // expected-warning{{flag '#' results in undefined behavior with 'p' conversion specifier}}
381  printf("%0d", -1); // no-warning
382  printf("%#n", (int *) 0); // expected-warning{{flag '#' results in undefined behavior with 'n' conversion specifier}}
383  printf("%-n", (int *) 0); // expected-warning{{flag '-' results in undefined behavior with 'n' conversion specifier}}
384  printf("%-p", (void *) 0); // no-warning
385
386  // Bad optional amount use
387  printf("%.2c", 'a'); // expected-warning{{precision used with 'c' conversion specifier, resulting in undefined behavior}}
388  printf("%1n", (int *) 0); // expected-warning{{field width used with 'n' conversion specifier, resulting in undefined behavior}}
389  printf("%.9n", (int *) 0); // expected-warning{{precision used with 'n' conversion specifier, resulting in undefined behavior}}
390
391  // Ignored flags
392  printf("% +f", 1.23); // expected-warning{{flag ' ' is ignored when flag '+' is present}}
393  printf("%+ f", 1.23); // expected-warning{{flag ' ' is ignored when flag '+' is present}}
394  printf("%0-f", 1.23); // expected-warning{{flag '0' is ignored when flag '-' is present}}
395  printf("%-0f", 1.23); // expected-warning{{flag '0' is ignored when flag '-' is present}}
396  printf("%-+f", 1.23); // no-warning
397}
398
399// PR 7981 - handle '%lc' (wint_t)
400
401void pr7981(wint_t c, wchar_t c2) {
402  printf("%lc", c); // no-warning
403  printf("%lc", 1.0); // expected-warning{{the argument has type 'double'}}
404#if __WINT_WIDTH__ == 32
405  printf("%lc", (char) 1); // no-warning
406#else
407  printf("%lc", (char) 1); // expected-warning{{the argument has type 'char'}}
408#endif
409  printf("%lc", &c); // expected-warning{{the argument has type 'wint_t *'}}
410  // If wint_t and wchar_t are the same width and wint_t is signed where
411  // wchar_t is unsigned, an implicit conversion isn't possible.
412#if defined(__WINT_UNSIGNED__) || !defined(__WCHAR_UNSIGNED__) ||   \
413  __WINT_WIDTH__ > __WCHAR_WIDTH__
414  printf("%lc", c2); // no-warning
415#endif
416}
417
418// <rdar://problem/8269537> -Wformat-security says NULL is not a string literal
419void rdar8269537() {
420  // This is likely to crash in most cases, but -Wformat-nonliteral technically
421  // doesn't warn in this case.
422  printf(0); // no-warning
423}
424
425// Handle functions with multiple format attributes.
426extern void rdar8332221_vprintf_scanf(const char *, va_list, const char *, ...)
427     __attribute__((__format__(__printf__, 1, 0)))
428     __attribute__((__format__(__scanf__, 3, 4)));
429     
430void rdar8332221(va_list ap, int *x, long *y) {
431  rdar8332221_vprintf_scanf("%", ap, "%d", x); // expected-warning{{incomplete format specifier}}
432}
433
434// PR8641
435void pr8641() {
436  printf("%#x\n", 10);
437  printf("%#X\n", 10);
438}
439
440void posix_extensions() {
441  // Test %'d, "thousands grouping".
442  // <rdar://problem/8816343>
443  printf("%'d\n", 123456789); // no-warning
444  printf("%'i\n", 123456789); // no-warning
445  printf("%'f\n", (float) 1.0); // no-warning
446  printf("%'p\n", (void*) 0); // expected-warning{{results in undefined behavior with 'p' conversion specifier}}
447}
448
449// PR8486
450//
451// Test what happens when -Wformat is on, but -Wformat-security is off.
452#pragma GCC diagnostic warning "-Wformat"
453#pragma GCC diagnostic ignored "-Wformat-security"
454
455void pr8486() {
456  printf("%s", 1); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}}
457}
458
459// PR9314
460// Don't warn about string literals that are PreDefinedExprs, e.g. __func__.
461void pr9314() {
462  printf(__PRETTY_FUNCTION__); // no-warning
463  printf(__func__); // no-warning
464}
465
466int printf(const char * restrict, ...) __attribute__((__format__ (__printf__, 1, 2)));
467
468void rdar9612060(void) {
469  printf("%s", 2); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}}
470}
471
472void check_char(unsigned char x, signed char y) {
473  printf("%c", y); // no-warning
474  printf("%hhu", x); // no-warning
475  printf("%hhi", y); // no-warning
476  printf("%hhi", x); // no-warning
477  printf("%c", x); // no-warning
478  printf("%hhu", y); // no-warning
479}
480
481// Test suppression of individual warnings.
482
483void test_suppress_invalid_specifier() {
484#pragma clang diagnostic push
485#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
486  printf("%@", 12); // no-warning
487#pragma clang diagnostic pop
488}
489
490// Make sure warnings are on for next test.
491#pragma GCC diagnostic warning "-Wformat"
492#pragma GCC diagnostic warning "-Wformat-security"
493
494// Test that the printf call site is where the warning is attached.  If the
495// format string is somewhere else, point to it in a note.
496void pr9751() {
497  const char kFormat1[] = "%d %d \n"; // expected-note{{format string is defined here}}}
498  printf(kFormat1, 0); // expected-warning{{more '%' conversions than data arguments}}
499  printf("%d %s\n", 0); // expected-warning{{more '%' conversions than data arguments}}
500
501  const char kFormat2[] = "%18$s\n"; // expected-note{{format string is defined here}}
502  printf(kFormat2, 1, "foo"); // expected-warning{{data argument position '18' exceeds the number of data arguments (2)}}
503  printf("%18$s\n", 1, "foo"); // expected-warning{{data argument position '18' exceeds the number of data arguments (2)}}
504
505  const char kFormat4[] = "%y"; // expected-note{{format string is defined here}}
506  printf(kFormat4, 5); // expected-warning{{invalid conversion specifier 'y'}}
507  printf("%y", 5); // expected-warning{{invalid conversion specifier 'y'}}
508
509  const char kFormat5[] = "%."; // expected-note{{format string is defined here}}
510  printf(kFormat5, 5); // expected-warning{{incomplete format specifier}}
511  printf("%.", 5); // expected-warning{{incomplete format specifier}}
512
513  const char kFormat6[] = "%s"; // expected-note{{format string is defined here}}
514  printf(kFormat6, 5); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}}
515  printf("%s", 5); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}}
516
517  const char kFormat7[] = "%0$"; // expected-note{{format string is defined here}}
518  printf(kFormat7, 5); // expected-warning{{position arguments in format strings start counting at 1 (not 0)}}
519  printf("%0$", 5); // expected-warning{{position arguments in format strings start counting at 1 (not 0)}}
520
521  const char kFormat8[] = "%1$d %d"; // expected-note{{format string is defined here}}
522  printf(kFormat8, 4, 4); // expected-warning{{cannot mix positional and non-positional arguments in format string}}
523  printf("%1$d %d", 4, 4); // expected-warning{{cannot mix positional and non-positional arguments in format string}}
524
525  const char kFormat9[] = ""; // expected-note{{format string is defined here}}
526  printf(kFormat9, 4, 4); // expected-warning{{format string is empty}}
527  printf("", 4, 4); // expected-warning{{format string is empty}}
528
529  const char kFormat10[] = "\0%d"; // expected-note{{format string is defined here}}
530  printf(kFormat10, 4); // expected-warning{{format string contains '\0' within the string body}}
531  printf("\0%d", 4); // expected-warning{{format string contains '\0' within the string body}}
532
533  const char kFormat11[] = "%*d"; // expected-note{{format string is defined here}}
534  printf(kFormat11); // expected-warning{{'*' specified field width is missing a matching 'int' argument}}
535  printf("%*d"); // expected-warning{{'*' specified field width is missing a matching 'int' argument}}
536
537  const char kFormat12[] = "%*d"; // expected-note{{format string is defined here}}
538  printf(kFormat12, 4.4); // expected-warning{{field width should have type 'int', but argument has type 'double'}}
539  printf("%*d", 4.4); // expected-warning{{field width should have type 'int', but argument has type 'double'}}
540
541  const char kFormat13[] = "%.3p"; // expected-note{{format string is defined here}}
542  void *p;
543  printf(kFormat13, p); // expected-warning{{precision used with 'p' conversion specifier, resulting in undefined behavior}}
544  printf("%.3p", p); // expected-warning{{precision used with 'p' conversion specifier, resulting in undefined behavior}}
545
546  const char kFormat14[] = "%0s"; // expected-note{{format string is defined here}}
547  printf(kFormat14, "a"); // expected-warning{{flag '0' results in undefined behavior with 's' conversion specifier}}
548  printf("%0s", "a"); // expected-warning{{flag '0' results in undefined behavior with 's' conversion specifier}}
549
550  const char kFormat15[] = "%hhs"; // expected-note{{format string is defined here}}
551  printf(kFormat15, "a"); // expected-warning{{length modifier 'hh' results in undefined behavior or no effect with 's' conversion specifier}}
552  printf("%hhs", "a"); // expected-warning{{length modifier 'hh' results in undefined behavior or no effect with 's' conversion specifier}}
553
554  const char kFormat16[] = "%-0d"; // expected-note{{format string is defined here}}
555  printf(kFormat16, 5); // expected-warning{{flag '0' is ignored when flag '-' is present}}
556  printf("%-0d", 5); // expected-warning{{flag '0' is ignored when flag '-' is present}}
557
558  // Make sure that the "format string is defined here" note is not emitted
559  // when the original string is within the argument expression.
560  printf(1 ? "yes %d" : "no %d"); // expected-warning{{more '%' conversions than data arguments}}
561
562  const char kFormat17[] = "%hu"; // expected-note{{format string is defined here}}}
563  printf(kFormat17, (int[]){0}); // expected-warning{{format specifies type 'unsigned short' but the argument}}
564
565  printf("%a", (long double)0); // expected-warning{{format specifies type 'double' but the argument has type 'long double'}}
566
567  // Test braced char[] initializers.
568  const char kFormat18[] = { "%lld" }; // expected-note{{format string is defined here}}
569  printf(kFormat18, 0); // expected-warning{{format specifies type}}
570
571  // Make sure we point at the offending argument rather than the format string.
572  const char kFormat19[] = "%d";  // expected-note{{format string is defined here}}
573  printf(kFormat19,
574         0.0); // expected-warning{{format specifies}}
575}
576
577void pr18905() {
578  const char s1[] = "s\0%s"; // expected-note{{format string is defined here}}
579  const char s2[1] = "s"; // expected-note{{format string is defined here}}
580  const char s3[2] = "s\0%s"; // expected-warning{{initializer-string for char array is too long}}
581  const char s4[10] = "s";
582  const char s5[0] = "%s"; // expected-warning{{initializer-string for char array is too long}}
583                           // expected-note@-1{{format string is defined here}}
584
585  printf(s1); // expected-warning{{format string contains '\0' within the string body}}
586  printf(s2); // expected-warning{{format string is not null-terminated}}
587  printf(s3); // no-warning
588  printf(s4); // no-warning
589  printf(s5); // expected-warning{{format string is not null-terminated}}
590}
591
592void __attribute__((format(strfmon,1,2))) monformat(const char *fmt, ...);
593void __attribute__((format(strftime,1,0))) dateformat(const char *fmt);
594
595// Other formats
596void test_other_formats() {
597  char *str = "";
598  monformat("", 1); // expected-warning{{format string is empty}}
599  monformat(str); // expected-warning{{format string is not a string literal (potentially insecure)}}
600  dateformat(""); // expected-warning{{format string is empty}}
601  dateformat(str); // no-warning (using strftime non-literal is not unsafe)
602}
603
604// Do not warn about unused arguments coming from system headers.
605// <rdar://problem/11317765>
606#include <format-unused-system-args.h>
607void test_unused_system_args(int x) {
608  PRINT1("%d\n", x); // no-warning{{extra argument is system header is OK}}
609}
610
611void pr12761(char c) {
612  // This should not warn even with -fno-signed-char.
613  printf("%hhx", c);
614}
615
616void test_opencl_vector_format(int x) {
617  printf("%v4d", x); // expected-warning{{invalid conversion specifier 'v'}}
618  printf("%vd", x); // expected-warning{{invalid conversion specifier 'v'}}
619  printf("%0vd", x); // expected-warning{{invalid conversion specifier 'v'}}
620  printf("%hlf", x); // expected-warning{{invalid conversion specifier 'l'}}
621  printf("%hld", x); // expected-warning{{invalid conversion specifier 'l'}}
622}
623
624// Test that we correctly merge the format in both orders.
625extern void test14_foo(const char *, const char *, ...)
626     __attribute__((__format__(__printf__, 1, 3)));
627extern void test14_foo(const char *, const char *, ...)
628     __attribute__((__format__(__scanf__, 2, 3)));
629
630extern void test14_bar(const char *, const char *, ...)
631     __attribute__((__format__(__scanf__, 2, 3)));
632extern void test14_bar(const char *, const char *, ...)
633     __attribute__((__format__(__printf__, 1, 3)));
634
635void test14_zed(int *p) {
636  test14_foo("%", "%d", p); // expected-warning{{incomplete format specifier}}
637  test14_bar("%", "%d", p); // expected-warning{{incomplete format specifier}}
638}
639
640void test_qualifiers(volatile int *vip, const int *cip,
641                     const volatile int *cvip) {
642  printf("%n", cip); // expected-warning{{format specifies type 'int *' but the argument has type 'const int *'}}
643  printf("%n", cvip); // expected-warning{{format specifies type 'int *' but the argument has type 'const volatile int *'}}
644
645  printf("%n", vip); // No warning.
646  printf("%p", cip); // No warning.
647  printf("%p", cvip); // No warning.
648
649
650  typedef int* ip_t;
651  typedef const int* cip_t;
652  printf("%n", (ip_t)0); // No warning.
653  printf("%n", (cip_t)0); // expected-warning{{format specifies type 'int *' but the argument has type 'cip_t' (aka 'const int *')}}
654}
655
656#pragma GCC diagnostic ignored "-Wformat-nonliteral"
657#pragma GCC diagnostic warning "-Wformat-security"
658// <rdar://problem/14178260>
659extern void test_format_security_extra_args(const char*, int, ...)
660    __attribute__((__format__(__printf__, 1, 3)));
661void test_format_security_pos(char* string) {
662  test_format_security_extra_args(string, 5); // expected-warning {{format string is not a string literal (potentially insecure)}}
663  // expected-note@-1{{treat the string as an argument to avoid this}}
664}
665#pragma GCC diagnostic warning "-Wformat-nonliteral"
666
667void test_char_pointer_arithmetic(int b) {
668  const char s1[] = "string";
669  const char s2[] = "%s string";
670
671  printf(s1 - 1);  // expected-warning {{format string is not a string literal (potentially insecure)}}
672  // expected-note@-1{{treat the string as an argument to avoid this}}
673
674  printf(s1 + 2);  // no-warning
675  printf(s2 + 2);  // no-warning
676
677  const char s3[] = "%s string";
678  printf((s3 + 2) - 2);  // expected-warning{{more '%' conversions than data arguments}}
679  // expected-note@-2{{format string is defined here}}
680  printf(2 + s2);             // no-warning
681  printf(6 + s2 - 2);         // no-warning
682  printf(2 + (b ? s1 : s2));  // no-warning
683
684  const char s5[] = "string %s";
685  printf(2 + (b ? s2 : s5));  // expected-warning{{more '%' conversions than data arguments}}
686  // expected-note@-2{{format string is defined here}}
687  printf(2 + (b ? s2 : s5), "");      // no-warning
688  printf(2 + (b ? s1 : s2 - 2), "");  // no-warning
689
690  const char s6[] = "%s string";
691  printf(2 + (b ? s1 : s6 - 2));  // expected-warning{{more '%' conversions than data arguments}}
692  // expected-note@-2{{format string is defined here}}
693  printf(1 ? s2 + 2 : s2);  // no-warning
694  printf(0 ? s2 : s2 + 2);  // no-warning
695  printf(2 + s2 + 5 * 3 - 16, "");  // expected-warning{{data argument not used}}
696
697  const char s7[] = "%s string %s %s";
698  printf(s7 + 3, "");  // expected-warning{{more '%' conversions than data arguments}}
699  // expected-note@-2{{format string is defined here}}
700}
701
702void PR30481() {
703  // This caused crashes due to invalid casts.
704  printf(1 > 0); // expected-warning{{format string is not a string literal}} expected-warning{{incompatible integer to pointer conversion}} expected-note@format-strings.c:*{{passing argument to parameter here}} expected-note{{to avoid this}}
705}
706