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