1 /* PR middle-end/80364 - sanitizer detects signed integer overflow
2    in gimple-ssa-sprintf.c
3    { dg-do compile }
4    { dg-options "-O2 -Wall -Wformat-overflow=1 -ftrack-macro-expansion=0" }
5    { dg-require-effective-target int32plus } */
6 
7 typedef __SIZE_TYPE__  size_t;
8 typedef __WCHAR_TYPE__ wchar_t;
9 
10 void sink (void*);
11 void* get_value (void);
12 
13 /* Return a random width as type T.  */
14 #define W(T) *(T*)get_value ()
15 
16 /* Return a random precision as type T.  */
17 #define P(T) *(T*)get_value ()
18 
19 /* Return a random value as type T.  */
20 #define V(T) *(T*)get_value ()
21 
22 extern char buf[1];
23 
24 /* Test convenience macro.  */
25 #define T(fmt, ...)					\
26   __builtin_sprintf (buf + 1, fmt, __VA_ARGS__);	\
27   sink (buf)
28 
29 typedef signed char         schar_t;
30 typedef unsigned char       uchar_t;
31 typedef signed short        sshort_t;
32 typedef unsigned short      ushort_t;
33 typedef signed int          sint_t;
34 typedef unsigned int        uint_t;
35 typedef signed long         slong_t;
36 typedef unsigned long       ulong_t;
37 typedef signed long long    sllong_t;
38 typedef unsigned long long  ullong_t;
39 
40 #if __SIZEOF_INT128__
41 typedef __int128_t          sint128_t;
42 typedef __uint128_t         uint128_t;
43 #else
44 /* When __int128_t is not available, repeat the same tests with long long.
45    This is to avoid having to guard the tests below and to avoid making
46    the dg-warning directives conditional.  */
47 typedef signed long long    sint128_t;
48 typedef unsigned long long  uint128_t;
49 #endif
50 
51 const sint128_t sint128_max
52   = (sint128_t)1 << (sizeof sint128_max * __CHAR_BIT__ - 2);
53 const sint128_t uint128_max = (uint128_t)-1;
54 
test_width_cst(void)55 void test_width_cst (void)
56 {
57   T ("%*i", W (schar_t), 1);     /* { dg-warning "between 1 and 128 " } */
58   T ("%*i", W (uchar_t), 12);    /* { dg-warning "between 2 and 255 " } */
59 
60   T ("%*i", W (sshort_t), 123);  /* { dg-warning "between 3 and 32768 " } */
61   T ("%*i", W (ushort_t), 1234); /* { dg-warning "between 4 and 65535 " } */
62 
63   T ("%*i", W (sint_t), 12345);  /* { dg-warning "between 5 and 2147483648 " } */
64   T ("%*i", W (uint_t), 123456); /* { dg-warning "between 6 and 2147483648 " } */
65 
66   /* Exercise calls with invalid arguments (to verify there is no ICE).  */
67   T ("%*li", W (slong_t), 1234567L);  /* { dg-warning "between 7 and 2147483648 " } */
68   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
69   T ("%*li", W (ulong_t), 12345678L); /* { dg-warning "between 8 and 2147483648 " } */
70   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
71 
72   T ("%*lli", W (sllong_t), 123456789LL);  /* { dg-warning "between 9 and 2147483648 " } */
73   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
74   T ("%*lli", W (ullong_t), 1234567890LL); /* { dg-warning "between 10 and 2147483648 " } */
75   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
76 
77   T ("%*i", W (sint128_t), 0);  /* { dg-warning "between 1 and 2147483648 " } */
78   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
79   T ("%*i", W (uint128_t), 1); /* { dg-warning "between 1 and 2147483648 " } */
80   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
81 
82   {
83     extern sint128_t si128;
84     if (si128 < sint128_max / 2 || sint128_max - 8 < si128)
85       si128 = sint128_max / 2;
86 
87     T ("%*i", si128, 0);  /* { dg-warning "between 1 and 2147483648 " } */
88     /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
89 
90     extern uint128_t ui128;
91     if (ui128 < uint128_max / 2 || uint128_max - 8 < ui128)
92       ui128 = uint128_max / 2;
93 
94     T ("%*i", ui128, 0);  /* { dg-warning "between 1 and 2147483648 " } */
95     /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
96   }
97 
98   T ("%*i", W (float), 2);  /* { dg-warning "between 1 and 2147483648 " } */
99   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
100   T ("%*i", W (double), 3); /* { dg-warning "between 1 and 2147483648 " } */
101   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
102 }
103 
test_width_var(void)104 void test_width_var (void)
105 {
106   T ("%*i", W (schar_t), V (schar_t));     /* { dg-warning "between 1 and 128 " } */
107   T ("%*i", W (uchar_t), V (uchar_t));    /* { dg-warning "between 1 and 255 " } */
108 
109   T ("%*i", W (sshort_t), V (sshort_t));  /* { dg-warning "between 1 and 32768 " } */
110   T ("%*i", W (ushort_t), V (ushort_t)); /* { dg-warning "between 1 and 65535 " } */
111 
112   T ("%*i", W (sint_t), V (sint_t));  /* { dg-warning "between 1 and 2147483648 " } */
113   T ("%*i", W (uint_t), V (uint_t)); /* { dg-warning "between 1 and 2147483648 " } */
114 
115   /* Exercise calls with invalid arguments (to verify there is no ICE).  */
116   T ("%*li", W (slong_t), V (slong_t));  /* { dg-warning "between 1 and 2147483648 " } */
117   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
118   T ("%*li", W (ulong_t), V (ulong_t)); /* { dg-warning "between 1 and 2147483648 " } */
119   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
120 
121   T ("%*lli", W (sllong_t), V (sllong_t));  /* { dg-warning "between 1 and 2147483648 " } */
122   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
123   T ("%*lli", W (ullong_t), V (ullong_t)); /* { dg-warning "between 1 and 2147483648 " } */
124   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
125 
126   T ("%*i", W (float), V (int));  /* { dg-warning "between 1 and 2147483648 " } */
127   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
128   T ("%*i", W (double), V (int)); /* { dg-warning "between 1 and 2147483648 " } */
129   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
130 
131   {
132     /* Create an unsigned range with a lower bound greater than 1 and
133        an upper bound in excess of INT_MAX and verify that the lower
134        bound isn't used as the minimum output (since the excessive
135        upper bound wraps around zero).  It's possible to constrain
136        the upper bound on the output more, based on the upper bound
137        of the width here, but not worth the trouble.  */
138     extern unsigned w;
139     if (w < 5 || (unsigned)-1 - 7 < w)
140       w = 5;
141 
142     T ("%*u", w, V (int));   /* { dg-warning "between 1 and 2147483648 " } */
143   }
144 
145   {
146     /* Verify that enums are correctly handled (i.e., that the warning
147        doesn't just test for TREE_CODE(type) == INTEGER_TYPE but instead
148        uses INTEGRAL_TYPE_P() or some equivalent.  */
149     enum WidthEnum { e7 = 7, e9 = 9 };
150     enum WidthEnum w = V (enum WidthEnum);
151     if (w < e7 || e9 < w)
152       w = e7;
153 
154     T ("%*hu", w, V (int));   /* { dg-warning "between 7 and 9 " } */
155   }
156 }
157 
test_precision_cst(void)158 void test_precision_cst (void)
159 {
160   T ("%.*i", P (schar_t), 1);     /* { dg-warning "between 1 and 127 " } */
161   T ("%.*i", P (uchar_t), 12);    /* { dg-warning "between 2 and 255 " } */
162 
163   T ("%.*i", P (sshort_t), 123);  /* { dg-warning "between 3 and 32767 " } */
164   T ("%.*i", P (ushort_t), 1234); /* { dg-warning "between 4 and 65535 " } */
165 
166   T ("%.*i", P (sint_t), 12345);  /* { dg-warning "between 5 and 2147483647 " } */
167   T ("%.*i", P (uint_t), 123456); /* { dg-warning "between 6 and 2147483647 " } */
168 
169   /* Exercise calls with invalid arguments (to verify there is no ICE).  */
170   T ("%.*li", P (slong_t), 1234567L);  /* { dg-warning "between 7 and 2147483647 " } */
171   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
172   T ("%.*li", P (ulong_t), 12345678L); /* { dg-warning "between 8 and 2147483647 " } */
173   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
174 
175   T ("%.*lli", P (sllong_t), 123456789LL);  /* { dg-warning "between 9 and 2147483647 " } */
176   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
177   T ("%.*lli", P (ullong_t), 1234567890LL); /* { dg-warning "between 10 and 2147483647 " } */
178   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
179 
180   T ("%.*i", P (sint128_t), 0);  /* { dg-warning "up to 2147483647 " } */
181   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
182   T ("%.*i", P (uint128_t), 1); /* { dg-warning "between 1 and 2147483647 " } */
183   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
184 
185   {
186     extern sint128_t si128;
187     if (si128 < sint128_max / 2 || sint128_max - 8 < si128)
188       si128 = sint128_max / 2;
189 
190     T ("%.*i", si128, 0);  /* { dg-warning "up to 2147483647 " } */
191     /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
192 
193     extern uint128_t ui128;
194     if (ui128 < uint128_max / 2 || uint128_max - 8 < ui128)
195       ui128 = uint128_max / 2;
196 
197     T ("%.*i", ui128, 0);  /* { dg-warning "up to 2147483647 " } */
198     /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
199   }
200 
201   T ("%.*i", P (float), 0);  /* { dg-warning "up to 2147483647 " } */
202   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
203   T ("%.*i", P (double), 1); /* { dg-warning "between 1 and 2147483647 " } */
204   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
205 }
206 
test_precision_var(void)207 void test_precision_var (void)
208 {
209   T ("%.*i", P (schar_t), V (schar_t));     /* { dg-warning "up to 128 " } */
210   T ("%.*i", P (uchar_t), V (uchar_t));    /* { dg-warning "up to 255 " } */
211 
212   T ("%.*i", P (sshort_t), V (sshort_t));  /* { dg-warning "up to 32768 " } */
213   T ("%.*i", P (ushort_t), V (ushort_t)); /* { dg-warning "up to 65535 " } */
214 
215   T ("%.*i", P (sint_t), V (sint_t));  /* { dg-warning "up to 2147483648 " } */
216   T ("%.*i", P (uint_t), V (uint_t)); /* { dg-warning "up to 2147483648 " } */
217 
218   /* Exercise calls with invalid arguments (to verify there is no ICE).  */
219   T ("%.*li", P (slong_t), V (slong_t));  /* { dg-warning "up to 2147483648 " } */
220   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
221   T ("%.*li", P (ulong_t), V (ulong_t)); /* { dg-warning "up to 2147483648 " } */
222   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
223 
224   T ("%.*lli", P (sllong_t), V (sllong_t));  /* { dg-warning "up to 2147483648" } */
225   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
226   T ("%.*lli", P (ullong_t), V (ullong_t)); /* { dg-warning "up to 2147483648" } */
227   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
228 
229   T ("%.*i", P (float), V (int));  /* { dg-warning "up to 2147483648 " } */
230   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
231   T ("%.*i", P (double), V (int)); /* { dg-warning "up to 2147483648 " } */
232   /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
233 
234   {
235     /* Similar to the corresponding width case, create an unsigned range
236        with a lower bound greater than 1 and an upper bound in excess of
237        INT_MAX and verify that the lower bound isn't used as the minimum
238        output (since the excessive upper bound wraps around zero).  */
239     extern unsigned p;
240     if (p < 7 || (unsigned)-1 - 9 < p)
241       p = 7;
242 
243     T ("%.*u", p, V (int));   /* { dg-warning "up to 2147483647 " } */
244   }
245 
246   {
247     /* Verify that enums are correctly handled.  */
248     enum PrecEnum { e9 = 9, e17 = 17 };
249     enum PrecEnum p = V (enum PrecEnum);
250     if (p < e9 || e17 < p)
251       p = e9;
252 
253     T ("%.*u", p, V (int));   /* { dg-warning "between 9 and 17 " } */
254   }
255 }
256