snprintf-chk.c (ptr): Declare volatile.
[official-gcc.git] / gcc / testsuite / gcc.c-torture / execute / builtins / snprintf-chk.c
blobb244f8925190430f2073604438b78c69de7dc306
1 /* Copyright (C) 2004, 2005 Free Software Foundation.
3 Ensure builtin __snprintf_chk performs correctly. */
5 extern void abort (void);
6 typedef __SIZE_TYPE__ size_t;
7 extern size_t strlen(const char *);
8 extern void *memcpy (void *, const void *, size_t);
9 extern char *strcpy (char *, const char *);
10 extern int memcmp (const void *, const void *, size_t);
11 extern void *memset (void *, int, size_t);
12 extern int sprintf (char *, const char *, ...);
13 extern int snprintf (char *, size_t, const char *, ...);
15 #include "chk.h"
17 const char s1[] = "123";
18 char p[32] = "";
19 char *s2 = "defg";
20 char *s3 = "FGH";
21 char *s4;
22 size_t l1 = 1;
23 static char buffer[32];
24 char * volatile ptr = "barf"; /* prevent constant propagation to happen when whole program assumptions are made. */
26 void
27 __attribute__((noinline))
28 test1 (void)
30 chk_calls = 0;
31 /* snprintf_disallowed = 1; */
33 memset (buffer, 'A', 32);
34 snprintf (buffer, 4, "foo");
35 if (memcmp (buffer, "foo", 4) || buffer[4] != 'A')
36 abort ();
38 memset (buffer, 'A', 32);
39 if (snprintf (buffer, 4, "foo bar") != 7)
40 abort ();
41 if (memcmp (buffer, "foo", 4) || buffer[4] != 'A')
42 abort ();
44 memset (buffer, 'A', 32);
45 snprintf (buffer, 32, "%s", "bar");
46 if (memcmp (buffer, "bar", 4) || buffer[4] != 'A')
47 abort ();
49 memset (buffer, 'A', 32);
50 if (snprintf (buffer, 21, "%s", "bar") != 3)
51 abort ();
52 if (memcmp (buffer, "bar", 4) || buffer[4] != 'A')
53 abort ();
55 snprintf_disallowed = 0;
57 memset (buffer, 'A', 32);
58 if (snprintf (buffer, 4, "%d%d%d", (int) l1, (int) l1 + 1, (int) l1 + 12)
59 != 4)
60 abort ();
61 if (memcmp (buffer, "121", 4) || buffer[4] != 'A')
62 abort ();
64 memset (buffer, 'A', 32);
65 if (snprintf (buffer, 32, "%d%d%d", (int) l1, (int) l1 + 1, (int) l1 + 12)
66 != 4)
67 abort ();
68 if (memcmp (buffer, "1213", 5) || buffer[5] != 'A')
69 abort ();
71 if (chk_calls)
72 abort ();
74 memset (buffer, 'A', 32);
75 snprintf (buffer, strlen (ptr) + 1, "%s", ptr);
76 if (memcmp (buffer, "barf", 5) || buffer[5] != 'A')
77 abort ();
79 memset (buffer, 'A', 32);
80 snprintf (buffer, l1 + 31, "%d - %c", (int) l1 + 27, *ptr);
81 if (memcmp (buffer, "28 - b\0AAAAA", 12))
82 abort ();
84 if (chk_calls != 2)
85 abort ();
86 chk_calls = 0;
88 memset (s4, 'A', 32);
89 snprintf (s4, l1 + 6, "%d - %c", (int) l1 - 17, ptr[1]);
90 if (memcmp (s4, "-16 - \0AAA", 10))
91 abort ();
92 if (chk_calls)
93 abort ();
96 /* Test whether compile time checking is done where it should
97 and so is runtime object size checking. */
98 void
99 __attribute__((noinline))
100 test2 (void)
102 struct A { char buf1[10]; char buf2[10]; } a;
103 char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
104 char buf3[20];
105 int i;
107 /* The following calls should do runtime checking
108 - length is not known, but destination is. */
109 chk_calls = 0;
110 snprintf (a.buf1 + 2, l1, "%s", s3 + 3);
111 snprintf (r, l1 + 4, "%s%c", s3 + 3, s3[3]);
112 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
113 snprintf (r, strlen (s2) - 2, "%c %s", s2[2], s2 + 4);
114 snprintf (r + 2, l1, s3 + 3);
115 r = buf3;
116 for (i = 0; i < 4; ++i)
118 if (i == l1 - 1)
119 r = &a.buf1[1];
120 else if (i == l1)
121 r = &a.buf2[7];
122 else if (i == l1 + 1)
123 r = &buf3[5];
124 else if (i == l1 + 2)
125 r = &a.buf1[9];
127 snprintf (r, l1, s2 + 4);
128 if (chk_calls != 5)
129 abort ();
131 /* Following have known destination and known source length,
132 so if optimizing certainly shouldn't result in the checking
133 variants. */
134 chk_calls = 0;
135 /* snprintf_disallowed = 1; */
136 snprintf (a.buf1 + 2, 4, "");
137 snprintf (r, 1, "a");
138 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
139 snprintf (r, 3, "%s", s1 + 1);
140 r = buf3;
141 for (i = 0; i < 4; ++i)
143 if (i == l1 - 1)
144 r = &a.buf1[1];
145 else if (i == l1)
146 r = &a.buf2[7];
147 else if (i == l1 + 1)
148 r = &buf3[5];
149 else if (i == l1 + 2)
150 r = &a.buf1[9];
152 snprintf (r, 1, "%s", "");
153 snprintf (r, 0, "%s", "");
154 snprintf_disallowed = 0;
155 /* Unknown destination and source, no checking. */
156 snprintf (s4, l1 + 31, "%s %d", s3, 0);
157 if (chk_calls)
158 abort ();
161 /* Test whether runtime and/or compile time checking catches
162 buffer overflows. */
163 void
164 __attribute__((noinline))
165 test3 (void)
167 struct A { char buf1[10]; char buf2[10]; } a;
168 char buf3[20];
170 chk_fail_allowed = 1;
171 /* Runtime checks. */
172 if (__builtin_setjmp (chk_fail_buf) == 0)
174 snprintf (&a.buf2[9], l1 + 1, "%c%s", s2[3], s2 + 4);
175 abort ();
177 if (__builtin_setjmp (chk_fail_buf) == 0)
179 snprintf (&a.buf2[7], l1 + 30, "%s%c", s3 + strlen (s3) - 2, *s3);
180 abort ();
182 if (__builtin_setjmp (chk_fail_buf) == 0)
184 snprintf (&a.buf2[7], l1 + 3, "%d", (int) l1 + 9999);
185 abort ();
187 /* This should be detectable at compile time already. */
188 if (__builtin_setjmp (chk_fail_buf) == 0)
190 snprintf (&buf3[19], 2, "a");
191 abort ();
193 if (__builtin_setjmp (chk_fail_buf) == 0)
195 snprintf (&buf3[17], 4, "a");
196 abort ();
198 if (__builtin_setjmp (chk_fail_buf) == 0)
200 snprintf (&buf3[17], 4, "%s", "abc");
201 abort ();
203 chk_fail_allowed = 0;
206 void
207 main_test (void)
209 #ifndef __OPTIMIZE__
210 /* Object size checking is only intended for -O[s123]. */
211 return;
212 #endif
213 __asm ("" : "=r" (s2) : "0" (s2));
214 __asm ("" : "=r" (s3) : "0" (s3));
215 __asm ("" : "=r" (l1) : "0" (l1));
216 s4 = p;
217 test1 ();
218 test2 ();
219 test3 ();