1 /* PR middle-end/88993 - GCC 9 -Wformat-overflow=2 should reflect real
2    libc limits
3    Verify that -Wformat-overflow=2 "may exceed" warnings are not issued
4    for printf family of functions.
5    { dg-do compile }
6    { dg-options "-O -Wformat -Wformat-overflow=2 -ftrack-macro-expansion=0" }
7    { dg-require-effective-target int32plus } */
8 
9 #define INT_MAX __INT_MAX__
10 
11 typedef __SIZE_TYPE__ size_t;
12 
13 #if !__cplusplus
14 typedef __WCHAR_TYPE__ wchar_t;
15 #endif
16 
17 typedef struct FILE FILE;
18 
19 FILE *fp;
20 
21 #define T(...) __builtin_fprintf (__VA_ARGS__)
22 
23 /* Exercise the "%c" directive with constant arguments.  */
24 
test_fprintf_c_const(int width)25 void test_fprintf_c_const (int width)
26 {
27   /* Verify that a warning is only issued when the output is definitely
28      exceeded but not when exceeding it is possible but not inevitable.
29      Also verify that a note is printed with amount of output produced
30      by the call (the result - 1).  */
31   T (fp, "%2147483647c", '1');
32   T (fp, "X%2147483647c", '2');   /* { dg-warning ".%2147483647c. directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
33   /* { dg-message ".__builtin_fprintf. output 2147483649 bytes" "note" { target *-*-* } .-1 } */
34   T (fp, "%2147483647cY", '3');   /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
35 
36   T (fp, "%2147483648c", '1');    /* { dg-warning ".%2147483648c. directive output of 2147483648 bytes exceeds .INT_MAX." } */
37   T (fp, "X%2147483649c", '2');   /* { dg-warning ".%2147483649c. directive output of 2147483649 bytes exceeds .INT_MAX." } */
38   T (fp, "%2147483650cY", '3');   /* { dg-warning ".%2147483650c. directive output of 2147483650 bytes exceeds .INT_MAX." } */
39 
40   T (fp, "%*c", INT_MAX, '1');
41   T (fp, "X%*c", INT_MAX, '1');   /* { dg-warning ".%*c. directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
42   T (fp, "%*cY", INT_MAX, '1');   /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
43 
44   T (fp, "X%*c", INT_MAX - 1, '1');
45   T (fp, "%*cY", INT_MAX - 1, '1');
46 
47   T (fp, "%*cY", INT_MAX, '1');   /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
48   T (fp, "X%*c", INT_MAX, '1');   /* { dg-warning ".%*c. directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
49 }
50 
51 /* Exercise the "%c" directive with arguments in a known range.  */
52 
test_fprintf_c_range(int width)53 void test_fprintf_c_range (int width)
54 {
55   /* Verify that an known upper bound doesn't trigger a warning.  */
56   if (width > INT_MAX - 1)
57     width = INT_MAX - 1;
58 
59   T (fp, "%*c", width, '1');
60   T (fp, "X%*c", width, '1');
61   T (fp, "%*cY", width, '1');
62 
63   T (fp, "%*c", width, '1');
64   T (fp, "X%*c", width, '1');
65   T (fp, "%*cY", width, '1');
66 
67   T (fp, "%*c%*c", width, '1', width, '2');
68   T (fp, "X%*cY%*cZ", width, '1', width, '2');
69 
70   /* Verify that a lower bound in excess of 4095 doesn't trigger
71      a warning.  */
72   if (width < 4096)
73     width = 4096;
74 
75   T (fp, "%*c", width, '1');
76   T (fp, "X%*c", width, '1');
77   T (fp, "%*cY", width, '1');
78 
79   /* Verify that a large lower bound triggers a warning when the total
80      result of the function definitely exceeds INT_MAX.  */
81   if (width < INT_MAX - 1)
82     width = INT_MAX - 1;
83 
84   T (fp, "%*c", width, '1');
85   T (fp, "X%*c", width, '2');
86   T (fp, "%*cY", width, '3');
87   T (fp, "X%*cY", width, '4');    /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
88   /* { dg-message ".__builtin_fprintf. output 2147483649 bytes" "note" { target *-*-* } .-1 } */
89 }
90 
91 
92 /* Exercise the "%s" directive.  */
93 
test_fprintf_s_const(int width,const char * s)94 void test_fprintf_s_const (int width, const char *s)
95 {
96   T (fp, "%2147483647s", s);
97   T (fp, "%2147483647s", "1");
98 
99   T (fp, "%2147483647.2147483647s", s);
100   T (fp, "%2147483647.2147483647s", "12");
101 
102   T (fp, "X%2147483647s", s);     /* { dg-warning ".%2147483647s. directive output between 2147483647 and \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
103   T (fp, "%2147483647sY", s);     /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
104 
105   T (fp, "X%2147483647.1s", s);   /* { dg-warning ".%2147483647\\\.1s. directive output of 2147483647 bytes causes result to exceed .INT_MAX." } */
106   T (fp, "%2147483647.2sY", s);   /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
107 
108   T (fp, "X%1.2147483647s", s);
109   T (fp, "%2.2147483647sY", s);
110 
111   T (fp, "X%1.2147483647s", "123");
112   T (fp, "%2.2147483647sY", "1234");
113 
114   T (fp, "%2147483648s", s);      /* { dg-warning "%2147483648s. directive output between 2147483648 and \[0-9\]+ bytes exceeds .INT_MAX." } */
115   T (fp, "X%2147483649s", s);     /* { dg-warning "%2147483649s. directive output between 2147483649 and \[0-9\]+ bytes exceeds .INT_MAX." } */
116   T (fp, "%2147483650sY", s);     /* { dg-warning ".%2147483650s. directive output between 2147483650 and \[0-9\]+ bytes exceeds .INT_MAX." } */
117 
118   T (fp, "%*s", INT_MAX, s);
119   T (fp, "X%*s", INT_MAX, s);     /* { dg-warning ".%\\\*s. directive output between 2147483647 and \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
120   T (fp, "%*sY", INT_MAX, s);     /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
121 
122   T (fp, "X%*s", INT_MAX - 1, s);
123   T (fp, "%*sY", INT_MAX - 1, s);
124 
125   T (fp, "%*sY", INT_MAX, s);     /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
126   T (fp, "X%*s", INT_MAX, s);     /* { dg-warning ".%\\\*s. directive output between 2147483647 and \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
127 
128   if (width > INT_MAX - 1)
129     width = INT_MAX - 1;
130 
131   T (fp, "%*s", width, s);
132   T (fp, "X%*s", width, s);
133   T (fp, "%*sY", width, s);
134 
135   T (fp, "%*s", width, s);
136   T (fp, "X%*s", width, s);
137   T (fp, "%*sY", width, s);
138 
139   T (fp, "%*s%*s", width, s, width, s);
140   T (fp, "X%*sY%*sZ", width, s, width, s);
141 
142   if (width < 4096)
143     width = 4096;
144 
145   T (fp, "%*s", width, s);
146   T (fp, "X%*s", width, s);
147   T (fp, "%*sY", width, s);
148 
149   if (width < INT_MAX - 1)
150     width = INT_MAX - 1;
151 
152   T (fp, "%*s", width, s);
153   T (fp, "X%*s", width, s);
154   T (fp, "%*sY", width, s);
155   T (fp, "X%*sY", width, s);      /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
156 }
157 
158 /* Exercise the "%ls" directive.  */
159 
test_fprintf_ls_const(int width,const wchar_t * s)160 void test_fprintf_ls_const (int width, const wchar_t *s)
161 {
162   T (fp, "%2147483647ls", s);
163   T (fp, "X%2147483647ls", s);    /* { dg-warning ".%2147483647ls. directive output between 2147483647 and \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
164   T (fp, "%2147483647lsY", s);    /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
165 
166   T (fp, "%2147483648ls", s);     /* { dg-warning "%2147483648ls. directive output between 2147483648 and \[0-9\]+ bytes exceeds .INT_MAX." } */
167   T (fp, "X%2147483649ls", s);    /* { dg-warning "%2147483649ls. directive output between 2147483649 and \[0-9\]+ bytes exceeds .INT_MAX." } */
168   T (fp, "%2147483650lsY", s);    /* { dg-warning ".%2147483650ls. directive output between 2147483650 and \[0-9\]+ bytes exceeds .INT_MAX." } */
169 
170   T (fp, "%*ls", INT_MAX, s);
171   T (fp, "X%*ls", INT_MAX, s);    /* { dg-warning ".%\\\*ls. directive output between 2147483647 and \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
172   T (fp, "%*lsY", INT_MAX, s);    /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
173 
174   T (fp, "X%*ls", INT_MAX - 1, s);
175   T (fp, "%*lsY", INT_MAX - 1, s);
176 
177   T (fp, "%*lsY", INT_MAX, s);    /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
178   T (fp, "X%*ls", INT_MAX, s);     /* { dg-warning ".%\\\*ls. directive output between 2147483647 and \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
179 
180   if (width > INT_MAX - 1)
181     width = INT_MAX - 1;
182 
183   T (fp, "%*ls", width, s);
184   T (fp, "X%*ls", width, s);
185   T (fp, "%*lsY", width, s);
186 
187   T (fp, "%*ls", width, s);
188   T (fp, "X%*ls", width, s);
189   T (fp, "%*lsY", width, s);
190 
191   T (fp, "%*ls%*ls", width, s, width, s);
192   T (fp, "X%*lsY%*lsZ", width, s, width, s);
193 
194   if (width < 4096)
195     width = 4096;
196 
197   T (fp, "%*ls", width, s);
198   T (fp, "X%*ls", width, s);
199   T (fp, "%*lsY", width, s);
200 
201   if (width < INT_MAX - 1)
202     width = INT_MAX - 1;
203 
204   T (fp, "%*ls", width, s);
205   T (fp, "X%*ls", width, s);
206   T (fp, "%*lsY", width, s);
207   T (fp, "X%*lsY", width, s);     /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
208 }
209 
210 
211 /* Also exercise fprintf_chk.  */
212 
213 #undef T
214 #define T(...) __builtin___fprintf_chk (__VA_ARGS__)
215 
test_fprintf_chk_s_const(int width)216 void test_fprintf_chk_s_const (int width)
217 {
218   const char *s = "0123456789";
219 
220   T (fp, 0, "%2147483647s", s);
221   T (fp, 0, "X%2147483647s", s);    /* { dg-warning ".%2147483647s. directive output of 2147483647 bytes causes result to exceed .INT_MAX." } */
222   T (fp, 0, "%2147483647sY", s);    /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
223 
224   T (fp, 0, "%2147483648s", s);      /* { dg-warning "%2147483648s. directive output of 2147483648 bytes exceeds .INT_MAX." } */
225   T (fp, 0, "X%2147483649s", s);     /* { dg-warning "%2147483649s. directive output of 2147483649 bytes exceeds .INT_MAX." } */
226   T (fp, 0, "%2147483650sY", s);     /* { dg-warning ".%2147483650s. directive output of 2147483650 bytes exceeds .INT_MAX." } */
227 
228   T (fp, 0, "%*s", INT_MAX, s);
229   T (fp, 0, "X%*s", INT_MAX, s);     /* { dg-warning ".%\\\*s. directive output of 2147483647 bytes causes result to exceed .INT_MAX." } */
230   T (fp, 0, "%*sY", INT_MAX, s);     /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
231 
232   T (fp, 0, "X%*s", INT_MAX - 1, s);
233   T (fp, 0, "%*sY", INT_MAX - 1, s);
234 
235   T (fp, 0, "%*sY", INT_MAX, s);     /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
236   T (fp, 0, "X%*s", INT_MAX, s);     /* { dg-warning ".%\\\*s. directive output of 2147483647 bytes causes result to exceed .INT_MAX." } */
237 
238   if (width > INT_MAX - 1)
239     width = INT_MAX - 1;
240 
241   T (fp, 0, "%*s", width, s);
242   T (fp, 0, "X%*s", width, s);
243   T (fp, 0, "%*sY", width, s);
244 
245   T (fp, 0, "%*s", width, s);
246   T (fp, 0, "X%*s", width, s);
247   T (fp, 0, "%*sY", width, s);
248 
249   T (fp, 0, "%*s%*s", width, s, width, s);
250   T (fp, 0, "X%*sY%*sZ", width, s, width, s);
251 
252   if (width < 4096)
253     width = 4096;
254 
255   T (fp, 0, "%*s", width, s);
256   T (fp, 0, "X%*s", width, s);
257   T (fp, 0, "%*sY", width, s);
258 
259   if (width < INT_MAX - 1)
260     width = INT_MAX - 1;
261 
262   T (fp, 0, "%*s", width, s);
263   T (fp, 0, "X%*s", width, s);
264   T (fp, 0, "%*sY", width, s);
265   T (fp, 0, "X%*sY", width, s);      /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
266 }
267 
268 
269 /* And finally exercise fprintf_unlocked.  */
270 
271 #undef T
272 #define T(...) __builtin_fprintf_unlocked (__VA_ARGS__)
273 
test_fprintf_unlocked_s_const(int width)274 void test_fprintf_unlocked_s_const (int width)
275 {
276   const char *s = "0123456789";
277 
278   T (fp, "%2147483647s", s);
279   T (fp, "X%2147483647s", s);     /* { dg-warning ".%2147483647s. directive output of 2147483647 bytes causes result to exceed .INT_MAX." } */
280   T (fp, "%2147483647sY", s);     /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
281 
282   T (fp, "%2147483648s", s);      /* { dg-warning "%2147483648s. directive output of 2147483648 bytes exceeds .INT_MAX." } */
283   T (fp, "X%2147483649s", s);     /* { dg-warning "%2147483649s. directive output of 2147483649 bytes exceeds .INT_MAX." } */
284   T (fp, "%2147483650sY", s);     /* { dg-warning ".%2147483650s. directive output of 2147483650 bytes exceeds .INT_MAX." } */
285 
286   T (fp, "%*s", INT_MAX, s);
287   T (fp, "X%*s", INT_MAX, s);     /* { dg-warning ".%\\\*s. directive output of 2147483647 bytes causes result to exceed .INT_MAX." } */
288   T (fp, "%*sY", INT_MAX, s);     /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
289 
290   T (fp, "X%*s", INT_MAX - 1, s);
291   T (fp, "%*sY", INT_MAX - 1, s);
292 
293   T (fp, "%*sY", INT_MAX, s);     /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
294   T (fp, "X%*s", INT_MAX, s);     /* { dg-warning ".%\\\*s. directive output of 2147483647 bytes causes result to exceed .INT_MAX." } */
295 
296   if (width > INT_MAX - 1)
297     width = INT_MAX - 1;
298 
299   T (fp, "%*s", width, s);
300   T (fp, "X%*s", width, s);
301   T (fp, "%*sY", width, s);
302 
303   T (fp, "%*s", width, s);
304   T (fp, "X%*s", width, s);
305   T (fp, "%*sY", width, s);
306 
307   T (fp, "%*s%*s", width, s, width, s);
308   T (fp, "X%*sY%*sZ", width, s, width, s);
309 
310   if (width < 4096)
311     width = 4096;
312 
313   T (fp, "%*s", width, s);
314   T (fp, "X%*s", width, s);
315   T (fp, "%*sY", width, s);
316 
317   if (width < INT_MAX - 1)
318     width = INT_MAX - 1;
319 
320   T (fp, "%*s", width, s);
321   T (fp, "X%*s", width, s);
322   T (fp, "%*sY", width, s);
323   T (fp, "X%*sY", width, s);      /* { dg-warning ".Y. directive output of 1 bytes causes result to exceed .INT_MAX." } */
324 }
325