1 /* { dg-do compile }
2    { dg-options "-O2 -Wall -Wformat-overflow=1 -ftrack-macro-expansion=0" }
3    { dg-require-effective-target int32plus } */
4 
5 typedef __SIZE_TYPE__  size_t;
6 typedef __WCHAR_TYPE__ wchar_t;
7 
8 #define INT_MAX __INT_MAX__
9 #define INT_MIN (-INT_MAX - 1)
10 
11 /* When debugging, define LINE to the line number of the test case to exercise
12    and avoid exercising any of the others.  The buffer and objsize macros
13    below make use of LINE to avoid warnings for other lines.  */
14 #ifndef LINE
15 # define LINE 0
16 #endif
17 
18 void sink (char*, char*);
19 
20 int dummy_sprintf (char*, const char*, ...);
21 
22 char buffer [256];
23 extern char *ptr;
24 
int_range(int min,int max)25 static int int_range (int min, int max)
26 {
27   extern int int_value (void);
28   int n = int_value ();
29   return n < min || max < n ? min : n;
30 }
31 
32 /* Evaluate to an array of SIZE characters when non-negative, or to
33    a pointer to an unknown object otherwise.  */
34 #define buffer(size)					\
35   ((0 <= size) ? buffer + sizeof buffer - (size) : ptr)
36 
37 /* Helper to expand function to either __builtin_f or dummy_f to
38    make debugging GCC easy.  */
39 #define FUNC(f)							\
40   ((!LINE || LINE == __LINE__) ? __builtin_ ## f : dummy_ ## f)
41 
42 /* Macro to verify that calls to __builtin_sprintf (i.e., with no size
43    argument) issue diagnostics by correctly determining the size of
44    the destination buffer.  */
45 #define T(size, ...)						\
46   (FUNC (sprintf) (buffer (size),  __VA_ARGS__),		\
47    sink (buffer, ptr))
48 
49 /* Return a signed integer in the range [MIN, MAX].  */
50 #define R(min, max)  int_range (min, max)
51 
52 /* Verify warnings and ranges for certain overflow.  */
test_min_overflow(int i)53 void test_min_overflow (int i)
54 {
55   T (0, "%#hho", i);            /* { dg-warning "between 1 and 4 bytes" } */
56   T (0, "%#1hho", i);           /* { dg-warning "between 1 and 4 bytes" } */
57   T (0, "%#2hho", i);           /* { dg-warning "between 2 and 4 bytes" } */
58   T (0, "%#3hho", i);           /* { dg-warning "between 3 and 4 bytes" } */
59   T (0, "%#4hho", i);           /* { dg-warning "writing 4 bytes" } */
60   T (0, "%#hho", R (-1,  0));   /* { dg-warning "between 1 and 4 bytes" } */
61   T (0, "%#1hho", R (-1,  0));  /* { dg-warning "between 1 and 4 bytes" } */
62   T (0, "%#2hho", R (-1,  0));  /* { dg-warning "between 2 and 4 bytes" } */
63   T (0, "%#3hho", R (-1,  0));  /* { dg-warning "between 3 and 4 bytes" } */
64   T (0, "%#4hho", R (-1,  0));  /* { dg-warning "writing 4 bytes" } */
65   T (0, "%#hho", R (-1,  1));   /* { dg-warning "between 1 and 4 bytes" } */
66   T (0, "%#1hho", R (-1,  1));  /* { dg-warning "between 1 and 4 bytes" } */
67   T (0, "%#2hho", R (-1,  1));  /* { dg-warning "between 2 and 4 bytes" } */
68   T (0, "%#3hho", R (-1,  1));  /* { dg-warning "between 3 and 4 bytes" } */
69   T (0, "%#4hho", R (-1,  1));  /* { dg-warning "writing 4 bytes" } */
70   T (0, "%#hho", R ( 0,  1));   /* { dg-warning "between 1 and 2 bytes" } */
71   T (0, "%#1hho", R ( 0,  1));  /* { dg-warning "between 1 and 2 bytes" } */
72   T (0, "%#2hho", R ( 0,  1));  /* { dg-warning "writing 2 bytes" } */
73   T (0, "%#3hho", R ( 0,  1));  /* { dg-warning "writing 3 bytes" } */
74   T (0, "%#4hho", R ( 0,  1));  /* { dg-warning "writing 4 bytes" } */
75   T (0, "%#hho", R ( 1,  2));   /* { dg-warning "writing 2 bytes" } */
76   T (0, "%#1hho", R ( 1,  2));  /* { dg-warning "writing 2 bytes" } */
77   T (0, "%#2hho", R ( 1,  2));  /* { dg-warning "writing 2 bytes" } */
78   T (0, "%#3hho", R ( 1,  2));  /* { dg-warning "writing 3 bytes" } */
79   T (0, "%#4hho", R ( 1,  2));  /* { dg-warning "writing 4 bytes" } */
80 
81   T (0, "%#ho",  i);            /* { dg-warning "between 1 and 7 bytes" } */
82   T (0, "%#.*ho",               /* { dg-warning "between 1 and 7 bytes" } */
83      R (0, 2), i);
84   T (0, "%#.*ho",               /* { dg-warning "between 1 and 7 bytes" } */
85      R (1, 2), i);
86   T (0, "%#.*ho",               /* { dg-warning "between 2 and 7 bytes" } */
87      R (2, 3), i);
88   T (0, "%#.*ho",               /* { dg-warning "between 3 and 7 bytes" } */
89      R (3, 4), i);
90   T (0, "%#.*ho",               /* { dg-warning "between 7 and 8 bytes" } */
91      R (7, 8), i);
92 
93   T (0, "%#ho",  R (-1,  0));   /* { dg-warning "between 1 and 7 bytes" } */
94   T (0, "%#ho",  R (-1,  1));   /* { dg-warning "between 1 and 7 bytes" } */
95   T (0, "%#ho",  R ( 0,  1));   /* { dg-warning "between 1 and 2 bytes" } */
96   T (0, "%#ho",  R ( 1,  2));   /* { dg-warning "writing 2 bytes" } */
97 
98   T (0, "%#o",   i);            /* { dg-warning "between 1 and 12 bytes" } */
99   T (0, "%#o",   R (-1,  0));   /* { dg-warning "between 1 and 12 bytes" } */
100   T (0, "%#o",   R (-1,  1));   /* { dg-warning "between 1 and 12 bytes" } */
101   T (0, "%#o",   R ( 0,  1));   /* { dg-warning "between 1 and 2 bytes" } */
102   T (0, "%#o",   R ( 1,  2));   /* { dg-warning "writing 2 bytes" } */
103 
104   T (0, "%#hhx", i);            /* { dg-warning "between 1 and 4 bytes" } */
105   T (0, "%#.*hhx",              /* { dg-warning "writing up to 4 bytes" } */
106      R (0, 2), i);
107   T (0, "%#.*hhx",              /* { dg-warning "between 1 and 4 bytes" } */
108      R (1, 2), i);
109   T (0, "%#.*hhx",              /* { dg-warning "between 2 and 5 bytes" } */
110      R (2, 3), i);
111   T (0, "%#.*hhx",              /* { dg-warning "between 3 and 6 bytes" } */
112      R (3, 4), i);
113 
114   T (0, "%#hhx", R (-1,  0));   /* { dg-warning "between 1 and 4 bytes" } */
115   T (0, "%#hhx", R (-1,  1));   /* { dg-warning "between 1 and 4 bytes" } */
116   T (0, "%#hhx", R ( 0,  1));   /* { dg-warning "between 1 and 3 bytes" } */
117   T (0, "%#hhx", R ( 1,  2));   /* { dg-warning "writing 3 bytes" } */
118 
119   T (0, "%#hx", i);             /* { dg-warning "between 1 and 6 bytes" } */
120   T (0, "%#hx", R (-1,  0));    /* { dg-warning "between 1 and 6 bytes" } */
121   T (0, "%#hx", R (-1,  1));    /* { dg-warning "between 1 and 6 bytes" } */
122   T (0, "%#hx", R ( 0,  1));    /* { dg-warning "between 1 and 3 bytes" } */
123   T (0, "%#hx", R ( 1,  2));    /* { dg-warning "writing 3 bytes" } */
124 
125   T (0, "%#x",   i);            /* { dg-warning "between 1 and 10 bytes" } */
126   T (0, "%#x",   R (-1,  0));   /* { dg-warning "between 1 and 10 bytes" } */
127   T (0, "%#x",   R (-1,  1));   /* { dg-warning "between 1 and 10 bytes" } */
128   T (0, "%#x",   R ( 0,  1));   /* { dg-warning "between 1 and 3 bytes" } */
129   T (0, "%#x",   R ( 1,  2));   /* { dg-warning "writing 3 bytes" } */
130 }
131 
132 /* Verify warnings and ranges for likely overflow.  */
test_likely_overflow(int i)133 void test_likely_overflow (int i)
134 {
135   T (2, "%#hho", i);          /* { dg-warning "may write a terminating nul" } */
136   T (2, "%#1hho", i);         /* { dg-warning "may write a terminating nul" } */
137   T (2, "%#2hho", i);         /* { dg-warning "writing a terminating nul" } */
138   T (2, "%#3hho", i);         /* { dg-warning "between 3 and 4 bytes" } */
139   T (2, "%#4hho", i);         /* { dg-warning "writing 4 bytes" } */
140   T (2, "%#hho", R (-1,  0)); /* { dg-warning "may write a terminating nul" } */
141   T (2, "%#1hho", R (-1,  0));/* { dg-warning "may write a terminating nul" } */
142   T (2, "%#2hho", R (-1,  0));/* { dg-warning "writing a terminating nul" } */
143   T (2, "%#3hho", R (-1,  0));/* { dg-warning "between 3 and 4 bytes" } */
144   T (2, "%#4hho", R (-1,  0));/* { dg-warning "writing 4 bytes" } */
145   T (2, "%#hho", R (-1,  1)); /* { dg-warning "may write a terminating nul" } */
146   T (2, "%#1hho", R (-1,  1));/* { dg-warning "may write a terminating nul" } */
147   T (2, "%#2hho", R (-1,  1));/* { dg-warning "writing a terminating nul" } */
148   T (2, "%#3hho", R (-1,  1));/* { dg-warning "between 3 and 4 bytes" } */
149   T (2, "%#4hho", R (-1,  1));/* { dg-warning "writing 4 bytes" } */
150   T (2, "%#hho", R ( 0,  1)); /* { dg-warning "may write a terminating nul" } */
151   T (2, "%#1hho", R ( 0,  1));/* { dg-warning "may write a terminating nul" } */
152   T (2, "%#2hho", R ( 0,  1));/* { dg-warning "writing a terminating nul" } */
153   T (2, "%#3hho", R ( 0,  1));/* { dg-warning "writing 3 bytes" } */
154   T (2, "%#4hho", R ( 0,  1));/* { dg-warning "writing 4 bytes" } */
155   T (2, "%#hho", R ( 1,  2)); /* { dg-warning "writing a terminating nul" } */
156   T (2, "%#1hho", R ( 1,  2));/* { dg-warning "writing a terminating nul" } */
157   T (2, "%#2hho", R ( 1,  2));/* { dg-warning "writing a terminating nul" } */
158   T (2, "%#3hho", R ( 1,  2));/* { dg-warning "writing 3 bytes" } */
159   T (2, "%#4hho", R ( 1,  2));/* { dg-warning "writing 4 bytes" } */
160 
161   T (2, "%#ho",  i);          /* { dg-warning "may write a terminating nul" } */
162   T (2, "%#ho",  R (-1,  0)); /* { dg-warning "may write a terminating nul" } */
163   T (2, "%#ho",  R (-1,  1)); /* { dg-warning "may write a terminating nul" } */
164   T (2, "%#ho",  R ( 0,  1)); /* { dg-warning "may write a terminating nul" } */
165   T (2, "%#ho",  R ( 1,  2)); /* { dg-warning "writing a terminating nul" } */
166 
167   T (2, "%#o",   i);          /* { dg-warning "may write a terminating nul" } */
168   T (2, "%#o",   R (-1,  0)); /* { dg-warning "may write a terminating nul" } */
169   T (2, "%#o",   R (-1,  1)); /* { dg-warning "may write a terminating nul" } */
170   T (2, "%#o",   R ( 0,  1)); /* { dg-warning "may write a terminating nul" } */
171   T (2, "%#o",   R ( 1,  2)); /* { dg-warning "writing a terminating nul" } */
172 
173   T (2, "%#hhx", i);          /* { dg-warning "between 1 and 4 bytes" } */
174   T (2, "%#1hhx", i);         /* { dg-warning "between 1 and 4 bytes" } */
175   T (2, "%#2hhx", i);         /* { dg-warning "between 2 and 4 bytes" } */
176   T (2, "%#3hhx", i);         /* { dg-warning "between 3 and 4 bytes" } */
177   T (2, "%#4hhx", i);         /* { dg-warning "writing 4 bytes" } */
178   T (2, "%#1hhx", R (-1,  0));/* { dg-warning "between 1 and 4 bytes" } */
179   T (2, "%#2hhx", R (-1,  0));/* { dg-warning "between 2 and 4 bytes" } */
180   T (2, "%#3hhx", R (-1,  0));/* { dg-warning "between 3 and 4 bytes" } */
181   T (2, "%#4hhx", R (-1,  0));/* { dg-warning "writing 4 bytes" } */
182   T (2, "%#hhx", R (-1,  0)); /* { dg-warning "between 1 and 4 bytes" } */
183   T (2, "%#1hhx", R (-1,  0));/* { dg-warning "between 1 and 4 bytes" } */
184   T (2, "%#2hhx", R (-1,  0));/* { dg-warning "between 2 and 4 bytes" } */
185   T (2, "%#3hhx", R (-1,  0));/* { dg-warning "between 3 and 4 bytes" } */
186   T (2, "%#4hhx", R (-1,  0));/* { dg-warning "writing 4 bytes" } */
187   T (2, "%#hhx", R (-1,  1)); /* { dg-warning "between 1 and 4 bytes" } */
188   T (2, "%#1hhx", R (-1,  1));/* { dg-warning "between 1 and 4 bytes" } */
189   T (2, "%#2hhx", R (-1,  1));/* { dg-warning "between 2 and 4 bytes" } */
190   T (2, "%#3hhx", R (-1,  1));/* { dg-warning "between 3 and 4 bytes" } */
191   T (2, "%#4hhx", R (-1,  1));/* { dg-warning "writing 4 bytes" } */
192   T (2, "%#hhx", R ( 0,  1)); /* { dg-warning "between 1 and 3 bytes" } */
193   T (2, "%#1hhx", R ( 0,  1));/* { dg-warning "between 1 and 3 bytes" } */
194   T (2, "%#2hhx", R ( 0,  1));/* { dg-warning "between 2 and 3 bytes" } */
195   T (2, "%#3hhx", R ( 0,  1));/* { dg-warning "writing 3 bytes" } */
196   T (2, "%#4hhx", R ( 0,  1));/* { dg-warning "writing 4 bytes" } */
197   T (2, "%#hhx", R ( 1,  2)); /* { dg-warning "writing 3 bytes" } */
198   T (2, "%#1hhx", R ( 1,  2));/* { dg-warning "writing 3 bytes" } */
199   T (2, "%#2hhx", R ( 1,  2));/* { dg-warning "writing 3 bytes" } */
200   T (2, "%#3hhx", R ( 1,  2));/* { dg-warning "writing 3 bytes" } */
201   T (2, "%#4hhx", R ( 1,  2));/* { dg-warning "writing 4 bytes" } */
202 
203   T (2, "%#hx", i);           /* { dg-warning "between 1 and 6 bytes" } */
204   T (2, "%#hx", R (-1,  0));  /* { dg-warning "between 1 and 6 bytes" } */
205   T (2, "%#hx", R (-1,  1));  /* { dg-warning "between 1 and 6 bytes" } */
206   T (2, "%#hx", R ( 0,  1));  /* { dg-warning "between 1 and 3 bytes" } */
207   T (2, "%#hx", R ( 1,  2));  /* { dg-warning "writing 3 bytes" } */
208 
209   T (2, "%#x",   i);          /* { dg-warning "between 1 and 10 bytes" } */
210   T (2, "%#x",   R (-1,  0)); /* { dg-warning "between 1 and 10 bytes" } */
211   T (2, "%#x",   R (-1,  1)); /* { dg-warning "between 1 and 10 bytes" } */
212   T (2, "%#x",   R ( 0,  1)); /* { dg-warning "between 1 and 3 bytes" } */
213   T (2, "%#x",   R ( 1,  2)); /* { dg-warning "writing 3 bytes" } */
214 }
215 
216 /* Verify warnings likely overflow due to the terminating nul.  */
test_likely_nul_overflow(int i)217 void test_likely_nul_overflow (int i)
218 {
219   T (3, "%#hho", i);
220   T (3, "%#hho", R (-1,  0));
221   T (3, "%#hho", R (-1,  1));
222   T (3, "%#hho", R ( 0,  1));
223   T (3, "%#hho", R ( 1,  2));
224 
225   T (3, "%#ho",  i);
226   T (3, "%#ho",  R (-1,  0));
227   T (3, "%#ho",  R (-1,  1));
228   T (3, "%#ho",  R ( 0,  1));
229   T (3, "%#ho",  R ( 1,  2));
230 
231   T (3, "%#o",   i);
232   T (3, "%#o",   R (-1,  0));
233   T (3, "%#o",   R (-1,  1));
234   T (3, "%#o",   R ( 0,  1));
235   T (3, "%#o",   R ( 1,  2));
236 
237   T (3, "%#hhx", i);          /* { dg-warning "may write a terminating nul" } */
238   T (3, "%#hhx", R (-1,  0)); /* { dg-warning "may write a terminating nul" } */
239   T (3, "%#hhx", R (-1,  1)); /* { dg-warning "may write a terminating nul" } */
240   T (3, "%#hhx", R ( 0,  1)); /* { dg-warning "may write a terminating nul" } */
241   T (3, "%#hhx", R ( 1,  2)); /* { dg-warning "writing a terminating nul" } */
242 
243   T (3, "%#hx", i);           /* { dg-warning "may write a terminating nul" } */
244   T (3, "%#hx", R (-1,  0));  /* { dg-warning "may write a terminating nul" } */
245   T (3, "%#hx", R (-1,  1));  /* { dg-warning "may write a terminating nul" } */
246   T (3, "%#hx", R ( 0,  1));  /* { dg-warning "may write a terminating nul" } */
247   T (3, "%#hx", R ( 1,  2));  /* { dg-warning "writing a terminating nul" } */
248 
249   T (3, "%#x",   i);          /* { dg-warning "may write a terminating nul" } */
250   T (3, "%#x",   R (-1,  0)); /* { dg-warning "may write a terminating nul" } */
251   T (3, "%#x",   R (-1,  1)); /* { dg-warning "may write a terminating nul" } */
252   T (3, "%#x",   R ( 0,  1)); /* { dg-warning "may write a terminating nul" } */
253   T (3, "%#x",   R ( 1,  2)); /* { dg-warning "writing a terminating nul" } */
254 }
255