* tree-loop-distribution.c (INCLUDE_ALGORITHM): New header file.
[official-gcc.git] / gcc / testsuite / gcc.dg / tree-ssa / builtin-sprintf-warn-2.c
blob60695b88e47b2d34d120d28ee6afe7732c573da7
1 /* { dg-do compile } */
2 /* { dg-options "-Wformat -Wformat-overflow=2 -ftrack-macro-expansion=0" } */
4 /* When debugging, define LINE to the line number of the test case to exercise
5 and avoid exercising any of the others. The buffer and objsize macros
6 below make use of LINE to avoid warnings for other lines. */
7 #ifndef LINE
8 # define LINE 0
9 #endif
11 char buffer [256];
12 extern char *ptr;
14 #define buffer(size) \
15 (!LINE || __LINE__ == LINE ? buffer + sizeof buffer - size : ptr)
17 #define objsize(size) (!LINE || __LINE__ == LINE ? size : __SIZE_MAX__ / 2)
19 typedef __SIZE_TYPE__ size_t;
21 #if !__cplusplus
22 typedef __WCHAR_TYPE__ wchar_t;
23 #endif
25 typedef unsigned char UChar;
27 #define T(size, fmt, ...) \
28 __builtin_sprintf (buffer (size), fmt, __VA_ARGS__)
30 __builtin_va_list va;
32 /* Exercise buffer overflow detection with const string arguments. */
34 void test_s_const (void)
36 /* Wide string literals are handled slightly differently than
37 at level 1. At level 1, each wide character is assumed to
38 convert into a single byte. At level 2, they are assumed
39 to convert into at least one byte. */
40 T (0, "%ls", L""); /* { dg-warning "nul past the end" } */
41 T (1, "%ls", L"");
42 T (1, "%ls", L"\0");
43 T (1, "%1ls", L""); /* { dg-warning "nul past the end" } */
45 T (0, "%*ls", 0, L""); /* { dg-warning "nul past the end" } */
46 T (1, "%*ls", 0, L"");
47 T (1, "%*ls", 0, L"\0");
48 T (1, "%*ls", 1, L""); /* { dg-warning "nul past the end" } */
50 /* A wide character converts into between zero and MB_LEN_MAX bytes
51 (although individual ASCII characters are assumed to convert into
52 1 bt %lc so this could be made smarter. */
53 T (1, "%ls", L"1"); /* { dg-warning "directive writing up to 6 bytes into a region of size 1" } */
54 T (1, "%.0ls", L"1");
55 T (2, "%.0ls", L"1");
56 T (2, "%.1ls", L"1");
57 T (2, "%.2ls", L"1"); /* { dg-warning "nul past the end" } */
58 T (2, "%.3ls", L"1"); /* { dg-warning "directive writing up to 3 bytes into a region of size 2" } */
59 T (2, "%.7ls", L"1"); /* { dg-warning "directive writing up to 6 bytes into a region of size 2" } */
60 T (2, "%.2ls", L"12"); /* { dg-warning "nul past the end" } */
62 /* The "%.2ls" directive below will write at a minimum 1 byte (because
63 L"1" is known and can be assumed to convert to at least one multibyte
64 character), and at most 2 bytes because of the precision. Since its
65 output is explicitly bounded it is diagnosed. */
66 T (2, "%.2ls", L"1"); /* { dg-warning "nul past the end" } */
67 T (2, "%.*ls", 2, L"1"); /* { dg-warning "nul past the end" } */
69 /* The following three are constrained by the precision to at most
70 that many bytes of the converted wide string plus a terminating NUL. */
71 T (2, "%.0ls", L"1");
72 T (2, "%.1ls", L"1");
73 T (3, "%.2ls", L"1");
74 T (3, "%.2ls", L"12");
75 T (3, "%.3ls", L"12"); /* { dg-warning "nul past the end" } */
76 T (4, "%.3ls", L"123");
77 T (4, "%.4ls", L"123"); /* { dg-warning "nul past the end" } */
78 T (4, "%.5ls", L"123"); /* { dg-warning "directive writing up to 5 bytes into a region of size 4" } */
79 T (4, "%.6ls", L"123"); /* { dg-warning "directive writing up to 6 bytes into a region of size 4" } */
83 struct Arrays {
84 char a1 [1];
85 char a2 [2];
86 char a3 [3];
87 char a4 [4];
88 char a0 [0];
89 char ax [];
92 /* Exercise buffer overflow detection with non-const string arguments. */
94 void test_s_nonconst (int w, int p, const char *s, const wchar_t *ws,
95 struct Arrays *a)
97 T (0, "%s", s); /* { dg-warning "into a region" } */
98 T (1, "%s", s); /* { dg-warning "nul past the end" } */
99 T (1, "%1s", s); /* { dg-warning "writing a terminating nul" } */
100 T (1, "%.0s", s);
101 T (1, "%.1s", s); /* { dg-warning "may write a terminating nul" } */
102 T (1, "%*s", 0, s); /* { dg-warning "may write a terminating nul" } */
103 T (1, "%*s", 1, s); /* { dg-warning "writing a terminating nul" } */
104 T (1, "%*s", 2, s); /* { dg-warning "directive writing 2 or more bytes" } */
105 T (1, "%*s", 3, s); /* { dg-warning "directive writing 3 or more bytes" } */
107 T (1, "%.*s", 1, s); /* { dg-warning "may write a terminating nul" } */
108 T (1, "%.*s", 2, s); /* { dg-warning "writing up to 2 bytes" } */
109 T (1, "%.*s", 3, s); /* { dg-warning "writing up to 3 bytes" } */
111 T (1, "%.0ls", ws);
112 T (1, "%.1ls", ws); /* { dg-warning "may write a terminating nul" } */
113 T (1, "%ls", ws); /* { dg-warning "may write a terminating nul" } */
115 /* Verify that the size of the array is used in lieu of its length. */
116 T (1, "%s", a->a1);
118 /* In the following test, since the length of the strings isn't known,
119 their type (the array) is used to bound the maximum length to 1,
120 which means the "%s" directive would not overflow the buffer,
121 but it would leave no room for the terminating nul. */
122 T (1, "%s", a->a2); /* { dg-warning "may write a terminating nul" } */
124 /* Unlike in the test above, since the length of the string is bounded
125 by the array type to at most 2, the "%s" directive is diagnosed firts,
126 preventing the diagnostic about the terminatinb nul. */
127 T (1, "%s", a->a3); /* { dg-warning "directive writing up to 2 bytes" } */
129 /* The length of a zero length array and flexible array member is
130 unknown and at leve 2 assumed to be at least 1. */
131 T (1, "%s", a->a0); /* { dg-warning "may write a terminating nul" } */
132 T (1, "%s", a->ax); /* { dg-warning "may write a terminating nul" } */
134 T (2, "%s", a->a0);
135 T (2, "%s", a->ax);
138 /* Exercise buffer overflow detection with non-const integer arguments. */
140 void test_hh_nonconst (int w, int p, int x, unsigned y)
142 T (1, "%hhi", x); /* { dg-warning "into a region" } */
143 T (2, "%hhi", x); /* { dg-warning "into a region" } */
144 T (3, "%hhi", x); /* { dg-warning "into a region" } */
145 T (4, "%hhi", x); /* { dg-warning "may write a terminating nul past the end of the destination" } */
147 T (1, "%hhi", y); /* { dg-warning "between 1 and 4 bytes" } */
148 T (2, "%hhi", y); /* { dg-warning "into a region" } */
149 T (3, "%hhi", y); /* { dg-warning "into a region" } */
150 T (4, "%hhi", y); /* { dg-warning "may write a terminating nul past the end of the destination" } */
152 /* Negative precision is treated as if none were specified. */
153 T (1, "%.*hhi", -1, x); /* { dg-warning "between 1 and 4 bytes" } */
154 T (2, "%.*hhi", -1, x); /* { dg-warning "into a region" } */
155 T (3, "%.*hhi", -1, x); /* { dg-warning "into a region" } */
156 T (4, "%.*hhi", -1, x); /* { dg-warning "may write a terminating nul past the end of the destination" } */
158 /* Zero precision means that zero argument formats as no bytes unless
159 length or flags make it otherwise. */
160 T (1, "%.*hhi", 0, x); /* { dg-warning "writing up to 4 bytes" } */
161 T (2, "%.*hhi", 0, x); /* { dg-warning "writing up to 4 bytes" } */
162 T (3, "%.*hhi", 0, x); /* { dg-warning "writing up to 4 bytes" } */
163 T (4, "%.*hhi", 0, x); /* { dg-warning "may write a terminating nul past the end of the destination" } */
165 T (1, "%.*hhi", 0, y); /* { dg-warning "writing up to 4 bytes" } */
166 T (2, "%.*hhi", 0, y); /* { dg-warning "writing up to 4 bytes" } */
167 T (3, "%.*hhi", 0, y); /* { dg-warning "writing up to 4 bytes" } */
168 T (4, "%.*hhi", 0, y); /* { dg-warning "may write a terminating nul past the end of the destination" } */
170 T (1, "%#.*hhi", 0, y); /* { dg-warning "writing up to 4 bytes" } */
171 /* { dg-warning ".#. flag used" "-Wformat" { target *-*-* } .-1 } */
172 T (1, "%+.*hhi", 0, y); /* { dg-warning "between 1 and 4 bytes" } */
173 T (1, "%-.*hhi", 0, y); /* { dg-warning "writing up to 4 bytes" } */
174 T (1, "% .*hhi", 0, y); /* { dg-warning "between 1 and 4 bytes" } */
176 T (1, "%#.*hhi", 1, y); /* { dg-warning "between 1 and 4 bytes" } */
177 /* { dg-warning ".#. flag used" "-Wformat" { target *-*-* } .-1 } */
178 T (1, "%+.*hhi", 1, y); /* { dg-warning "between 2 and 4 bytes" } */
179 T (1, "%-.*hhi", 1, y); /* { dg-warning "between 1 and 4 bytes" } */
180 T (1, "% .*hhi", 1, y); /* { dg-warning "between 2 and 4 bytes" } */
182 T (1, "%#.*hhi", p, y); /* { dg-warning "writing up to \[0-9\]+ bytes" } */
183 /* { dg-warning ".#. flag used" "-Wformat" { target *-*-* } .-1 } */
184 T (1, "%+.*hhi", p, y); /* { dg-warning "writing 1 or more bytes|writing between 1 and \[0-9\]+ bytes" } */
185 T (1, "%-.*hhi", p, y); /* { dg-warning "writing up to \[0-9\]+ bytes" } */
186 T (1, "% .*hhi", p, y); /* { dg-warning "writing between 1 and \[0-9\]+ bytes|writing 1 or more bytes" } */
188 T (1, "%#.*hhu", 0, y); /* { dg-warning "writing up to 3 bytes" } */
189 /* { dg-warning ".#. flag used" "-Wformat" { target *-*-* } .-1 } */
190 T (1, "%+.*hhu", 0, y); /* { dg-warning "writing up to 3 bytes" } */
191 /* { dg-warning ".\\+. flag used" "-Wformat" { target *-*-* } .-1 } */
192 T (1, "%-.*hhu", 0, y); /* { dg-warning "writing up to 3 bytes" } */
193 T (1, "% .*hhu", 0, y); /* { dg-warning "writing up to 3 bytes" } */
194 /* { dg-warning ". . flag used" "-Wformat" { target *-*-* } .-1 } */
197 void test_h_nonconst (int x)
199 extern UChar uc;
201 T (1, "%hi", uc); /* { dg-warning "into a region" } */
202 T (2, "%hi", uc); /* { dg-warning "into a region" } */
203 /* Formatting an 8-bit unsigned char as a signed short (or any other
204 type with greater precision) can write at most 3 characters. */
205 T (3, "%hi", uc); /* { dg-warning "terminating nul past" } */
206 T (4, "%hi", uc);
208 /* Verify that the same thing works when the int argument is cast
209 to unsigned char. */
210 T (1, "%hi", (UChar)x); /* { dg-warning "into a region" } */
211 T (2, "%hi", (UChar)x); /* { dg-warning "into a region" } */
212 T (3, "%hi", (UChar)x); /* { dg-warning "may write a terminating nul past the end of the destination" } */
213 T (4, "%hi", (UChar)x);
216 void test_i_nonconst (int x)
218 extern UChar uc;
220 T (1, "%i", uc); /* { dg-warning "into a region" } */
221 T (2, "%i", uc); /* { dg-warning "into a region" } */
222 T (3, "%i", uc); /* { dg-warning "terminating nul past" } */
223 T (4, "%i", uc);
225 T (1, "%i", (UChar)x); /* { dg-warning "into a region" } */
226 T (2, "%i", (UChar)x); /* { dg-warning "into a region" } */
227 T (3, "%i", (UChar)x); /* { dg-warning "terminating nul past" } */
228 T (4, "%i", (UChar)x);
230 /* Verify the same thing using a bit-field. */
231 extern struct {
232 unsigned int b1: 1;
233 unsigned int b2: 2;
234 unsigned int b3: 3;
235 unsigned int b4: 4;
236 int sb4: 4;
237 unsigned int b5: 5;
238 unsigned int b6: 6;
239 unsigned int b7: 7;
240 unsigned int b8: 8;
241 } bf, abf[], *pbf;
243 T (1, "%i", bf.b1); /* { dg-warning "nul past the end" } */
244 T (1, "%i", abf [x].b1); /* { dg-warning "nul past the end" } */
245 T (1, "%i", pbf->b1); /* { dg-warning "nul past the end" } */
246 /* A one bit bit-field can only be formatted as '0' or '1'. Similarly,
247 two- and three-bit bit-fields can only be formatted as a single
248 decimal digit. */
249 T (2, "%i", bf.b1);
250 T (2, "%i", abf [x].b1);
251 T (2, "%i", pbf->b1);
252 T (2, "%i", bf.b2);
253 T (2, "%i", abf [x].b2);
254 T (2, "%i", pbf->b2);
255 T (2, "%i", bf.b3);
256 T (2, "%i", abf [x].b3);
257 T (2, "%i", pbf->b3);
258 /* A four-bit bit-field can be formatted as either one or two digits. */
259 T (2, "%i", bf.b4); /* { dg-warning "nul past the end" } */
260 T (2, "%i", abf [x].b4); /* { dg-warning "nul past the end" } */
261 T (2, "%i", pbf->b4); /* { dg-warning "nul past the end" } */
263 T (3, "%i", bf.b4);
264 T (3, "%i", pbf->b4);
265 T (3, "%i", bf.b5);
266 T (3, "%i", pbf->b5);
267 T (3, "%i", bf.b6);
268 T (3, "%i", pbf->b6);
269 T (3, "%i", bf.b7); /* { dg-warning "nul past the end" } */
270 T (3, "%i", pbf->b7); /* { dg-warning "nul past the end" } */
272 T (1, "%i", bf.b8); /* { dg-warning "into a region" } */
273 T (2, "%i", bf.b8); /* { dg-warning "into a region" } */
274 /* Formatting an 8-bit unsigned char as a signed short (or any other
275 type with greater precision) int can write at most 3 characters. */
276 T (3, "%i", bf.b8); /* { dg-warning "terminating nul past" } */
277 T (4, "%i", bf.b8);
279 T (1, "%i", bf.b8); /* { dg-warning "into a region" } */
280 T (2, "%i", bf.b8); /* { dg-warning "into a region" } */
281 T (3, "%i", bf.b8); /* { dg-warning "terminating nul past" } */
283 T (2, "%i", bf.sb4); /* { dg-warning "terminating nul past" } */
284 T (3, "%i", bf.sb4);
285 T (4, "%i", bf.sb4);