PR middle-end/77357 - strlen of constant strings not folded
[official-gcc.git] / gcc / testsuite / gcc.c-torture / execute / builtins / vsnprintf-chk.c
blob8a3f37203e5abac9fb8b57ebc17be0dc8be3bfc2
1 /* Copyright (C) 2004, 2005 Free Software Foundation.
3 Ensure builtin __vsnprintf_chk performs correctly. */
5 #include <stdarg.h>
7 extern void abort (void);
8 typedef __SIZE_TYPE__ size_t;
9 extern size_t strlen(const char *);
10 extern void *memcpy (void *, const void *, size_t);
11 extern char *strcpy (char *, const char *);
12 extern int memcmp (const void *, const void *, size_t);
13 extern void *memset (void *, int, size_t);
14 extern int vsnprintf (char *, size_t, const char *, va_list);
16 #include "chk.h"
18 const char s1[] = "123";
19 char p[32] = "";
20 char *s2 = "defg";
21 char *s3 = "FGH";
22 char *s4;
23 size_t l1 = 1;
24 static char buffer[32];
25 char * volatile ptr = "barf"; /* prevent constant propagation to happen when whole program assumptions are made. */
27 int
28 __attribute__((noinline))
29 test1_sub (int i, ...)
31 int ret = 0;
32 va_list ap;
33 va_start (ap, i);
34 switch (i)
36 case 0:
37 vsnprintf (buffer, 4, "foo", ap);
38 break;
39 case 1:
40 ret = vsnprintf (buffer, 4, "foo bar", ap);
41 break;
42 case 2:
43 vsnprintf (buffer, 32, "%s", ap);
44 break;
45 case 3:
46 ret = vsnprintf (buffer, 21, "%s", ap);
47 break;
48 case 4:
49 ret = vsnprintf (buffer, 4, "%d%d%d", ap);
50 break;
51 case 5:
52 ret = vsnprintf (buffer, 32, "%d%d%d", ap);
53 break;
54 case 6:
55 ret = vsnprintf (buffer, strlen (ptr) + 1, "%s", ap);
56 break;
57 case 7:
58 vsnprintf (buffer, l1 + 31, "%d - %c", ap);
59 break;
60 case 8:
61 vsnprintf (s4, l1 + 6, "%d - %c", ap);
62 break;
64 va_end (ap);
65 return ret;
68 void
69 __attribute__((noinline))
70 test1 (void)
72 chk_calls = 0;
73 /* vsnprintf_disallowed = 1; */
75 memset (buffer, 'A', 32);
76 test1_sub (0);
77 if (memcmp (buffer, "foo", 4) || buffer[4] != 'A')
78 abort ();
80 memset (buffer, 'A', 32);
81 if (test1_sub (1) != 7)
82 abort ();
83 if (memcmp (buffer, "foo", 4) || buffer[4] != 'A')
84 abort ();
86 vsnprintf_disallowed = 0;
88 memset (buffer, 'A', 32);
89 test1_sub (2, "bar");
90 if (memcmp (buffer, "bar", 4) || buffer[4] != 'A')
91 abort ();
93 memset (buffer, 'A', 32);
94 if (test1_sub (3, "bar") != 3)
95 abort ();
96 if (memcmp (buffer, "bar", 4) || buffer[4] != 'A')
97 abort ();
99 memset (buffer, 'A', 32);
100 if (test1_sub (4, (int) l1, (int) l1 + 1, (int) l1 + 12) != 4)
101 abort ();
102 if (memcmp (buffer, "121", 4) || buffer[4] != 'A')
103 abort ();
105 memset (buffer, 'A', 32);
106 if (test1_sub (5, (int) l1, (int) l1 + 1, (int) l1 + 12) != 4)
107 abort ();
108 if (memcmp (buffer, "1213", 5) || buffer[5] != 'A')
109 abort ();
111 if (chk_calls)
112 abort ();
114 memset (buffer, 'A', 32);
115 test1_sub (6, ptr);
116 if (memcmp (buffer, "barf", 5) || buffer[5] != 'A')
117 abort ();
119 memset (buffer, 'A', 32);
120 test1_sub (7, (int) l1 + 27, *ptr);
121 if (memcmp (buffer, "28 - b\0AAAAA", 12))
122 abort ();
124 if (chk_calls != 2)
125 abort ();
126 chk_calls = 0;
128 memset (s4, 'A', 32);
129 test1_sub (8, (int) l1 - 17, ptr[1]);
130 if (memcmp (s4, "-16 - \0AAA", 10))
131 abort ();
132 if (chk_calls)
133 abort ();
136 void
137 __attribute__((noinline))
138 test2_sub (int i, ...)
140 va_list ap;
141 struct A { char buf1[10]; char buf2[10]; } a;
142 char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
143 char buf3[20];
144 int j;
146 va_start (ap, i);
147 /* The following calls should do runtime checking
148 - length is not known, but destination is. */
149 switch (i)
151 case 0:
152 vsnprintf (a.buf1 + 2, l1, "%s", ap);
153 break;
154 case 1:
155 vsnprintf (r, l1 + 4, "%s%c", ap);
156 break;
157 case 2:
158 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
159 vsnprintf (r, strlen (s2) - 2, "%c %s", ap);
160 break;
161 case 3:
162 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
163 vsnprintf (r + 2, l1, s3 + 3, ap);
164 break;
165 case 4:
166 case 7:
167 r = buf3;
168 for (j = 0; j < 4; ++j)
170 if (j == l1 - 1)
171 r = &a.buf1[1];
172 else if (j == l1)
173 r = &a.buf2[7];
174 else if (j == l1 + 1)
175 r = &buf3[5];
176 else if (j == l1 + 2)
177 r = &a.buf1[9];
179 if (i == 4)
180 vsnprintf (r, l1, s2 + 4, ap);
181 else
182 vsnprintf (r, 1, "a", ap);
183 break;
184 case 5:
185 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
186 vsnprintf (r, l1 + 3, "%s", ap);
187 break;
188 case 6:
189 vsnprintf (a.buf1 + 2, 4, "", ap);
190 break;
191 case 8:
192 vsnprintf (s4, 3, "%s %d", ap);
193 break;
195 va_end (ap);
198 /* Test whether compile time checking is done where it should
199 and so is runtime object size checking. */
200 void
201 __attribute__((noinline))
202 test2 (void)
204 /* The following calls should do runtime checking
205 - length is not known, but destination is. */
206 chk_calls = 0;
207 test2_sub (0, s3 + 3);
208 test2_sub (1, s3 + 3, s3[3]);
209 test2_sub (2, s2[2], s2 + 4);
210 test2_sub (3);
211 test2_sub (4);
212 test2_sub (5, s1 + 1);
213 if (chk_calls != 6)
214 abort ();
216 /* Following have known destination and known source length,
217 so if optimizing certainly shouldn't result in the checking
218 variants. */
219 chk_calls = 0;
220 /* vsnprintf_disallowed = 1; */
221 test2_sub (6);
222 test2_sub (7);
223 vsnprintf_disallowed = 0;
224 /* Unknown destination and source, no checking. */
225 test2_sub (8, s3, 0);
226 if (chk_calls)
227 abort ();
230 void
231 __attribute__((noinline))
232 test3_sub (int i, ...)
234 va_list ap;
235 struct A { char buf1[10]; char buf2[10]; } a;
236 char buf3[20];
238 va_start (ap, i);
239 /* The following calls should do runtime checking
240 - source length is not known, but destination is. */
241 switch (i)
243 case 0:
244 vsnprintf (&a.buf2[9], l1 + 1, "%c%s", ap);
245 break;
246 case 1:
247 vsnprintf (&a.buf2[7], l1 + 30, "%s%c", ap);
248 break;
249 case 2:
250 vsnprintf (&a.buf2[7], l1 + 3, "%d", ap);
251 break;
252 case 3:
253 vsnprintf (&buf3[17], l1 + 3, "%s", ap);
254 break;
255 case 4:
256 vsnprintf (&buf3[19], 2, "a", ap);
257 break;
258 case 5:
259 vsnprintf (&buf3[16], 5, "a", ap);
260 break;
262 va_end (ap);
265 /* Test whether runtime and/or compile time checking catches
266 buffer overflows. */
267 void
268 __attribute__((noinline))
269 test3 (void)
271 chk_fail_allowed = 1;
272 /* Runtime checks. */
273 if (__builtin_setjmp (chk_fail_buf) == 0)
275 test3_sub (0, s2[3], s2 + 4);
276 abort ();
278 if (__builtin_setjmp (chk_fail_buf) == 0)
280 test3_sub (1, s3 + strlen (s3) - 2, *s3);
281 abort ();
283 if (__builtin_setjmp (chk_fail_buf) == 0)
285 test3_sub (2, (int) l1 + 9999);
286 abort ();
288 if (__builtin_setjmp (chk_fail_buf) == 0)
290 test3_sub (3, "abc");
291 abort ();
293 /* This should be detectable at compile time already. */
294 if (__builtin_setjmp (chk_fail_buf) == 0)
296 test3_sub (4);
297 abort ();
299 if (__builtin_setjmp (chk_fail_buf) == 0)
301 test3_sub (5);
302 abort ();
304 chk_fail_allowed = 0;
307 void
308 main_test (void)
310 #ifndef __OPTIMIZE__
311 /* Object size checking is only intended for -O[s123]. */
312 return;
313 #endif
314 __asm ("" : "=r" (s2) : "0" (s2));
315 __asm ("" : "=r" (s3) : "0" (s3));
316 __asm ("" : "=r" (l1) : "0" (l1));
317 s4 = p;
318 test1 ();
319 test2 ();
320 test3 ();