1 /* { dg-do compile } */
2 /* { dg-options "-Wformat -Wformat-overflow=1 -ftrack-macro-expansion=0" } */
3 /* { dg-require-effective-target int32plus } */
4 
5 /* When debugging, define LINE to the line number of the test case to exercise
6    and avoid exercising any of the others.  The buffer and objsize macros
7    below make use of LINE to avoid warnings for other lines.  */
8 #ifndef LINE
9 # define LINE 0
10 #endif
11 
12 #define INT_MAX __INT_MAX__
13 
14 typedef __builtin_va_list va_list;
15 
16 
17 char buffer [256];
18 extern char *ptr;
19 
20 /* Evaluate to an array of SIZE characters when non-negative, or to
21    a pointer to an unknown object otherwise.  */
22 #define buffer(size)					\
23   ((0 <= size) ? buffer + sizeof buffer - (size) : ptr)
24 
25 /* Evaluate to SIZE when non-negative, or to SIZE_MAX otherise.  */
26 #define objsize(size) ((0 <= size) ? (size) : __SIZE_MAX__)
27 
28 typedef __SIZE_TYPE__ size_t;
29 
30 #if !__cplusplus
31 typedef __WCHAR_TYPE__ wchar_t;
32 #endif
33 
34 typedef __WINT_TYPE__ wint_t;
35 
36 typedef unsigned char UChar;
37 
38 /* Constants used to verify the pass can determine their values even
39    without optimization.  */
40 const int cst0   =  0;
41 const int cst1   =  1;
42 const int cst10  = 10;
43 
44 /* Initialized global variables used to verify that the pass doesn't
45    use their initial values (they could be modified by calls to other
46    functions).  */
47 int var0  =  0;
48 int var10 = 10;
49 
50 const char s0[] = "";
51 const char s1[] = "1";
52 const char s2[] = "12";
53 const char s3[] = "123";
54 const char s4[] = "1234";
55 const char s5[] = "12345";
56 const char s6[] = "123456";
57 const char s7[] = "1234567";
58 const char s8[] = "12345678";
59 
60 void sink (void*, ...);
61 
62 int dummy_sprintf (char*, const char*, ...);
63 int dummy_snprintf (char*, size_t, const char*, ...);
64 int dummy_vsprintf (char*, const char*, va_list);
65 int dummy_vsnprintf (char*, size_t, const char*, va_list);
66 int dummy___sprintf_chk (char*, int, size_t, const char*, ...);
67 int dummy___snprintf_chk (char*, size_t, int, size_t, const char*, ...);
68 int dummy___vsprintf_chk (char*, int, size_t, const char*, va_list);
69 int dummy___vsnprintf_chk (char*, size_t, int, size_t, const char*, va_list);
70 
71 /* Helper to expand function to either __builtin_f or dummy_f to
72    make debugging GCC easy.  */
73 #define FUNC(f)							\
74   ((!LINE || LINE == __LINE__) ? __builtin_ ## f : dummy_ ## f)
75 
76 /* Macro to verify that calls to __builtin_sprintf (i.e., with no size
77    argument) issue diagnostics by correctly determining the size of
78    the destination buffer.  */
79 #define T(size, ...)						\
80   (FUNC (sprintf) (buffer (size),  __VA_ARGS__),		\
81    sink (buffer, ptr))
82 
83 /* Exercise the "%%" directive.  */
84 
test_sprintf_percent(void)85 void test_sprintf_percent (void)
86 {
87   T (-1, "%%");
88   T ( 0, "%%");                 /* { dg-warning ".%%. directive writing 1 byte into a region of size 0" } */
89   T ( 1, "%%");                 /* { dg-warning "writing a terminating nul past the end" } */
90   T ( 2, "%%");
91   T ( 2, "%%%%");               /* { dg-warning "writing a terminating nul past the end" } */
92   T ( 3, "%%%%");
93   T ( 3, "%%X%%");              /* { dg-warning "writing a terminating nul past the end" } */
94   T ( 4, "%%X%%");
95 }
96 
97 /* Exercise the "%c" and "%lc" directive with constant arguments.  */
98 
test_sprintf_c_const(void)99 void test_sprintf_c_const (void)
100 {
101   T (-1, "%c",    0);           /* No warning for unknown destination size.  */
102   T ( 0, "%c",    0);           /* { dg-warning ".%c. directive writing 1 byte into a region of size 0" } */
103   T ( 1, "%c",    0);           /* { dg-warning "writing a terminating nul past the end" } */
104   T ( 1, "%c",   '1');          /* { dg-warning "nul past the end" } */
105   T ( 2, "%c",   '1');
106   T ( 2, "%2c",  '1');          /* { dg-warning "nul past the end" } */
107   T ( 2, "%3c",  '1');          /* { dg-warning "into a region" } */
108   T ( 2, "%c%c", '1', '2');     /* { dg-warning "nul past the end" } */
109   T ( 3, "%c%c", '1', '2');
110 
111   T ( 2, "%1$c%2$c", '1', '2'); /* { dg-warning "does not support %n.|nul past the end" } */
112   T ( 3, "%1$c%2$c", '1', '2');
113 
114   /* Verify that a warning is issued for exceeding INT_MAX bytes and
115      not otherwise.  */
116   T (-1, "%*c",  INT_MAX - 1, '1');
117   T (-1, "%*c",  INT_MAX,     '1');
118   T (-1, "X%*c", INT_MAX - 1, '1');
119   T (-1, "X%*c", INT_MAX,     '1'); /* { dg-warning "directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
120 
121   T (-1, "%*c%*c", INT_MAX - 1, '1', INT_MAX - 1, '2'); /* { dg-warning "directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
122 
123   T (-1, "%*cX", INT_MAX - 2, '1');
124   T (-1, "%*cX", INT_MAX - 1, '1');
125   T (-1, "%*cX", INT_MAX,     '1'); /* { dg-warning "output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
126 }
127 
128 /* Verify that no warning is issued for calls that write into a flexible
129    array member whose size isn't known.  Also verify that calls that use
130    a flexible array member as an argument to the "%s" directive do not
131    cause a warning.  */
132 
test_sprintf_flexarray(void * p,int i)133 void test_sprintf_flexarray (void *p, int i)
134 {
135   struct S
136   {
137     int n;
138     char a[];
139   } *s = p;
140 
141   FUNC (sprintf)(s->a, "%c",       'x');
142 
143   FUNC (sprintf)(s->a, "%-s",      "");
144   FUNC (sprintf)(s->a, "%-s",      "abc");
145   FUNC (sprintf)(s->a, "abc%sghi", "def");
146 
147   FUNC (sprintf)(s->a, "%i",       1234);
148 
149   FUNC (sprintf)(buffer (1), "%-s", s->a);
150   FUNC (sprintf)(buffer (1), "%-s", s [i].a);
151   FUNC (sprintf)(buffer (2), "%-s", s->a);
152   FUNC (sprintf)(buffer (2), "%-s", s [i].a);
153 }
154 
155 /* Same as above but for zero-length arrays.  */
156 
test_sprintf_zero_length_array(void * p,int i)157 void test_sprintf_zero_length_array (void *p, int i)
158 {
159   struct S
160   {
161     int n;
162     char a [0];
163   } *s = p;
164 
165   FUNC (sprintf)(s->a, "%c",       'x');
166 
167   FUNC (sprintf)(s->a, "%s",       "");
168   FUNC (sprintf)(s->a, "%s",       "abc");
169   FUNC (sprintf)(s->a, "abc%sghi", "def");
170 
171   FUNC (sprintf)(s->a, "%i",       1234);
172 
173   FUNC (sprintf)(buffer (1), "%s",  s->a);
174   FUNC (sprintf)(buffer (1), "%s",  s [i].a);
175 }
176 
177 #undef T
178 #define T(size, fmt, ...)						\
179   (FUNC (__sprintf_chk) (buffer (size), 0, objsize (size), fmt, __VA_ARGS__), \
180    sink (buffer, ptr))
181 
182 /* Exercise the "%c" and "%lc" directive with constant arguments.  */
183 
test_sprintf_chk_c_const(void)184 void test_sprintf_chk_c_const (void)
185 {
186   T (-1, "%c",    0);            /* No warning for unknown destination size.  */
187   /* Verify the full text of the diagnostic for just the distinct messages
188      and use abbreviations in subsequent test cases.  */
189   T (0, "%c",     0);            /* { dg-warning ".%c. directive writing 1 byte into a region of size 0" } */
190   T (1, "%c",     0);            /* { dg-warning "writing a terminating nul past the end" } */
191   T (1, "%c",   '1');            /* { dg-warning "nul past the end" } */
192   T (2, "%c",   '1');
193   T (2, "%2c",  '1');            /* { dg-warning "nul past the end" } */
194   T (2, "%3c",  '1');            /* { dg-warning "into a region" } */
195   T (2, "%c%c", '1', '2');       /* { dg-warning "nul past the end" } */
196   T (3, "%c%c", '1', '2');
197 
198   /* Wide characters.  */
199   T (0, "%lc",     (wint_t)0);   /* { dg-warning "nul past the end" } */
200   T (1, "%lc",     (wint_t)0);
201   T (1, "%lc%lc",  (wint_t)0, (wint_t)0);
202   T (2, "%lc",     (wint_t)0);
203   T (2, "%lc%lc",  (wint_t)0, (wint_t)0);
204 
205   /* The following could result in as few as no bytes and in as many as
206      MB_CUR_MAX, but since the MB_CUR_MAX value is a runtime property
207      the write cannot be reliably diagnosed.  */
208   T (2, "%lc",  (wint_t)L'1');
209   T (2, "%1lc", (wint_t)L'1');
210   /* Writing some unknown number of bytes into a field two characters wide.  */
211   T (2, "%2lc", (wint_t)L'1');          /* { dg-warning "nul past the end" } */
212 
213   T (3, "%lc%c",   (wint_t)L'1', '2');
214   /* Here in the best case each argument will format as single character,
215      causing the terminating NUL to be written past the end.  */
216   T (3, "%lc%c%c", (wint_t)L'1', '2', '3');   /* { dg-warning "nul past the end" } */
217   T (3, "%lc%lc%c", (wint_t)L'1', (wint_t)L'2', '3'); /* { dg-warning "nul past the end" } */
218 }
219 
220 /* Exercise the "%s" and "%ls" directive with constant arguments.  */
221 
test_sprintf_chk_s_const(void)222 void test_sprintf_chk_s_const (void)
223 {
224   T (-1, "%*s",  0, "");        /* No warning for unknown destination size.  */
225   T ( 0, "%*s",  0, "");        /* { dg-warning "nul past the end" } */
226   T ( 0, "%-s",     "");        /* { dg-warning "nul past the end" } */
227   T ( 0, "%*s",  0, s0);        /* { dg-warning "nul past the end" } */
228   T ( 1, "%*s",  0, "");
229   T ( 1, "%*s",  0, s0);
230   T ( 1, "%*s",  0, "\0");
231   T ( 1, "%*s",  0, "1");       /* { dg-warning "nul past the end" } */
232   T ( 1, "%*s",  0, s1);        /* { dg-warning "nul past the end" } */
233   T ( 1, "%1s",     "");        /* { dg-warning "nul past the end" } */
234   T ( 1, "%1s",     s0);        /* { dg-warning "nul past the end" } */
235   T (-1, "%1s",    "1");        /* No warning for unknown destination size.  */
236   T ( 1, "%*s",  1, "");        /* { dg-warning "nul past the end" } */
237   T ( 1, "%*s",  1, s0);        /* { dg-warning "nul past the end" } */
238   T (-1, "%*s",  1, s0);        /* No warning for unknown destination size.  */
239 
240   T (1, "%.s",     "");
241   T (1, "%.s",     "123");
242   T (1, "%.0s",    "123");
243   T (1, "%.0s",    s3);
244   T (1, "%.*s", 0, "123");
245   T (1, "%.*s", 0, s3);
246   T (1, "%.1s",    "123");      /* { dg-warning "nul past the end" } */
247   T (1, "%.1s",    s3);         /* { dg-warning "nul past the end" } */
248   T (1, "%.*s", 1, "123");      /* { dg-warning "nul past the end" } */
249   T (1, "%.*s", 1, s3);         /* { dg-warning "nul past the end" } */
250 
251   T (2, "%.*s", 0, "");
252   T (2, "%.*s", 0, "1");
253   T (2, "%.*s", 0, s1);
254   T (2, "%.*s", 0, "1\0");
255   T (2, "%.*s", 0, "12");
256   T (2, "%.*s", 0, s2);
257 
258   T (2, "%.*s", 1, "");
259   T (2, "%.*s", 1, "1");
260   T (2, "%.*s", 1, s1);
261   T (2, "%.*s", 1, "1\0");
262   T (2, "%.*s", 1, "12");
263   T (2, "%.*s", 1, s2);
264 
265   T (2, "%.*s", 2, "");
266   T (2, "%.*s", 2, "1");
267   T (2, "%.*s", 2, s1);
268   T (2, "%.*s", 2, "1\0");
269   T (2, "%.*s", 2, "12");       /* { dg-warning "nul past the end" } */
270   T (2, "%.*s", 2, s2);         /* { dg-warning "nul past the end" } */
271 
272   T (2, "%.*s", 3, "");
273   T (2, "%.*s", 3, "1");
274   T (2, "%.*s", 3, s1);
275   T (2, "%.*s", 3, "1\0");
276   T (2, "%.*s", 3, "12");       /* { dg-warning "nul past the end" } */
277   T (2, "%.*s", 3, "123");      /* { dg-warning "into a region" } */
278   T (2, "%.*s", 3, s2);         /* { dg-warning "nul past the end" } */
279   T (2, "%.*s", 3, s3);         /* { dg-warning "into a region" } */
280 
281   T (2, "%*s",  0, "");
282   T (2, "%*s",  0, "1");
283   T (2, "%*s",  0, s1);
284   T (2, "%*s",  0, "1\0");
285   T (2, "%*s",  0, "12");       /* { dg-warning "nul past the end" } */
286   T (2, "%*s",  0, s2);         /* { dg-warning "nul past the end" } */
287 
288   /* Verify that output in excess of INT_MAX bytes is diagnosed even
289      when the size of the destination object is unknown.  */
290   T (-1, "%*s",  INT_MAX - 1, "");
291   T (-1, "%*s",  INT_MAX,     "");
292   T (-1, "X%*s", INT_MAX,     ""); /* { dg-warning "directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
293 
294   /* Multiple directives.  */
295 
296   T (1, "%s%s", "", "");
297   T (1, "%s%s", s0, s0);
298   T (1, "%s%s", "", "1");       /* { dg-warning "nul past the end" } */
299   T (1, "%s%s", s0, s1);        /* { dg-warning "nul past the end" } */
300   T (1, "%s%s", "1", "");       /* { dg-warning "nul past the end" } */
301   T (1, "%s%s", s1, s0);        /* { dg-warning "nul past the end" } */
302   T (1, "%s%s", "1", "2");      /* { dg-warning "into a region" } */
303   T (1, "%s%s", s1, s1);        /* { dg-warning "into a region" } */
304 
305   T (2, "%s%s", "", "");
306   T (2, "%s%s", "", "1");
307   T (2, "%s%s", "1", "");
308   T (2, "%s%s", "", "12");      /* { dg-warning "nul past the end" } */
309   T (2, "%s%s", "1", "2");      /* { dg-warning "nul past the end" } */
310   T (2, "%s%s", "12", "2");     /* { dg-warning "into a region" } */
311   T (2, "%s%s", "1", "23");     /* { dg-warning "into a region" } */
312   T (2, "%s%s", "12", "3");     /* { dg-warning "into a region" } */
313   T (2, "%s%s", "12", "34");    /* { dg-warning "into a region" } */
314 
315   T (2, "_%s",   "");
316   T (2, "%%%s",  "");
317   T (2, "%%%%%s",  "");         /* { dg-warning "nul past the end" } */
318   T (2, "%s%%",  "");
319   T (2, "_%s",   "1");          /* { dg-warning "nul past the end" } */
320   T (2, "%%%s",  "1");          /* { dg-warning "nul past the end" } */
321   T (2, "%s%%",  "1");          /* { dg-warning "nul past the end" } */
322   T (2, "_%s",   "12");         /* { dg-warning "into a region" } */
323   T (2, "__%s",  "1");          /* { dg-warning "into a region" } */
324 
325   T (2, "%1$s%2$s", "12", "3"); /* { dg-warning ".%2.s. directive writing 1 byte into a region of size 0" } */
326   T (2, "%1$s%1$s", "12");      /* { dg-warning "does not support|.%1.s. directive writing 2 bytes into a region of size 0" } */
327   T (2, "%2$s%1$s", "1", "23"); /* { dg-warning ".%1.s. directive writing 1 byte into a region of size 0" } */
328   T (2, "%2$s%2$s", "1", "23"); /* { dg-warning "unused|%2.s. directive writing 2 bytes into a region of size 0" } */
329 
330   T (3, "__%s", "");
331   T (3, "__%s", "1");           /* { dg-warning "nul past the end" } */
332   T (3, "%s_%s", "", "");
333   T (3, "%s_%s", "1", "");
334   T (3, "%s_%s", "", "1");
335   T (3, "%s_%s", "1", "2");     /* { dg-warning "nul past the end" } */
336 
337   /* Wide strings.  */
338   T (-1, "%ls",      L"");
339   T ( 0, "%ls",      L"");      /* { dg-warning "nul past the end" } */
340   T ( 1, "%ls",      L"");
341   T ( 1, "%ls",      L"\0");
342   T ( 1, "%1ls",     L"");      /* { dg-warning "nul past the end" } */
343 
344   T (0, "%*ls",  0, L"");       /* { dg-warning "nul past the end" } */
345   T (1, "%*ls",  0, L"");
346   T (1, "%*ls",  0, L"\0");
347   T (1, "%*ls",  1, L"");       /* { dg-warning "nul past the end" } */
348 
349   /* A wide character string need not convert into any bytes (although
350      individual ASCII characters are assumed to convert into 1 bt %lc
351      so this could be made smarter.  */
352   T (1, "%ls",      L"1");      /* { dg-warning "directive writing up to 6 bytes into a region of size 1" } */
353   T (1, "%.0ls",    L"1");
354   T (2, "%.0ls",    L"1");
355   T (2, "%.1ls",    L"1");
356   T (2, "%.*ls", 1, L"1");
357 
358   /* The "%.2ls" directive below will write at a minimum 1 byte (because
359      L"1" is known and can be assumed to convert to at least one multibyte
360      character), and at most 2 bytes because of the precision.  Since its
361      output is explicitly bounded it is diagnosed.  */
362   T (2, "%.2ls",    L"1");      /* { dg-warning "nul past the end" } */
363   T (2, "%.*ls", 2, L"1");      /* { dg-warning "nul past the end" } */
364 
365   T (3, "%.0ls",    L"1");
366   T (3, "%.1ls",    L"1");
367   T (3, "%.2ls",    L"1");
368   T (3, "%ls",      L"12");     /* { dg-warning "directive writing up to 12 bytes" } */
369 
370   T (3, "%ls",      L"123");    /* { dg-warning "directive writing up to 18 bytes" } */
371   T (3, "%.0ls",    L"123");
372   T (3, "%.1ls",    L"123");
373   T (3, "%.2ls",    L"123");
374   T (3, "%.3ls",    L"123");    /* { dg-warning "nul past the end" } */
375 }
376 
377 /* Exercise the "%hhd", "%hhi", "%hho", "%hhu", and "%hhx" directives
378    with constant arguments.  */
379 
test_sprintf_chk_hh_const(void)380 void test_sprintf_chk_hh_const (void)
381 {
382   T (-1, "%hhd",        0);
383 
384   T (1, "%hhd",         0);     /* { dg-warning "nul past the end" } */
385   T (1, "%hhd",      cst0);     /* { dg-warning "nul past the end" } */
386   T (1, "%hhd",         1);     /* { dg-warning "nul past the end" } */
387   T (1, "%hhd",      cst1);     /* { dg-warning "nul past the end" } */
388   T (1, "%hhd",        -1);     /* { dg-warning "into a region" } */
389   T (1, "%+hhd",        0);     /* { dg-warning "into a region" } */
390   T (1, "%+hhd",        1);     /* { dg-warning "into a region" } */
391   T (1, "%-hhd",        0);     /* { dg-warning "nul past the end" } */
392 
393   T (1, "%hhi",         0);     /* { dg-warning "nul past the end" } */
394   T (1, "%hhi",         1);     /* { dg-warning "nul past the end" } */
395   T (1, "%hhi",        -1);     /* { dg-warning "into a region" } */
396   T (1, "%+hhi",        0);     /* { dg-warning "into a region" } */
397   T (1, "%+hhi",        1);     /* { dg-warning "into a region" } */
398   T (1, "%-hhi",        0);     /* { dg-warning "nul past the end" } */
399 
400   T (2, "%hhi",         0);
401   T (2, "%hhi",         1);
402   T (2, "%hhi",         9);
403   T (2, "% hhi",        9);     /* { dg-warning "nul past the end" } */
404   T (2, "%+hhi",        9);     /* { dg-warning "nul past the end" } */
405   T (2, "%-hhi",        9);
406   T (2, "%hhi",        10);     /* { dg-warning "nul past the end" } */
407   T (2, "%hhi",     cst10);     /* { dg-warning "nul past the end" } */
408   T (2, "%hhi",        -1);     /* { dg-warning "nul past the end" } */
409   T (2, "% hhi",       -1);     /* { dg-warning "nul past the end" } */
410   T (2, "%+hhi",       -1);     /* { dg-warning "nul past the end" } */
411   T (2, "%-hhi",       -1);     /* { dg-warning "nul past the end" } */
412 
413   T (2, "%hho",         0);
414   T (2, "%hho",         1);
415   T (2, "%hho",         7);
416   T (2, "%hho",       010);     /* { dg-warning "nul past the end" } */
417   T (2, "%hho",       077);     /* { dg-warning "nul past the end" } */
418   T (2, "%hho",        -1);     /* { dg-warning "into a region" } */
419 
420   T (2, "%hhx",         0);
421   T (2, "%hhX",         1);
422   T (2, "%hhx",         7);
423   T (2, "%hhX",         8);
424   T (2, "%hhx",        -1);     /* { dg-warning "nul past the end" } */
425   T (2, "%hhX",       0xf);
426   T (2, "%hhx",      0x10);     /* { dg-warning "nul past the end" } */
427   T (2, "%hhX",      0xff);     /* { dg-warning "nul past the end" } */
428 
429   T (1, "%#hhx",        0);     /* { dg-warning "nul past the end" } */
430   T (2, "%#hhx",        0);
431   T (3, "%#hhx",        1);     /* { dg-warning "nul past the end" } */
432 
433   T (4, "%hhd",       255);
434   T (4, "%hhd",       256);
435   T (4, "%hhd",     0xfff);
436   T (4, "%hhd",    0xffff);
437 
438   T (4, "%hhi",       255);
439   T (4, "%hhi",       256);
440   T (4, "%hhi",     0xfff);
441   T (4, "%hhi",    0xffff);
442 
443   T (4, "%hhu",        -1);
444   T (4, "%hhu",       255);
445   T (4, "%hhu",       256);
446   T (4, "%hhu",     0xfff);
447   T (4, "%hhu",    0xffff);
448 
449   T (4, "%#hhx",        0);
450   T (4, "%#hhx",        1);
451   T (4, "%#hhx",       -1);     /* { dg-warning "nul past the end" } */
452   T (4, "%#hhx",      0xf);
453   T (4, "%#hhx",     0x10);     /* { dg-warning "nul past the end" } */
454   T (4, "%#hhx",     0xff);     /* { dg-warning "nul past the end" } */
455   T (4, "%#hhx",    0xfff);     /* { dg-warning "nul past the end" } */
456 
457   T (4, "%hhi %hhi",  0,  0);
458   T (4, "%hhi %hhi",  9,  9);
459   T (4, "%hhi %hhi",  1, 10);   /* { dg-warning "nul past the end" } */
460   T (4, "%hhi %hhi", 10,  1);   /* { dg-warning "nul past the end" } */
461   T (4, "%hhi %hhi", 11, 12);   /* { dg-warning "into a region" } */
462 
463   /*  As a special case, a precision of zero with an argument of zero
464       results in zero bytes (unless modified by flags and/or width).  */
465   T (1, "%.0hhd",   0);
466   T (1, "%+.0hhd",  0);         /* { dg-warning "nul past the end" } */
467   T (1, "%-.0hhd",  0);
468   T (1, "% .0hhd",  0);         /* { dg-warning "nul past the end" } */
469   T (1, "%0.0hhd",  0);         /* { dg-warning ".0. flag ignored with precision" } */
470   T (1, "%00.0hhd", 0);         /* { dg-warning "repeated .0. flag in format" } */
471   /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
472   T (1, "%-0.0hhd", 0);         /* { dg-warning ".0. flag ignored with .-. flag" } */
473   /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
474   T (1, "%.0hhi",   0);
475   T (1, "%.0hho",   0);
476   /* As a special case, '#' in base 8 results in 1 byte (the zero).  */
477   T (1, "%#.0hho",  0);         /* { dg-warning "nul past the end" } */
478   T (1, "%.0hhx",   0);
479   T (1, "%.0hhX",   0);
480   T (1, "%#.0hhX",  0);
481 
482   T (5, "%0*hhd %0*hhi", 0,  7, 0,   9);
483   T (5, "%0*hhd %0*hhi", 1,  7, 1,   9);
484   T (5, "%0*hhd %0*hhi", 1,  7, 2,   9);
485   T (5, "%0*hhd %0*hhi", 2,  7, 1,   9);
486   T (5, "%0*hhd %0*hhi", 2,  7, 2,   9); /* { dg-warning "nul past the end" } */
487   T (5, "%0*hhd %0*hhi", 0, 12, 0, 123); /* { dg-warning ".%0\\*hhi. directive writing 3 bytes into a region of size 2" } */
488   T (5, "%0*hhd %0*hhi", 1, 12, 1, 123); /* { dg-warning ".%0\\*hhi. directive writing 3 bytes into a region of size 2" } */
489   T (5, "%0*hhd %0*hhi", 2, 12, 3, 123); /* { dg-warning ".%0\\*hhi. directive writing 3 bytes into a region of size 2" } */
490 
491   /* FIXME: Move the boundary test cases into a file of their own that's
492      exercised only on targets with the matching type limits (otherwise
493      they'll fail).  */
494 #undef MAX
495 #define MAX   127
496 
497 #undef MIN
498 #define MIN   (-MAX -1)
499 
500   T (1, "%hhi",        MAX);    /* { dg-warning "into a region" } */
501   T (1, "%hhi",        MIN);    /* { dg-warning "into a region" } */
502   T (1, "%hhi",  MAX +   1);    /* { dg-warning "into a region" } */
503 
504   T (2, "%hhi",  MAX +   1);    /* { dg-warning "into a region" } */
505   T (2, "%hhi",  MAX +  10);    /* { dg-warning "into a region" } */
506   T (2, "%hhi",  MAX + 100);    /* { dg-warning "into a region" } */
507 }
508 
509 /* Exercise the "%hhd", "%hi", "%ho", "%hu", and "%hx" directives
510    with constant arguments.  */
511 
test_sprintf_chk_h_const(void)512 void test_sprintf_chk_h_const (void)
513 {
514   T (1, "%hu",          0);     /* { dg-warning "nul past the end" } */
515   T (1, "%hu",          1);     /* { dg-warning "nul past the end" } */
516   T (1, "%hu",         -1);     /* { dg-warning "into a region" } */
517 
518   T (2, "%hi",          0);
519   T (2, "%hi",          1);
520   T (2, "%hi",          9);
521   T (2, "% hi",         9);     /* { dg-warning "nul past the end" } */
522   T (2, "%+hi",         9);     /* { dg-warning "nul past the end" } */
523   T (2, "%-hi",         9);
524   T (2, "%hi",         10);     /* { dg-warning "nul past the end" } */
525   T (2, "%hi",         -1);     /* { dg-warning "nul past the end" } */
526   T (2, "% hi",        -2);     /* { dg-warning "nul past the end" } */
527   T (2, "%+hi",        -3);     /* { dg-warning "nul past the end" } */
528   T (2, "%-hi",        -4);     /* { dg-warning "nul past the end" } */
529 
530   T (2, "%hu",          0);
531   T (2, "%hu",          1);
532   T (2, "%hu",          9);
533   T (2, "%hu",         10);     /* { dg-warning "nul past the end" } */
534   T (2, "%hu",         -1);     /* { dg-warning "into a region" } */
535 
536   T (2, "%ho",          0);
537   T (2, "%ho",          1);
538   T (2, "%ho",          7);
539   T (2, "%ho",        010);     /* { dg-warning "nul past the end" } */
540   T (2, "%ho",        077);     /* { dg-warning "nul past the end" } */
541   T (2, "%ho",       0100);     /* { dg-warning "into a region" } */
542   T (2, "%ho",         -1);     /* { dg-warning "into a region" } */
543 
544   T (2, "%hx",          0);
545   T (2, "%hx",          1);
546   T (2, "%hx",          7);
547   T (2, "%hx",        0xf);
548   T (2, "%hx",       0x10);     /* { dg-warning "nul past the end" } */
549   T (2, "%hx",       0xff);     /* { dg-warning "nul past the end" } */
550   T (2, "%hx",      0x100);     /* { dg-warning "into a region" } */
551   T (2, "%hx",         -1);     /* { dg-warning "into a region" } */
552 
553   T (3, "% hi",         7);
554   T (3, "%+hi",         8);
555   T (3, "%-hi",         9);
556   T (3, "%hi",         10);
557   T (3, "%hi",         -1);
558   T (3, "% hi",        -2);
559   T (3, "%+hi",        -3);
560   T (3, "%-hi",        -4);
561 
562   T (5, "%hu",       9999);
563   T (5, "%hu",      10000);     /* { dg-warning "nul past the end" } */
564   T (5, "%hu",      65535);     /* { dg-warning "nul past the end" } */
565 
566   T (1, "%#hx",         0);     /* { dg-warning "nul past the end" } */
567   T (2, "%#hx",         0);
568   T (3, "%#hx",         1);     /* { dg-warning "nul past the end" } */
569 
570   T (4, "%#hx",         0);
571   T (4, "%#hx",         1);
572   T (4, "%#hx",       0xf);
573   T (4, "%#hx",      0x10);     /* { dg-warning "nul past the end" } */
574   T (4, "%#hx",      0xff);     /* { dg-warning "nul past the end" } */
575   T (4, "%#hx",     0x100);     /* { dg-warning "into a region" } */
576   T (4, "%#hx",        -1);     /* { dg-warning "into a region" } */
577 
578   /*  As a special case, a precision of zero with an argument of zero
579       results in zero bytes (unless modified by width).  */
580   T (1, "%.0hd",        0);
581   T (1, "%+.0hd",       0);         /* { dg-warning "nul past the end" } */
582   T (1, "%-.0hd",       0);
583   T (1, "% .0hd",       0);         /* { dg-warning "nul past the end" } */
584   T (1, "%0.0hd",       0);         /* { dg-warning ".0. flag ignored with precision" } */
585   T (1, "%00.0hd",      0);         /* { dg-warning "repeated .0. flag in format" } */
586   /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
587   T (1, "%-0.0hd",      0);         /* { dg-warning ".0. flag ignored with .-. flag" } */
588   /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
589   T (1, "%.0hi",        0);
590   T (1, "%.0ho",        0);
591   T (1, "%#.0ho",       0);         /* { dg-warning "nul past the end" } */
592   T (1, "%.0hx",        0);
593   T (1, "%.0hX",        0);
594   T (1, "%#.0hX",       0);
595 
596 #undef MAX
597 #define MAX   65535
598 
599   T (1, "%hu",          0);     /* { dg-warning "nul past the end" } */
600   T (1, "%hu",          1);     /* { dg-warning "nul past the end" } */
601   T (1, "%hu",         -1);     /* { dg-warning "into a region" } */
602   T (1, "%hu",        MAX);     /* { dg-warning "into a region" } */
603   T (1, "%hu",   MAX +  1);     /* { dg-warning "nul past the end" } */
604 }
605 
606 /* Exercise the "%d", "%i", "%o", "%u", and "%x" directives with
607    constant arguments.  */
608 
test_sprintf_chk_integer_const(void)609 void test_sprintf_chk_integer_const (void)
610 {
611   T ( 1, "%i",          0);         /* { dg-warning "nul past the end" } */
612   T ( 1, "%i",          1);         /* { dg-warning "nul past the end" } */
613   T ( 1, "%i",         -1);         /* { dg-warning "into a region" } */
614   T ( 1, "%i_",         1);         /* { dg-warning " 1 byte into a region of size 0" } */
615   T ( 1, "_%i",         1);         /* { dg-warning "into a region" } */
616   T ( 1, "_%i_",        1);         /* { dg-warning "into a region" } */
617   T ( 1, "%o",          0);         /* { dg-warning "nul past the end" } */
618   T ( 1, "%u",          0);         /* { dg-warning "nul past the end" } */
619   T ( 1, "%x",          0);         /* { dg-warning "nul past the end" } */
620   T ( 1, "%#x",         0);         /* { dg-warning "nul past the end" } */
621   T ( 1, "%x",          1);         /* { dg-warning "nul past the end" } */
622   T ( 1, "%#x",         1);         /* { dg-warning "into a region" } */
623 
624   T ( 2, "%i",          0);
625   T ( 2, "%i",          1);
626   T ( 2, "%i",          9);
627   T ( 2, "%i",         -1);         /* { dg-warning "nul past the end" } */
628   T ( 2, "%i",         10);         /* { dg-warning "nul past the end" } */
629   T ( 2, "%i_",         0);         /* { dg-warning "nul past the end" } */
630   T ( 2, "_%i",         0);         /* { dg-warning "nul past the end" } */
631   T ( 2, "_%i_",        0);         /* { dg-warning " 1 byte into a region of size 0" } */
632   T ( 2, "%o",          1);
633   T ( 2, "%o",          7);
634   T ( 2, "%o",        010);         /* { dg-warning "nul past the end" } */
635   T ( 2, "%o",       0100);         /* { dg-warning "into a region" } */
636   T ( 2, "%x",          1);
637   T ( 2, "%#x",         1);         /* { dg-warning "into a region" } */
638   T ( 2, "%x",        0xa);
639   T ( 2, "%x",        0xf);
640   T ( 2, "%x",       0x10);         /* { dg-warning "nul past the end" } */
641   T ( 2, "%x",       0xff);         /* { dg-warning "nul past the end" } */
642   T ( 2, "%x",      0x1ff);         /* { dg-warning "into a region" } */
643 
644   T ( 3, "%i",          0);
645   T ( 3, "%i",          1);
646   T ( 3, "%i",          9);
647   T ( 3, "%i",         -9);
648   T ( 3, "%i",         10);
649   T ( 3, "%i",         99);
650   T ( 3, "%i",        -99);         /* { dg-warning "nul past the end" } */
651 
652   /* ~0U is formatted into exactly three bytes as "-1" followed by
653      the terminating NUL character.  */
654   T ( 3, "%+i",       ~0U);
655   T ( 3, "%-i",       ~0U);
656   T ( 3, "% i",       ~0U);
657 
658   T ( 8, "%8u",         1);        /* { dg-warning "nul past the end" } */
659   T ( 9, "%8u",         1);
660 
661   /*  As a special case, a precision of zero with an argument of zero
662       results in zero bytes (unless modified by width).  */
663   T (1, "%.0d",         0);
664   T (1, "%+.0d",        0);         /* { dg-warning "nul past the end" } */
665   T (1, "%-.0d",        0);
666   T (1, "% .0d",        0);         /* { dg-warning "nul past the end" } */
667   T (1, "%0.0d",        0);         /* { dg-warning ".0. flag ignored with precision" } */
668   T (1, "%00.0d",       0);         /* { dg-warning "repeated .0. flag in format" } */
669   /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
670   T (1, "%-0.0d",       0);         /* { dg-warning ".0. flag ignored with .-. flag" } */
671   /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
672   T (1, "%.0i",         0);
673   T (1, "%.0o",         0);
674   T (1, "%#.0o",        0);         /* { dg-warning "nul past the end" } */
675   T (1, "%.0x",         0);
676   T (1, "%.0X",         0);
677   T (1, "%#.0X",        0);
678 
679   T ( 7, "%1$i%2$i%3$i",     1, 23, 456);
680   T ( 8, "%1$i%2$i%3$i%1$i", 1, 23, 456);
681   T ( 8, "%1$i%2$i%3$i%2$i", 1, 23, 456);   /* { dg-warning "nul past the end" } */
682   T ( 8, "%1$i%2$i%3$i%3$i", 1, 23, 456);   /* { dg-warning "into a region" } */
683 
684 #undef MAX
685 #define MAX   2147483647   /* 10 digits.  */
686 #undef MIN
687 #define MIN   (-MAX -1)    /* Sign plus 10 digits.  */
688 
689   T ( 1, "%i",        MAX);         /* { dg-warning "into a region" } */
690   T ( 1, "%i",        MIN);         /* { dg-warning "into a region" } */
691   T ( 2, "%i",        MAX);         /* { dg-warning "into a region" } */
692   T ( 2, "%i",        MIN);         /* { dg-warning "into a region" } */
693   T (10, "%i",  123456789);
694   T (10, "%i", -123456789);         /* { dg-warning "nul past the end" } */
695   T (10, "%i",        MAX);         /* { dg-warning "nul past the end" } */
696   T (10, "%i",        MIN);         /* { dg-warning "into a region" } */
697 
698   T (11, "%i",        MAX);
699   T (11, "%i",        MIN);         /* { dg-warning "nul past the end" } */
700 }
701 
702 /* Exercise the "%jd", "%ji", "%jo", "%ju", and "%jx" directives
703    for the formatting of intmax_t and uintmax_t values with constant
704    arguments.  */
705 
test_sprintf_chk_j_const(void)706 void test_sprintf_chk_j_const (void)
707 {
708 #define I(x) ((__INTMAX_TYPE__)x)
709 
710   T ( 1, "%ji",  I (    0));      /* { dg-warning "nul past the end" } */
711   T ( 1, "%ji",  I (    1));      /* { dg-warning "nul past the end" } */
712   T ( 1, "%ji",  I (   -1));      /* { dg-warning "into a region" } */
713   T ( 1, "%ji_", I (    1));      /* { dg-warning " 1 byte into a region of size 0" } */
714   T ( 1, "_%ji", I (    1));      /* { dg-warning "into a region" } */
715   T ( 1, "_%ji_",I (    1));      /* { dg-warning "into a region" } */
716   T ( 1, "%jo",  I (    0));      /* { dg-warning "nul past the end" } */
717   T ( 1, "%ju",  I (    0));      /* { dg-warning "nul past the end" } */
718   T ( 1, "%jx",  I (    0));      /* { dg-warning "nul past the end" } */
719   T ( 1, "%#jx", I (    0));      /* { dg-warning "nul past the end" } */
720   T ( 1, "%jx",  I (    1));      /* { dg-warning "nul past the end" } */
721   T ( 1, "%#jx", I (    1));      /* { dg-warning "into a region" } */
722 
723   T ( 2, "%ji",  I (    0));
724   T ( 2, "%ji",  I (    1));
725   T ( 2, "%ji",  I (    9));
726   T ( 2, "%ji",  I (   -1));      /* { dg-warning "nul past the end" } */
727   T ( 2, "%ji",  I (   10));      /* { dg-warning "nul past the end" } */
728   T ( 2, "%ji_", I (    0));      /* { dg-warning "nul past the end" } */
729   T ( 2, "_%ji", I (    0));      /* { dg-warning "nul past the end" } */
730   T ( 2, "_%ji_",I (    0));      /* { dg-warning " 1 byte into a region of size 0" } */
731   T ( 2, "%jo",  I (    1));
732   T ( 2, "%jo",  I (    7));
733   T ( 2, "%jo",  I (  010));      /* { dg-warning "nul past the end" } */
734   T ( 2, "%jo",  I ( 0100));      /* { dg-warning "into a region" } */
735   T ( 2, "%jx",  I (    1));
736   T ( 2, "%#jx", I (    1));      /* { dg-warning "into a region" } */
737   T ( 2, "%jx",  I (  0xa));
738   T ( 2, "%jx",  I (  0xf));
739   T ( 2, "%jx",  I ( 0x10));      /* { dg-warning "nul past the end" } */
740   T ( 2, "%jx",  I ( 0xff));      /* { dg-warning "nul past the end" } */
741   T ( 2, "%jx",  I (0x1ff));      /* { dg-warning "into a region" } */
742 
743   T ( 3, "%ji",  I (    0));
744   T ( 3, "%ji",  I (    1));
745   T ( 3, "%ji",  I (    9));
746   T ( 3, "%ji",  I (   -9));
747   T ( 3, "%ji",  I (   10));
748   T ( 3, "%ji",  I (   99));
749   T ( 3, "%ji",  I (  -99));      /* { dg-warning "nul past the end" } */
750 
751   /* ~0 is formatted into exactly three bytes as "-1" followed by
752      the terminating NUL character.  */
753   T ( 3, "%+ji",    ~I (0));
754   T ( 3, "%-ji",    ~I (0));
755   T ( 3, "% ji",    ~I (0));
756 
757   T ( 8, "%8ju",     I (1));      /* { dg-warning "nul past the end" } */
758   T ( 9, "%8ju",     I (1));
759 
760   /*  As a special case, a precision of zero with an argument of zero
761       results in zero bytes (unless modified by width).  */
762   T (1, "%.0jd",     I (0));
763   T (1, "%+.0jd",    I (0));         /* { dg-warning "nul past the end" } */
764   T (1, "%+.0ju",    I (0));         /* { dg-warning ".\\+. flag used" } */
765   T (1, "%-.0jd",    I (0));
766   T (1, "% .0jd",    I (0));         /* { dg-warning "nul past the end" } */
767   T (1, "% .0ju",    I (0));         /* { dg-warning ". . flag used" } */
768   T (1, "%0.0jd",    I (0));         /* { dg-warning ".0. flag ignored with precision" } */
769   T (1, "%00.0jd",   I (0));         /* { dg-warning "repeated .0. flag in format" } */
770   /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
771   T (1, "%-0.0jd",   I (0));         /* { dg-warning ".0. flag ignored with .-. flag" } */
772   /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
773   T (1, "%.0ji",     I (0));
774   T (1, "%.0jo",     I (0));
775   T (1, "%#.0jo",    I (0));         /* { dg-warning "nul past the end" } */
776   T (1, "%.0jx",     I (0));
777   T (1, "%.0jX",     I (0));
778   T (1, "%#.0jX",    I (0));
779 }
780 
781 /* Exercise the "%ld", "%li", "%lo", "%lu", and "%lx" directives
782    with constant arguments.  */
783 
test_sprintf_chk_l_const(void)784 void test_sprintf_chk_l_const (void)
785 {
786   T ( 1, "%li",      0L);         /* { dg-warning "nul past the end" } */
787   T ( 1, "%li",      1L);         /* { dg-warning "nul past the end" } */
788   T ( 1, "%li",     -1L);         /* { dg-warning "into a region" } */
789   T ( 1, "%li_",     1L);         /* { dg-warning " 1 byte into a region of size 0" } */
790   T ( 1, "_%li",     1L);         /* { dg-warning "into a region" } */
791   T ( 1, "_%li_",    1L);         /* { dg-warning "into a region" } */
792   T ( 1, "%lo",      0L);         /* { dg-warning "nul past the end" } */
793   T ( 1, "%lu",      0L);         /* { dg-warning "nul past the end" } */
794   T ( 1, "%lx",      0L);         /* { dg-warning "nul past the end" } */
795   T ( 1, "%#lx",     0L);         /* { dg-warning "nul past the end" } */
796   T ( 1, "%lx",      1L);         /* { dg-warning "nul past the end" } */
797   T ( 1, "%#lx",     1L);         /* { dg-warning "into a region" } */
798 
799   T ( 2, "%li",      0L);
800   T ( 2, "%li",      1L);
801   T ( 2, "%li",      9L);
802   T ( 2, "%li",     -1L);         /* { dg-warning "nul past the end" } */
803   T ( 2, "%li",     10L);         /* { dg-warning "nul past the end" } */
804   T ( 2, "%li_",     0L);         /* { dg-warning "nul past the end" } */
805   T ( 2, "_%li",     0L);         /* { dg-warning "nul past the end" } */
806   T ( 2, "_%li_",    0L);         /* { dg-warning " 1 byte into a region of size 0" } */
807   T ( 2, "%lo",      1L);
808   T ( 2, "%lo",      7L);
809   T ( 2, "%lo",    010L);         /* { dg-warning "nul past the end" } */
810   T ( 2, "%lo",   0100L);         /* { dg-warning "into a region" } */
811   T ( 2, "%lx",      1L);
812   T ( 2, "%#lx",     1L);         /* { dg-warning "into a region" } */
813   T ( 2, "%lx",    0xaL);
814   T ( 2, "%lx",    0xfL);
815   T ( 2, "%lx",   0x10L);         /* { dg-warning "nul past the end" } */
816   T ( 2, "%lx",   0xffL);         /* { dg-warning "nul past the end" } */
817   T ( 2, "%lx",  0x1ffL);         /* { dg-warning "into a region" } */
818 
819   T ( 3, "%li",      0L);
820   T ( 3, "%li",      1L);
821   T ( 3, "%li",      9L);
822   T ( 3, "%li",     -9L);
823   T ( 3, "%li",     10L);
824   T ( 3, "%li",     99L);
825   T ( 3, "%li",    -99L);         /* { dg-warning "nul past the end" } */
826 
827   /* ~0U is formatted into exactly three bytes as "-1" followed by
828      the terminating NUL character.  */
829   T ( 3, "%+li",   ~0LU);
830   T ( 3, "%-li",   ~0LU);
831   T ( 3, "% li",   ~0LU);
832 
833   T ( 8, "%8lu",     1L);         /* { dg-warning "nul past the end" } */
834   T ( 9, "%8lu",     1L);
835 
836   /*  As a special case, a precision of zero with an argument of zero
837       results in zero bytes (unless modified by width).  */
838   T (1, "%.0ld",     0L);
839   T (1, "%+.0ld",    0L);         /* { dg-warning "nul past the end" } */
840   T (1, "%+.0lu",    0L);         /* { dg-warning ".\\+. flag used" } */
841   T (1, "%-.0ld",    0L);
842   T (1, "% .0ld",    0L);         /* { dg-warning "nul past the end" } */
843   T (1, "% .0lu",    0L);         /* { dg-warning ". . flag used" } */
844   T (1, "%0.0ld",    0L);         /* { dg-warning ".0. flag ignored with precision" } */
845   T (1, "%00.0ld",   0L);         /* { dg-warning "repeated .0. flag in format" } */
846   /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
847   T (1, "%-0.0ld",   0L);         /* { dg-warning ".0. flag ignored with .-. flag" } */
848   /* { dg-warning ".0. flag ignored with precision" "" { target *-*-* } .-1 } */
849   T (1, "%.0li",     0L);
850   T (1, "%.0lo",     0L);
851   T (1, "%#.0lo",    0L);         /* { dg-warning "nul past the end" } */
852   T (1, "%.0lx",     0L);
853   T (1, "%.0lX",     0L);
854   T (1, "%#.0lX",    0L);
855 }
856 
857 /* Exercise the "%lld", "%lli", "%llo", "%llu", and "%llx" directives
858    with constant arguments.  */
859 
test_sprintf_chk_ll_const(void)860 void test_sprintf_chk_ll_const (void)
861 {
862   T ( 1, "%lli",      0LL);     /* { dg-warning "nul past the end" } */
863   T ( 1, "%lli",      1LL);     /* { dg-warning "nul past the end" } */
864   T ( 1, "%lli",     -1LL);     /* { dg-warning "into a region" } */
865   T ( 1, "%lli_",     1LL);     /* { dg-warning " 1 byte into a region of size 0 " } */
866   T ( 1, "_%lli",     1LL);     /* { dg-warning "into a region" } */
867   T ( 1, "_%lli_",    1LL);     /* { dg-warning "into a region" } */
868   T ( 1, "%llo",      0LL);     /* { dg-warning "nul past the end" } */
869   T ( 1, "%llu",      0LL);     /* { dg-warning "nul past the end" } */
870   T ( 1, "%llx",      0LL);     /* { dg-warning "nul past the end" } */
871   T ( 1, "%#llx",     0LL);     /* { dg-warning "nul past the end" } */
872   T ( 1, "%llx",      1LL);     /* { dg-warning "nul past the end" } */
873   T ( 1, "%#llx",     1LL);     /* { dg-warning "into a region" } */
874 
875   T ( 2, "%lli",      0LL);
876   T ( 2, "%lli",      1LL);
877   T ( 2, "%lli",      9LL);
878   T ( 2, "%lli",     -1LL);     /* { dg-warning "nul past the end" } */
879   T ( 2, "%lli",     10LL);     /* { dg-warning "nul past the end" } */
880   T ( 2, "%lli_",     0LL);     /* { dg-warning "nul past the end" } */
881   T ( 2, "_%lli",     0LL);     /* { dg-warning "nul past the end" } */
882   T ( 2, "_%lli_",    0LL);     /* { dg-warning " 1 byte into a region of size 0" } */
883   T ( 2, "%llo",      1LL);
884   T ( 2, "%llo",      7LL);
885   T ( 2, "%llo",    010LL);     /* { dg-warning "nul past the end" } */
886   T ( 2, "%llo",   0100LL);     /* { dg-warning "into a region" } */
887   T ( 2, "%llx",      1LL);
888   T ( 2, "%#llx",     1LL);     /* { dg-warning "into a region" } */
889   T ( 2, "%llx",    0xaLL);
890   T ( 2, "%llx",    0xfLL);
891   T ( 2, "%llx",   0x10LL);     /* { dg-warning "nul past the end" } */
892   T ( 2, "%llx",   0xffLL);     /* { dg-warning "nul past the end" } */
893   T ( 2, "%llx",  0x1ffLL);     /* { dg-warning "into a region" } */
894 
895   T ( 3, "%lli",      0LL);
896   T ( 3, "%lli",      1LL);
897   T ( 3, "%lli",      9LL);
898   T ( 3, "%lli",     -9LL);
899   T ( 3, "%lli",     10LL);
900   T ( 3, "%lli",     99LL);
901   T ( 3, "%lli",    -99LL);     /* { dg-warning "nul past the end" } */
902 
903   /* ~0U is formatted into exactly three bytes as "-1" followed by
904      the terminating NUL character.  */
905   T ( 3, "%+lli",   ~0LLU);
906   T ( 3, "%-lli",   ~0LLU);
907   T ( 3, "% lli",   ~0LLU);
908 
909   T ( 8, "%8llu",     1LL);     /* { dg-warning "nul past the end" } */
910   T ( 9, "%8llu",     1LL);
911 
912   /* assume 64-bit long long.  */
913 #define LLONG_MAX   9223372036854775807LL   /* 19 bytes */
914 #define LLONG_MIN   (-LLONG_MAX - 1)        /* 20 bytes */
915 
916   T (18, "%lli", LLONG_MIN);    /* { dg-warning "into a region" } */
917   T (19, "%lli", LLONG_MIN);    /* { dg-warning "into a region" } */
918   T (20, "%lli", LLONG_MIN);    /* { dg-warning "nul past the end" } */
919   T (21, "%lli", LLONG_MIN);
920 
921   T (18, "%lli", LLONG_MAX);    /* { dg-warning "into a region" } */
922   T (19, "%lli", LLONG_MAX);    /* { dg-warning "nul past the end" } */
923   T (20, "%lli", LLONG_MAX);
924 
925   T (21, "%llo",      -1LL);    /* { dg-warning "into a region" } */
926   T (22, "%llo",      -1LL);    /* { dg-warning "nul past the end" } */
927   T (23, "%llo",      -1LL);
928 
929   T (19, "%llu",      -1LL);    /* { dg-warning "into a region" } */
930   T (20, "%llu",      -1LL);    /* { dg-warning "nul past the end" } */
931   T (21, "%llu",      -1LL);
932 
933   T (15, "%llx",      -1LL);    /* { dg-warning "into a region" } */
934   T (16, "%llx",      -1LL);    /* { dg-warning "nul past the end" } */
935   T (17, "%llx",      -1LL);
936 }
937 
test_sprintf_chk_L_const(void)938 void test_sprintf_chk_L_const (void)
939 {
940   T (-1, "%Li",        0LL);
941   T ( 1, "%Li",        0LL);         /* { dg-warning "nul past the end" } */
942   T ( 1, "%Li",        1LL);         /* { dg-warning "nul past the end" } */
943   T ( 1, "%Li",       -1LL);         /* { dg-warning "into a region" } */
944   T ( 1, "%Li_",       1LL);         /* { dg-warning " 1 byte into a region of size 0" } */
945   T ( 1, "_%Li",       1LL);         /* { dg-warning "into a region" } */
946   T ( 1, "_%Li_",      1LL);         /* { dg-warning "into a region" } */
947 }
948 
test_sprintf_chk_z_const(void)949 void test_sprintf_chk_z_const (void)
950 {
951   T (-1, "%zi",        (size_t)0);
952   T ( 1, "%zi",        (size_t)0);  /* { dg-warning "nul past the end" } */
953   T ( 1, "%zi",        (size_t)1);  /* { dg-warning "nul past the end" } */
954   T ( 1, "%zi",        (size_t)-1L);/* { dg-warning "into a region" } */
955   T ( 1, "%zi_",       (size_t)1);  /* { dg-warning " 1 byte into a region of size 0" } */
956   T ( 1, "_%zi",       (size_t)1);  /* { dg-warning "into a region" } */
957   T ( 1, "_%zi_",      (size_t)1);  /* { dg-warning "into a region" } */
958 
959   T ( 2, "%zu",        (size_t)1);
960   T ( 2, "%zu",        (size_t)9);
961   T ( 2, "%zu",        (size_t)10); /* { dg-warning "nul past the end" } */
962 }
963 
test_sprintf_chk_a_const(void)964 void test_sprintf_chk_a_const (void)
965 {
966   T (-1, "%a",         0.0);
967   T (-1, "%la",        0.0);
968   T (-1, "%.a",        0.0);
969   T (-1, "%.la",       0.0);
970   T (-1, "%123.a",     0.0);
971   T (-1, "%234.la",    0.0);
972   T (-1, "%.345a",     0.0);
973   T (-1, "%456.567la", 0.0);
974 
975   /* The least number of bytes on output is 6 for "0x0p+0".  When precision
976      is missing the number of digits after the decimal point isn't fully
977      specified by C (a defect).  Two sets of implementations are known to
978      exist: those that trim trailing zeros (e.g., Glibc) and those that
979      pad output with trailing zeros so that all floating point numbers
980      result in the same number of bytes on output (e.g., Solaris).  */
981   T ( 0, "%a",   0.0);         /* { dg-warning "writing between 6 and 20 bytes" } */
982   T ( 0, "%la",  0.0);         /* { dg-warning "between 6 and 20 bytes" } */
983   T ( 1, "%a",   0.0);         /* { dg-warning "between 6 and 20 bytes" } */
984   T ( 2, "%a",   0.0);         /* { dg-warning "between 6 and 20 bytes" } */
985   T ( 3, "%a",   0.0);         /* { dg-warning "between 6 and 20 bytes" } */
986   T ( 4, "%a",   0.0);         /* { dg-warning "between 6 and 20 bytes" } */
987   T ( 5, "%a",   0.0);         /* { dg-warning "between 6 and 20 bytes" } */
988   T ( 6, "%a",   0.0);         /* { dg-warning "between 6 and 20 bytes" } */
989   T (19, "%a",   0.0);         /* { dg-warning "between 6 and 20 bytes" } */
990   T (20, "%a",   0.0);         /* { dg-warning "may write a terminating nul" } */
991 
992   T (0, "%.a",    0.0);       /* { dg-warning "into a region" } */
993   T (0, "%.0a",   0.0);       /* { dg-warning "into a region" } */
994   T (0, "%.0la",  0.0);       /* { dg-warning "into a region" } */
995   T (1, "%.0a",   0.0);       /* { dg-warning "into a region" } */
996   T (2, "%.0a",   0.0);       /* { dg-warning "into a region" } */
997   T (3, "%.0a",   0.0);       /* { dg-warning "into a region" } */
998   T (4, "%.0a",   0.0);       /* { dg-warning "into a region" } */
999   T (5, "%.0a",   0.0);       /* { dg-warning "into a region" } */
1000   T (6, "%.0a",   0.0);       /* { dg-warning "writing a terminating nul" } */
1001 
1002   T (7, "%6.a",   0.0);
1003   T (7, "%7.a",   0.0);       /* { dg-warning "writing a terminating nul" } */
1004   T (7, "%7.1a",  0.0);       /* { dg-warning "writing 8 bytes into a region of size 7" } */
1005 
1006   T (7, "%.a",    0.0);
1007   T (7, "%.0a",   0.0);
1008 }
1009 
test_sprintf_chk_e_const(void)1010 void test_sprintf_chk_e_const (void)
1011 {
1012   T (-1, "%E",      0.0);
1013   T (-1, "%lE",     0.0);
1014   T (-1, "%.E",     0.0);
1015   T (-1, "%.lE",    0.0);
1016   T (-1, "%123.E",  0.0);
1017   T (-1, "%234.lE", 0.0);
1018   T (-1, "%.345E",  0.0);
1019   T (-1, "%.456lE", 0.0);
1020 
1021   T ( 0, "%E",   0.0);          /* { dg-warning "into a region" } */
1022   T ( 0, "%e",   0.0);          /* { dg-warning "into a region" } */
1023   T ( 1, "%E",   1.0);          /* { dg-warning "into a region" } */
1024   T ( 1, "%e",   1.0);          /* { dg-warning "into a region" } */
1025   T ( 2, "%e",   2.0);          /* { dg-warning "into a region" } */
1026   T ( 3, "%e",   3.0);          /* { dg-warning "into a region" } */
1027   T (12, "%e",   1.2);          /* { dg-warning "nul past the end" } */
1028   T (12, "%e",  12.0);          /* { dg-warning "nul past the end" } */
1029   T (13, "%e",   1.3);          /* 1.300000e+00 */
1030   T (13, "%E",  13.0);          /* 1.300000e+01 */
1031   T (13, "%e",  13.0);
1032   T (13, "%E",  1.4e+99);       /* 1.400000e+99 */
1033   T (13, "%e",  1.5e+100);      /* { dg-warning "nul past the end" } */
1034   T (14, "%E",  1.6e+101);      /* 1.600000E+101 */
1035   T (14, "%e", -1.7e+102);      /* { dg-warning "nul past the end" } */
1036   T (15, "%E", -1.8e+103);      /* -1.800000E+103 */
1037 
1038   T (16, "%.8e", -1.9e+104);    /* { dg-warning "nul past the end" } */
1039   T (17, "%.8e", -2.0e+105);    /* -2.00000000e+105 */
1040 
1041   T ( 5, "%.e",  0.0);          /* { dg-warning "nul past the end" } */
1042   T ( 5, "%.0e", 0.0);          /* { dg-warning "nul past the end" } */
1043   T ( 5, "%.0e", 1.0);          /* { dg-warning "nul past the end" } */
1044   T ( 6, "%.e",  1.0);
1045   T ( 6, "%.0e", 1.0);
1046 
1047   /* The output of the following directives depends on the rounding
1048      mode.  */
1049   T (12, "%e",  9.999999e+99);  /* { dg-warning "between 12 and 13" } */
1050   T (12, "%e",  9.9999994e+99); /* { dg-warning "between 12 and 13" } */
1051   T (12, "%e",  9.9999995e+99); /* { dg-warning "between 12 and 13" } */
1052   T (12, "%e",  9.9999996e+99); /* { dg-warning "between 12 and 13" } */
1053   T (12, "%e",  9.9999997e+99); /* { dg-warning "between 12 and 13" } */
1054   T (12, "%e",  9.9999998e+99); /* { dg-warning "between 12 and 13" } */
1055 
1056   T (12, "%Le", 9.9999994e+99L);/* { dg-warning "between 12 and 13" } */
1057   T (12, "%Le", 9.9999995e+99L);/* { dg-warning "between 12 and 13" } */
1058   T (12, "%Le", 9.9999996e+99L);/* { dg-warning "between 12 and 13" } */
1059   T (12, "%Le", 9.9999997e+99L);/* { dg-warning "between 12 and 13" } */
1060   T (12, "%Le", 9.9999998e+99L);/* { dg-warning "between 12 and 13" } */
1061   T (12, "%Le", 9.9999999e+99L);/* { dg-warning "between 12 and 13" } */
1062 }
1063 
1064 /* At -Wformat-overflow level 1 unknown numbers are assumed to have
1065    the value one, and unknown strings are assumed to have a zero
1066    length.  */
1067 
test_sprintf_chk_s_nonconst(int w,int p,const char * s)1068 void test_sprintf_chk_s_nonconst (int w, int p, const char *s)
1069 {
1070   T (-1, "%s",   s);
1071   T ( 0, "%-s",  s);            /* { dg-warning "writing a terminating nul" } */
1072   T ( 1, "%s",   s);
1073   T (-1, "%.0s", s);
1074   T ( 1, "%.0s", s);
1075   T (-1, "%.1s", s);
1076   T ( 1, "%.1s", s);            /* { dg-warning "may write a terminating nul past the end" } */
1077   T (-1, "%.2s", s);
1078   T ( 1, "%.2s", s);            /* { dg-warning "directive writing up to 2 bytes" } */
1079   T ( 2, "%.2s", s);            /* { dg-warning "may write a terminating nul" } */
1080   T ( 3, "%.2s", s);
1081 
1082   /* The string argument is constant but the width and/or precision
1083      is not.  */
1084   T (-1, "%*s",  w, "");
1085   T ( 1, "%*s",  w, "");        /* { dg-warning "may write a terminating nul past the end" } */
1086   T (-1, "%*s",  w, "1");
1087   T ( 1, "%*s",  w, "1");       /* { dg-warning "writing a terminating nul past the end" } */
1088   T (-1, "%.*s", p, "");
1089   T ( 1, "%.*s", p, "");
1090   T (-1, "%.*s", p, "1");
1091   T ( 1, "%.*s", p, "1");       /* { dg-warning "may write a terminating nul" } */
1092   T ( 1, "%.*s", w, "123");     /* { dg-warning "writing up to 3 bytes into a region of size 1" } */
1093 
1094   /* Either of the messages below is acceptable.  */
1095   T ( 1, "%*s", w, "123");      /* { dg-warning "writing 3 or more bytes into a region of size 1|writing between 3 and 2147483648 bytes" } */
1096   T ( 2, "%*s", w, "123");      /* { dg-warning "writing 3 or more bytes into a region of size 2|writing between 3 and 2147483648 bytes" } */
1097   T ( 3, "%*s", w, "123");      /* { dg-warning "writing a terminating nul past the end" } */
1098   T ( 4, "%*s", w, "123");
1099 
1100   /* The following will definitely write past the end of the buffer,
1101      but since at level 1 the length of an unknown string argument
1102      is assumed to be zero, it will write the terminating nul past
1103      the end (we don't print "past the end" when we're not
1104      sure which we can't be with an unknown string.  */
1105   T (1, "%1s",  s);             /* { dg-warning "writing a terminating nul past the end" } */
1106 
1107   /* Multiple directives.  */
1108   T (1, "%s%s",    s, s);
1109   T (1, "%s%s%s", s, s, s);
1110 }
1111 
1112 /* Exercise the hh length modifier with all integer specifiers and
1113    a non-constant argument.  */
1114 
test_sprintf_chk_hh_nonconst(int w,int p,int a)1115 void test_sprintf_chk_hh_nonconst (int w, int p, int a)
1116 {
1117   T (-1, "%hhd",        a);
1118 
1119   T (0, "%hhd",         a);     /* { dg-warning ".%hhd. directive writing between 1 and . bytes into a region of size 0" } */
1120   T (0, "%hhi",      var0);     /* { dg-warning "into a region" } */
1121   T (0, "%hhi",         a);     /* { dg-warning "into a region" } */
1122   T (0, "%hhu",         a);     /* { dg-warning "into a region" } */
1123   T (0, "%hhx",         a);     /* { dg-warning "into a region" } */
1124 
1125   T (1, "%hhd",         a);     /* { dg-warning "nul past the end" } */
1126   T (1, "%hhd",      var0);     /* { dg-warning "nul past the end" } */
1127   T (1, "%hhi",         a);     /* { dg-warning "nul past the end" } */
1128   T (1, "%hhu",         a);     /* { dg-warning "nul past the end" } */
1129   T (1, "%hhx",         a);     /* { dg-warning "nul past the end" } */
1130 
1131   T (1, "% hhd",        a);     /* { dg-warning "into a region" } */
1132   T (1, "% hhi",        a);     /* { dg-warning "into a region" } */
1133   T (1, "%+hhd",        a);     /* { dg-warning "into a region" } */
1134   T (1, "%+hhi",        a);     /* { dg-warning "into a region" } */
1135   T (1, "%-hhd",        a);     /* { dg-warning "nul past the end" } */
1136   T (1, "%-hhi",        a);     /* { dg-warning "nul past the end" } */
1137 
1138   T (2, "%hhd",         a);
1139   T (2, "%hhd",      var0);
1140   T (2, "%hhd",     var10);
1141   T (2, "%hhi",         a);
1142   T (2, "%hho",         a);
1143   T (2, "%hhu",         a);
1144   T (2, "%hhx",         a);
1145 
1146   T (2, "% hhd",        a);     /* { dg-warning "nul past the end" } */
1147   T (2, "% hhd",     var0);     /* { dg-warning "nul past the end" } */
1148   T (2, "% hhd",    var10);     /* { dg-warning "nul past the end" } */
1149   T (2, "% hhi",        a);     /* { dg-warning "nul past the end" } */
1150   T (2, "% hho",        a);     /* { dg-warning ". . flag used with .%o." } */
1151   T (2, "% hhu",        a);     /* { dg-warning ". . flag used with .%u." } */
1152   T (2, "% hhx",        a);     /* { dg-warning ". . flag used with .%x." } */
1153 
1154   /* The following results in between "0" and "0377" for -1.  Although
1155      the minimum output would fit, given the '#' flag the likely output
1156      (i.e., for any non-zero argument) includes a leading zero followed
1157      by one or more octal digits, which results in the terminating nul
1158      being written past the end.  Thus the "may write" warning.  */
1159   T (2, "%#hho",        a);     /* { dg-warning "may write a terminating nul" } */
1160   /* Similar to the above, but the likely output of the directive for
1161      a non-zero argument overflows.  Thus the "writing X bytes" (as
1162      opposed to "may write") warning.  */
1163   T (2, "%#hhx",        a);     /* { dg-warning "writing between 1 and 4 bytes" } */
1164 
1165   T (3, "%0hhd",        a);
1166   T (3, "%1hhd",        a);
1167   T (3, "%2hhd",        a);
1168   T (3, "%2hhi",        a);
1169   T (3, "%2hho",        a);
1170   T (3, "%2hhu",        a);
1171   T (3, "%2hhx",        a);
1172   T (3, "%2.hhx",       a);
1173 
1174   T (3, "%3hhd",        a);     /* { dg-warning "nul past the end" } */
1175   T (3, "%3hhi",        a);     /* { dg-warning "nul past the end" } */
1176   T (3, "%3hho",        a);     /* { dg-warning "nul past the end" } */
1177   T (3, "%3hhu",        a);     /* { dg-warning "nul past the end" } */
1178   T (3, "%3hhx",        a);     /* { dg-warning "nul past the end" } */
1179   T (3, "%3.hhx",       a);     /* { dg-warning "nul past the end" } */
1180 
1181   T (4, "%5hhd",        a);     /* { dg-warning "into a region" } */
1182   T (4, "%6hhi",        a);     /* { dg-warning "into a region" } */
1183   T (4, "%7hho",        a);     /* { dg-warning "into a region" } */
1184   T (4, "%8hhu",        a);     /* { dg-warning "into a region" } */
1185   T (4, "%9hhx",        a);     /* { dg-warning "into a region" } */
1186 
1187   T (3, "%.hhd",        a);
1188   T (3, "%.0hhd",       a);
1189   T (3, "%.1hhd",       a);
1190   T (3, "%.2hhd",       a);
1191   T (3, "%.2hhi",       a);
1192   T (3, "%.2hho",       a);
1193   T (3, "%.2hhu",       a);
1194   T (3, "%.2hhx",       a);
1195 
1196   T (3, "%.3hhd",       a);     /* { dg-warning "nul past the end" } */
1197   T (3, "%.3hhi",       a);     /* { dg-warning "nul past the end" } */
1198   T (3, "%.3hho",       a);     /* { dg-warning "nul past the end" } */
1199   T (3, "%.3hhu",       a);     /* { dg-warning "nul past the end" } */
1200   T (3, "%.3hhx",       a);     /* { dg-warning "nul past the end" } */
1201 
1202   T (4, "%.5hhd",       a);     /* { dg-warning "into a region" } */
1203   T (4, "%.6hhi",       a);     /* { dg-warning "into a region" } */
1204   T (4, "%.7hho",       a);     /* { dg-warning "into a region" } */
1205   T (4, "%.8hhu",       a);     /* { dg-warning "into a region" } */
1206   T (4, "%.9hhx",       a);     /* { dg-warning "into a region" } */
1207 
1208   /* Exercise cases where the type of the actual argument (whose value
1209      and range are unknown) constrain the size of the output and so
1210      can be used to avoid what would otherwise be false positives.  */
1211 
1212   T (2, "%hhd", (UChar)a);
1213   T (2, "%hhi", (UChar)a);
1214   T (2, "%-hhi", (UChar)a);
1215 
1216   /* Exercise cases where the argument is known but width isn't.  */
1217   T (0, "%*hhi", w,   0);       /* { dg-warning "into a region" } */
1218   T (1, "%*hhi", w,   0);       /* { dg-warning "nul past the end" } */
1219   T (2, "%*hhi", w,   0);
1220   T (2, "%*hhi", w,  12);       /* { dg-warning "nul past the end" } */
1221   T (2, "%*hhi", w, 123);       /* { dg-warning "into a region" } */
1222 
1223   /* The argument is known but precision isn't.  When the argument
1224      is zero only the first call can be diagnosed since a zero
1225      precision would result in no bytes on output.  */
1226   T (0, "%.*hhi", p,   0);      /* { dg-warning " writing up to \[0-9\]+ bytes" } */
1227   T (1, "%.*hhi", p,   0);      /* { dg-warning "may write a terminating nul" }*/
1228   T (2, "%.*hhi", p,   0);
1229   T (2, "%.*hhi", p,  12);      /* { dg-warning "nul past the end" } */
1230   T (2, "%.*hhi", p, 123);      /* { dg-warning "into a region" } */
1231 
1232   /* The argument is known but neither width nor precision is.  */
1233   T (0, "%*.*hhi", w, p,   0);  /* { dg-warning "writing up to \[0-9\]+ bytes" } */
1234   T (1, "%*.*hhi", w, p,   0);  /* { dg-warning "may write a terminating nul" } */
1235   T (2, "%*.*hhi", w, p,   0);
1236   T (2, "%*.*hhi", w, p,  12);  /* { dg-warning "nul past the end" } */
1237   T (2, "%*.*hhi", w, p, 123);  /* { dg-warning "into a region" } */
1238 
1239   /* The argument and width are known but precision isn't.  */
1240   T (0, "%1.*hhi",  p,   0);    /* { dg-warning "into a region" } */
1241   T (0, "%-1.*hhi", p,   0);    /* { dg-warning "into a region" } */
1242   T (1, "%1.*hhi",  p,   0);    /* { dg-warning "nul past the end" } */
1243   T (2, "%1.*hhi",  p,   0);
1244   T (2, "%2.*hhi",  p,   0);    /* { dg-warning "nul past the end" } */
1245   T (2, "%1.*hhi",  p,  12);    /* { dg-warning "nul past the end" } */
1246   T (2, "%2.*hhi",  p,  12);    /* { dg-warning "nul past the end" } */
1247 
1248   T (2, "%1.*hhi",  p, 123);    /* { dg-warning "into a region" } */
1249   T (2, "%2.*hhi",  p, 123);    /* { dg-warning "into a region" } */
1250   T (2, "%3.*hhi",  p, 123);    /* { dg-warning "into a region" } */
1251 
1252   /* The argument and precision are known but width isn't.  */
1253   T (0, "%*.1hhi",  w,   0);    /* { dg-warning "into a region" } */
1254   T (1, "%*.1hhi",  w,   0);    /* { dg-warning "nul past the end" } */
1255   T (2, "%*.1hhi",  w,   0);
1256   T (2, "%*.2hhi",  w,   0);    /* { dg-warning "nul past the end" } */
1257   T (2, "%*.1hhi",  w,  12);    /* { dg-warning "nul past the end" } */
1258   T (2, "%*.2hhi",  w,  12);    /* { dg-warning "nul past the end" } */
1259   T (2, "%*.3hhi",  w,  12);    /* { dg-warning "into a region" } */
1260 
1261   T (2, "%*.1hhi",  w, 123);    /* { dg-warning "into a region" } */
1262   T (2, "%*.2hhi",  w, 123);    /* { dg-warning "into a region" } */
1263   T (2, "%*.3hhi",  w, 123);    /* { dg-warning "into a region" } */
1264 }
1265 
1266 /* Exercise the h length modifier with all integer specifiers and
1267    a non-constant argument.  */
1268 
test_sprintf_chk_h_nonconst(int a)1269 void test_sprintf_chk_h_nonconst (int a)
1270 {
1271   T (-1, "%hd",         a);
1272 
1273   T (0, "%hd",          a);     /* { dg-warning "into a region" } */
1274   T (0, "%hi",          a);     /* { dg-warning "into a region" } */
1275   T (0, "%hu",          a);     /* { dg-warning "into a region" } */
1276   T (0, "%hx",          a);     /* { dg-warning "into a region" } */
1277 
1278   T (1, "%hd",          a);     /* { dg-warning "nul past the end" } */
1279   T (1, "%hi",          a);     /* { dg-warning "nul past the end" } */
1280   T (1, "%hu",          a);     /* { dg-warning "nul past the end" } */
1281   T (1, "%hx",          a);     /* { dg-warning "nul past the end" } */
1282 
1283   T (1, "% hd",         a);     /* { dg-warning "into a region" } */
1284   T (1, "% hi",         a);     /* { dg-warning "into a region" } */
1285   T (1, "%+hd",         a);     /* { dg-warning "into a region" } */
1286   T (1, "%+hi",         a);     /* { dg-warning "into a region" } */
1287   T (1, "%-hd",         a);     /* { dg-warning "nul past the end" } */
1288   T (1, "%-hi",         a);     /* { dg-warning "nul past the end" } */
1289 
1290   T (2, "%hd",          a);
1291   T (2, "%hi",          a);
1292   T (2, "%ho",          a);
1293   T (2, "%hu",          a);
1294   T (2, "%hx",          a);
1295 
1296   T (2, "% hd",         a);     /* { dg-warning "nul past the end" } */
1297   T (2, "% hi",         a);     /* { dg-warning "nul past the end" } */
1298   T (2, "% ho",         a);     /* { dg-warning ". . flag used with .%o." } */
1299   T (2, "% hu",         a);     /* { dg-warning ". . flag used with .%u." } */
1300   T (2, "% hx",         a);     /* { dg-warning ". . flag used with .%x." } */
1301 
1302   T (2, "#%ho",         a);     /* { dg-warning "nul past the end" } */
1303   T (2, "#%hx",         a);     /* { dg-warning "nul past the end" } */
1304 
1305   T (3, "%2hd",         a);
1306   T (3, "%2hi",         a);
1307   T (3, "%2ho",         a);
1308   T (3, "%2hu",         a);
1309   T (3, "%2hx",         a);
1310 }
1311 
1312 /* Exercise all integer specifiers with no modifier and a non-constant
1313    argument.  */
1314 
test_sprintf_chk_int_nonconst(int w,int p,int a)1315 void test_sprintf_chk_int_nonconst (int w, int p, int a)
1316 {
1317   T (-1, "%d",          a);
1318 
1319   T (0, "%d",           a);     /* { dg-warning "into a region" } */
1320   T (0, "%i",           a);     /* { dg-warning "into a region" } */
1321   T (0, "%u",           a);     /* { dg-warning "into a region" } */
1322   T (0, "%x",           a);     /* { dg-warning "into a region" } */
1323 
1324   T (1, "%d",           a);     /* { dg-warning "nul past the end" } */
1325   T (1, "%i",           a);     /* { dg-warning "nul past the end" } */
1326   T (1, "%u",           a);     /* { dg-warning "nul past the end" } */
1327   T (1, "%x",           a);     /* { dg-warning "nul past the end" } */
1328 
1329   T (1, "% d",          a);     /* { dg-warning "into a region" } */
1330   T (1, "% i",          a);     /* { dg-warning "into a region" } */
1331   T (1, "%+d",          a);     /* { dg-warning "into a region" } */
1332   T (1, "%+i",          a);     /* { dg-warning "into a region" } */
1333   T (1, "%-d",          a);     /* { dg-warning "nul past the end" } */
1334   T (1, "%-i",          a);     /* { dg-warning "nul past the end" } */
1335 
1336   T (2, "%d",           a);
1337   T (2, "%i",           a);
1338   T (2, "%o",           a);
1339   T (2, "%u",           a);
1340   T (2, "%x",           a);
1341 
1342   T (2, "% d",          a);     /* { dg-warning "nul past the end" } */
1343   T (2, "% i",          a);     /* { dg-warning "nul past the end" } */
1344   T (2, "% o",          a);     /* { dg-warning ". . flag used with .%o." } */
1345   T (2, "% u",          a);     /* { dg-warning ". . flag used with .%u." } */
1346   T (2, "% x",          a);     /* { dg-warning ". . flag used with .%x." } */
1347 
1348   T (2, "#%o",          a);     /* { dg-warning "nul past the end" } */
1349   T (2, "#%x",          a);     /* { dg-warning "nul past the end" } */
1350 
1351   T (3, "%2d",          a);
1352   T (3, "%2i",          a);
1353   T (3, "%2o",          a);
1354   T (3, "%2u",          a);
1355   T (3, "%2x",          a);
1356 
1357   T (1, "%.*d",      p, a);     /* { dg-warning "nul past the end" } */
1358   T (2, "%.*d",      p, a);
1359 
1360   T (4, "%i %i",        a, a);
1361   /* The following will definitely be "writing a terminating nul past the end"
1362      (i.e., not "may write".)  */
1363   T (4, "%i %i ",       a, a);      /* { dg-warning "nul past the end" } */
1364   T (4, "%i %i %i",     a, a, a);   /* { dg-warning "into a region" }*/
1365 }
1366 
test_sprintf_chk_e_nonconst(int w,int p,double d)1367 void test_sprintf_chk_e_nonconst (int w, int p, double d)
1368 {
1369   T (-1, "%E",           d);
1370   T (-1, "%lE",          d);
1371   T (-1, "%.E",          d);
1372   T (-1, "%.lE",         d);
1373   T (-1, "%*E",    w,    d);
1374   T (-1, "%*lE",   w,    d);
1375   T (-1, "%.*E",      p, d);
1376   T (-1, "%.*lE",     p, d);
1377   T (-1, "%*.*E",  w, p, d);
1378   T (-1, "%*.*lE", w, p, d);
1379 
1380   /* The least number of bytes %E can produce is 3 for "inf" and "nan".  */
1381   T ( 0, "%E",          d);           /* { dg-warning "writing between 3 and 14 bytes into a region of size 0" } */
1382   T ( 0, "%e",          d);           /* { dg-warning "into a region" } */
1383   T ( 1, "%E",          d);           /* { dg-warning "into a region" } */
1384   T ( 1, "%e",          d);           /* { dg-warning "into a region" } */
1385   T ( 2, "%e",          d);           /* { dg-warning "into a region" } */
1386   T ( 3, "%e",          d);           /* { dg-warning "into a region" } */
1387   T (12, "%e",          d);           /* { dg-warning "nul past the end" } */
1388   T (13, "%E",          d);           /* 1.000000E+00 */
1389   T (13, "%e",          d);
1390   T (14, "%E",          d);
1391   T (14, "%e",          d);
1392 
1393   T ( 0, "%+E",         d);           /* { dg-warning "writing between 4 and 14 bytes into a region of size 0" } */
1394   T ( 0, "%-e",         d);           /* { dg-warning "writing between 3 and 14 bytes into a region of size 0" } */
1395   T ( 0, "% E",         d);           /* { dg-warning "writing between 4 and 14 bytes into a region of size 0" } */
1396 
1397   /* The range of output of "%.0e" is between 3 and 7 bytes (not counting
1398      the terminating NUL.  */
1399   T ( 5, "%.0e",        d);           /* { dg-warning "may write a terminating nul past the end" } */
1400   T ( 6, "%.0e",        d);           /* 1e+00 */
1401 
1402   /* The range of output of "%.1e" is between 3 and 9 bytes (not counting
1403      the terminating NUL.  */
1404   T ( 7, "%.1e",        d);           /* { dg-warning "may write a terminating nul past the end" } */
1405   T ( 8, "%.1e",        d);
1406 
1407   T ( 0, "%*e",      0, d);           /* { dg-warning "writing between 3 and 14 bytes into a region of size 0" } */
1408   T ( 0, "%*e",      w, d);           /* { dg-warning "writing 3 or more bytes into a region of size 0|writing between 3 and \[0-9\]+ bytes into a region of size 0" } */
1409 }
1410 
test_sprintf_chk_f_nonconst(double d)1411 void test_sprintf_chk_f_nonconst (double d)
1412 {
1413   T (-1, "%F",          d);
1414   T (-1, "%lF",         d);
1415 
1416   T ( 0, "%F",          d);           /* { dg-warning "into a region" } */
1417   T ( 0, "%f",          d);           /* { dg-warning "into a region" } */
1418   T ( 1, "%F",          d);           /* { dg-warning "into a region" } */
1419   T ( 1, "%f",          d);           /* { dg-warning "into a region" } */
1420   T ( 2, "%F",          d);           /* { dg-warning "into a region" } */
1421   T ( 2, "%f",          d);           /* { dg-warning "into a region" } */
1422   T ( 3, "%F",          d);           /* { dg-warning "into a region" } */
1423   T ( 3, "%f",          d);           /* { dg-warning "into a region" } */
1424   T ( 4, "%F",          d);           /* { dg-warning "into a region" } */
1425   T ( 4, "%f",          d);           /* { dg-warning "into a region" } */
1426   T ( 5, "%F",          d);           /* { dg-warning "into a region" } */
1427   T ( 5, "%f",          d);           /* { dg-warning "into a region" } */
1428   T ( 6, "%F",          d);           /* { dg-warning "into a region" } */
1429   T ( 6, "%f",          d);           /* { dg-warning "into a region" } */
1430   T ( 7, "%F",          d);           /* { dg-warning "into a region" } */
1431   T ( 7, "%f",          d);           /* { dg-warning "into a region" } */
1432   T ( 8, "%F",          d);           /* { dg-warning "nul past the end" } */
1433   T ( 8, "%f",          d);           /* { dg-warning "nul past the end" } */
1434   T ( 9, "%F",          d);
1435   T ( 9, "%f",          d);
1436 }
1437 
1438 /* Tests for __builtin_vsprintf_chk are the same as those for
1439    __builtin_sprintf_chk with non-constant arguments.  */
1440 #undef T
1441 #define T(size, fmt)							\
1442   (FUNC (__vsprintf_chk) (buffer (size), 0, objsize (size), fmt, va),	\
1443    sink (buffer))
1444 
test_vsprintf_chk_c(va_list va)1445 void test_vsprintf_chk_c (va_list va)
1446 {
1447   T (-1, "%c");
1448 
1449   /* Verify the full text of the diagnostic for just the distinct messages
1450      and use abbreviations in subsequent test cases.  */
1451   T (0, "%c");              /* { dg-warning ".%c. directive writing 1 byte into a region of size 0" } */
1452   T (1, "%c");              /* { dg-warning "writing a terminating nul past the end" } */
1453   T (1, "%c");              /* { dg-warning "nul past the end" } */
1454   T (2, "%c");
1455   T (2, "%2c");             /* { dg-warning "nul past the end" } */
1456   T (2, "%3c");             /* { dg-warning "into a region" } */
1457   T (2, "%c%c");            /* { dg-warning "nul past the end" } */
1458   T (3, "%c%c");
1459 
1460   /* Wide characters.  */
1461   T (0, "%lc");             /* { dg-warning "up to 6 bytes " } */
1462   T (1, "%lc");             /* { dg-warning "up to 6 bytes " } */
1463   T (2, "%lc");             /* { dg-warning "may write a terminating nul" } */
1464 
1465   /* The following could result in as few as a single byte and in as many
1466      as MB_CUR_MAX, but since the MB_CUR_MAX value is a runtime property
1467      the write cannot be reliably diagnosed.  */
1468   T (2, "%1lc");            /* { dg-warning "may write a terminating nul" } */
1469   /* Writing some unknown number of bytes into a field two characters wide.  */
1470   T (2, "%2lc");            /* { dg-warning "nul past the end" } */
1471   T (2, "%lc%lc");          /* { dg-warning "writing up to 6 bytes into a region of size between 0 and 2" } */
1472 
1473   T (3, "%lc%c");           /* { dg-warning "may write a terminating nul" } */
1474   /* Here in the best case each argument will format as single character,
1475      causing the terminating NUL to be written past the end.  */
1476   T (3, "%lc%c%c");         /* { dg-warning "writing 1 byte into a region of size between 0 and 2" } */
1477 }
1478 
test_vsprintf_chk_int(va_list va)1479 void test_vsprintf_chk_int (va_list va)
1480 {
1481   T (-1, "%d");
1482 
1483   T (0, "%d");                /* { dg-warning "into a region" } */
1484   T (0, "%i");                /* { dg-warning "into a region" } */
1485   T (0, "%u");                /* { dg-warning "into a region" } */
1486   T (0, "%x");                /* { dg-warning "into a region" } */
1487 
1488   T (1, "%d");                /* { dg-warning "nul past the end" } */
1489   T (1, "%i");                /* { dg-warning "nul past the end" } */
1490   T (1, "%u");                /* { dg-warning "nul past the end" } */
1491   T (1, "%x");                /* { dg-warning "nul past the end" } */
1492 
1493   T (1, "% d");               /* { dg-warning "into a region" } */
1494   T (1, "% i");               /* { dg-warning "into a region" } */
1495   T (1, "%+d");               /* { dg-warning "into a region" } */
1496   T (1, "%+i");               /* { dg-warning "into a region" } */
1497   T (1, "%-d");               /* { dg-warning "nul past the end" } */
1498   T (1, "%-i");               /* { dg-warning "nul past the end" } */
1499 
1500   T (2, "%d");
1501   T (2, "%i");
1502   T (2, "%o");
1503   T (2, "%u");
1504   T (2, "%x");
1505 
1506   T (2, "% d");               /* { dg-warning "nul past the end" } */
1507   T (2, "% i");               /* { dg-warning "nul past the end" } */
1508   T (2, "% o");               /* { dg-warning ". . flag used with .%o." } */
1509   T (2, "% u");               /* { dg-warning ". . flag used with .%u." } */
1510   T (2, "% x");               /* { dg-warning ". . flag used with .%x." } */
1511 
1512   T (2, "#%o");               /* { dg-warning "nul past the end" } */
1513   T (2, "#%x");               /* { dg-warning "nul past the end" } */
1514 
1515   T (3, "%2d");
1516   T (3, "%2i");
1517   T (3, "%2o");
1518   T (3, "%2u");
1519   T (3, "%2x");
1520 }
1521 
1522 #undef T
1523 #define T(size, fmt, ...)					      \
1524   (FUNC (snprintf) (buffer (size), objsize (size), fmt, __VA_ARGS__), \
1525    sink (buffer))
1526 
test_snprintf_c_const(char * d)1527 void test_snprintf_c_const (char *d)
1528 {
1529   T (-1, "%c",    0);            /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
1530 
1531   /* Verify the full text of the diagnostic for just the distinct messages
1532      and use abbreviations in subsequent test cases.  */
1533 
1534   /* A call to snprintf with a buffer of zero size is a request to determine
1535      the size of output without writing anything into the destination. No
1536      warning must be issued.  */
1537   T (0, "%c",     0);
1538   T (1, "%c",     0);            /* { dg-warning "output truncated before the last format character" } */
1539   T (1, "%c",   '1');            /* { dg-warning "output truncated" } */
1540   T (2, "%c",   '1');
1541   T (2, "%2c",  '1');            /* { dg-warning "output truncated" } */
1542   T (2, "%3c",  '1');            /* { dg-warning "directive output truncated" } */
1543   T (2, "%c%c", '1', '2');       /* { dg-warning "output truncated" } */
1544   T (3, "%c%c", '1', '2');
1545 
1546   /* Wide characters.  */
1547   T (0, "%lc",  (wint_t)0);
1548   T (1, "%lc",  (wint_t)0);
1549   T (2, "%lc",  (wint_t)0);
1550 
1551   /* The following could result in as few as a single byte and in as many
1552      as MB_CUR_MAX, but since the MB_CUR_MAX value is a runtime property
1553      the write cannot be reliably diagnosed.  */
1554   T (2, "%lc",  (wint_t)L'1');
1555   T (2, "%1lc", (wint_t)L'1');
1556   /* Writing at least 1 characted into a field two characters wide.  */
1557   T (2, "%2lc", (wint_t)L'1');          /* { dg-warning "output truncated before the last format character" } */
1558 
1559   T (3, "%lc%c",   (wint_t)'1', '2');
1560   /* Here %lc may result in anywhere between 0 and MB_CUR_MAX characters
1561      so the output range is [0, 2, 6, 6] with the middle being used for
1562      the diagnostic (and the extremes for optimization).  The cast is
1563      to prevent sign extension.  */
1564   T (3, "%lc%c%c", (wint_t)(unsigned char)'\x80', '2', '3');  /* { dg-warning ".%c. directive output may be truncated writing 1 byte into a region of size between 0 and 2" } */
1565   /* It's reasonably safe that L'1' converts into the single byte '1'.  */
1566   T (3, "%lc%c%c", (wint_t)'1', '2', '3');   /* { dg-warning "output may be truncated" } */
1567   T (3, "%lc%lc%c", (wint_t)'1', (wint_t)'2', '3'); /* { dg-warning "output may be truncated" } */
1568 }
1569 
1570 #undef T
1571 #define T(size, fmt, ...)						\
1572   (FUNC (__snprintf_chk) (buffer (size), objsize (size),		\
1573 			  0, objsize (size), fmt, __VA_ARGS__),		\
1574    sink (buffer))
1575 
test_snprintf_chk_c_const(void)1576 void test_snprintf_chk_c_const (void)
1577 {
1578   /* Verify that specifying a size of the destination buffer that's
1579      bigger than its actual size (normally determined and passed to
1580      the function by __builtin_object_size) is diagnosed.  */
1581   FUNC (__snprintf_chk)(buffer, 3, 0, 2, " ");   /* { dg-warning "specified bound 3 exceeds destination size 2" } */
1582 
1583   T (-1, "%c",    0);           /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
1584 
1585   T (0, "%c",     0);
1586   T (0, "%c%c",   0, 0);
1587   T (0, "%c_%c",  0, 0);
1588   T (0, "_%c_%c", 0, 0);
1589 
1590   T (1, "%c",     0);            /* { dg-warning "output truncated before the last format character" } */
1591   T (1, "%c",   '1');            /* { dg-warning "output truncated" } */
1592   T (2, "%c",   '1');
1593   T (2, "%2c",  '1');            /* { dg-warning "output truncated" } */
1594   T (2, "%3c",  '1');            /* { dg-warning "directive output truncated" } */
1595   T (2, "%c%c", '1', '2');       /* { dg-warning "output truncated before the last format character" } */
1596   T (3, "%c%c", '1', '2');
1597   T (3, "%c_%c", '1', '2');      /* { dg-warning "output truncated" } */
1598 
1599   /* Wide characters.  */
1600   T (0, "%lc",  (wint_t)0);
1601   T (1, "%lc",  (wint_t)0);
1602   T (2, "%lc",  (wint_t)0);
1603 
1604   /* The following could result in as few as a single byte and in as many
1605      as MB_CUR_MAX, but since the MB_CUR_MAX value is a runtime property
1606      the write cannot be reliably diagnosed.  */
1607   T (2, "%lc",  (wint_t)L'1');
1608   T (2, "%1lc", (wint_t)L'1');
1609   /* Writing at least 1 characted into a field two characters wide.  */
1610   T (2, "%2lc", (wint_t)'1');          /* { dg-warning "output truncated before the last format character" } */
1611 
1612   T (3, "%lc%c",   (wint_t)'1', '2');
1613   /* Here %lc may result in anywhere between 0 and MB_CUR_MAX characters
1614      so the minimum number of bytes on output is 2 (plus the terminating
1615      nul), but the likely number is 3 (plus the nul).  */
1616   T (3, "%lc%c%c", (wint_t)'1', '2', '3');   /* { dg-warning "output may be truncated" } */
1617   T (3, "%lc%lc%c", (wint_t)'1', (wint_t)'2', '3'); /* { dg-warning "output may be truncated" } */
1618 }
1619 
1620 /* Macro to verify that calls to __builtin_vsprintf (i.e., with no size
1621    argument) issue diagnostics by correctly determining the size of
1622    the destination buffer.  */
1623 #undef T
1624 #define T(size, fmt)				\
1625   (FUNC (vsprintf) (buffer (size), fmt, va),	\
1626    sink (buffer))
1627 
test_vsprintf_s(va_list va)1628 void test_vsprintf_s (va_list va)
1629 {
1630   T (-1, "%s");
1631 
1632   T (0, "%s");              /* { dg-warning "writing a terminating nul" } */
1633   T (1, "%s");
1634   T (1, "%1s");             /* { dg-warning "writing a terminating nul past the end" } */
1635 
1636   T (2, "%s%s");
1637   T (2, "%s%s1");
1638   T (2, "%s%s12");          /* { dg-warning "writing a terminating nul" } */
1639   T (2, "%s%s123");         /* { dg-warning "writing 3 bytes into a region of size 2" } */
1640   T (2, "%s_%s");
1641   T (2, "_%s%s");
1642   T (2, "_%s_%s");          /* { dg-warning "writing a terminating nul" } */
1643 }
1644 
1645 /* Exercise all integer specifiers with no modifier and a non-constant
1646    argument.  */
1647 
test_vsprintf_int(va_list va)1648 void test_vsprintf_int (va_list va)
1649 {
1650   T (-1, "%d");
1651 
1652   T (0, "%d");     /* { dg-warning "into a region" } */
1653   T (0, "%i");     /* { dg-warning "into a region" } */
1654   T (0, "%u");     /* { dg-warning "into a region" } */
1655   T (0, "%x");     /* { dg-warning "into a region" } */
1656 
1657   T (1, "%d");     /* { dg-warning "nul past the end" } */
1658   T (1, "%i");     /* { dg-warning "nul past the end" } */
1659   T (1, "%u");     /* { dg-warning "nul past the end" } */
1660   T (1, "%x");     /* { dg-warning "nul past the end" } */
1661 
1662   T (1, "% d");     /* { dg-warning "into a region" } */
1663   T (1, "% i");     /* { dg-warning "into a region" } */
1664   T (1, "%+d");     /* { dg-warning "into a region" } */
1665   T (1, "%+i");     /* { dg-warning "into a region" } */
1666   T (1, "%-d");     /* { dg-warning "nul past the end" } */
1667   T (1, "%-i");     /* { dg-warning "nul past the end" } */
1668 
1669   T (2, "%d");
1670   T (2, "%i");
1671   T (2, "%o");
1672   T (2, "%u");
1673   T (2, "%x");
1674 
1675   T (2, "% d");     /* { dg-warning "nul past the end" } */
1676   T (2, "% i");     /* { dg-warning "nul past the end" } */
1677   T (2, "% o");     /* { dg-warning ". . flag used with .%o." } */
1678   T (2, "% u");     /* { dg-warning ". . flag used with .%u." } */
1679   T (2, "% x");     /* { dg-warning ". . flag used with .%x." } */
1680 
1681   T (2, "#%o");     /* { dg-warning "nul past the end" } */
1682   T (2, "#%x");     /* { dg-warning "nul past the end" } */
1683 
1684   T (3, "%2d");
1685   T (3, "%2i");
1686   T (3, "%2o");
1687   T (3, "%2u");
1688   T (3, "%2x");
1689 }
1690 
1691 #undef T
1692 #define T(size, fmt)						\
1693   (FUNC (vsnprintf) (buffer (size), objsize (size), fmt, va),	\
1694    sink (buffer))
1695 
test_vsnprintf_s(va_list va)1696 void test_vsnprintf_s (va_list va)
1697 {
1698   T (-1, "%s");             /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
1699 
1700   T (0, "%s");
1701   T (1, "%s");
1702   T (1, "%1s");             /* { dg-warning "output truncated before the last format character" } */
1703 
1704   T (2, "%s%s");
1705   T (2, "%s%s_");
1706   T (2, "%s_%s");
1707   T (2, "_%s%s");
1708   T (2, "_%s_%s");          /* { dg-warning "output truncated" } */
1709 }
1710 
1711 #undef T
1712 #define T(size, fmt)					\
1713   (FUNC (__vsnprintf_chk) (buffer (size), objsize (size),	\
1714 			   0, objsize (size), fmt, va),		\
1715    sink (buffer))
1716 
test_vsnprintf_chk_s(va_list va)1717 void test_vsnprintf_chk_s (va_list va)
1718 {
1719   /* Verify that specifying a size of the destination buffer that's
1720      bigger than its actual size (normally determined and passed to
1721      the function by __builtin_object_size) is diagnosed.  */
1722   FUNC (__vsnprintf_chk)(buffer, 123, 0, 122, "%-s", va);   /* { dg-warning "specified bound 123 exceeds destination size 122" } */
1723 
1724   FUNC (__vsnprintf_chk)(buffer, __SIZE_MAX__, 0, 2, "%-s", va);   /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
1725 
1726   T (0, "%s");
1727   T (1, "%s");
1728   T (1, "%1s");             /* { dg-warning "output truncated before the last format character" } */
1729 
1730   T (2, "%s%s");
1731   T (2, "%s%s_");
1732   T (2, "%s_%s");
1733   T (2, "_%s%s");
1734   T (2, "_%s_%s");          /* { dg-warning "output truncated" } */
1735 }
1736