PR middle-end/77357 - strlen of constant strings not folded
[official-gcc.git] / gcc / testsuite / gcc.c-torture / execute / builtins / stpncpy-chk.c
blob772f19c4e220eab6bb2390898dca5eeab0412754
1 /* Copyright (C) 2004, 2005, 2011 Free Software Foundation.
3 Ensure builtin __stpncpy_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 *stpncpy (char *, const char *, size_t);
10 extern int memcmp (const void *, const void *, size_t);
11 extern int strcmp (const char *, const char *);
12 extern int strncmp (const char *, const char *, size_t);
13 extern void *memset (void *, int, size_t);
15 #include "chk.h"
17 const char s1[] = "123";
18 char p[32] = "";
19 char * volatile s2 = "defg"; /* prevent constant propagation to happen when whole program assumptions are made. */
20 char * volatile s3 = "FGH"; /* prevent constant propagation to happen when whole program assumptions are made. */
21 char *s4;
22 volatile size_t l1 = 1; /* prevent constant propagation to happen when whole program assumptions are made. */
23 int i;
25 void
26 __attribute__((noinline))
27 test1 (void)
29 const char *const src = "hello world";
30 const char *src2;
31 char dst[64], *dst2;
33 chk_calls = 0;
35 memset (dst, 0, sizeof (dst));
36 if (stpncpy (dst, src, 4) != dst+4 || strncmp (dst, src, 4))
37 abort();
39 memset (dst, 0, sizeof (dst));
40 if (stpncpy (dst+16, src, 4) != dst+20 || strncmp (dst+16, src, 4))
41 abort();
43 memset (dst, 0, sizeof (dst));
44 if (stpncpy (dst+32, src+5, 4) != dst+36 || strncmp (dst+32, src+5, 4))
45 abort();
47 memset (dst, 0, sizeof (dst));
48 dst2 = dst;
49 if (stpncpy (++dst2, src+5, 4) != dst+5 || strncmp (dst2, src+5, 4)
50 || dst2 != dst+1)
51 abort();
53 memset (dst, 0, sizeof (dst));
54 if (stpncpy (dst, src, 0) != dst || strcmp (dst, ""))
55 abort();
57 memset (dst, 0, sizeof (dst));
58 dst2 = dst; src2 = src;
59 if (stpncpy (++dst2, ++src2, 0) != dst+1 || strcmp (dst2, "")
60 || dst2 != dst+1 || src2 != src+1)
61 abort();
63 memset (dst, 0, sizeof (dst));
64 dst2 = dst; src2 = src;
65 if (stpncpy (++dst2+5, ++src2+5, 0) != dst+6 || strcmp (dst2+5, "")
66 || dst2 != dst+1 || src2 != src+1)
67 abort();
69 memset (dst, 0, sizeof (dst));
70 if (stpncpy (dst, src, 12) != dst+11 || strcmp (dst, src))
71 abort();
73 /* Test at least one instance of the __builtin_ style. We do this
74 to ensure that it works and that the prototype is correct. */
75 memset (dst, 0, sizeof (dst));
76 if (__builtin_stpncpy (dst, src, 4) != dst+4 || strncmp (dst, src, 4))
77 abort();
79 memset (dst, 0, sizeof (dst));
80 if (stpncpy (dst, i++ ? "xfoo" + 1 : "bar", 4) != dst+3
81 || strcmp (dst, "bar")
82 || i != 1)
83 abort ();
85 /* If return value of stpncpy is ignored, it should be optimized into
86 stpncpy call. */
87 stpncpy_disallowed = 1;
88 stpncpy (dst + 1, src, 4);
89 stpncpy_disallowed = 0;
90 if (strncmp (dst + 1, src, 4))
91 abort ();
93 if (chk_calls)
94 abort ();
97 void
98 __attribute__((noinline))
99 test2 (void)
101 chk_calls = 0;
103 /* No runtime checking should be done here, both destination
104 and length are unknown. */
105 size_t cpy_length = l1 < 4 ? l1 + 1 : 4;
106 if (stpncpy (s4, "abcd", l1 + 1) != s4 + cpy_length || strncmp (s4, "abcd", cpy_length))
107 abort ();
109 if (chk_calls)
110 abort ();
113 /* Test whether compile time checking is done where it should
114 and so is runtime object size checking. */
115 void
116 __attribute__((noinline))
117 test3 (void)
119 struct A { char buf1[10]; char buf2[10]; } a;
120 char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
121 char buf3[20];
122 int i;
123 const char *l;
124 size_t l2;
126 /* The following calls should do runtime checking
127 - source length is not known, but destination is.
128 The returned value is checked so that stpncpy calls
129 are not rewritten to strncpy calls. */
130 chk_calls = 0;
131 if (!stpncpy (a.buf1 + 2, s3 + 3, l1))
132 abort();
133 if (!stpncpy (r, s3 + 2, l1 + 2))
134 abort();
135 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
136 if (!stpncpy (r, s2 + 2, l1 + 2))
137 abort();
138 if (!stpncpy (r + 2, s3 + 3, l1))
139 abort();
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 if (!stpncpy (r, s2 + 4, l1))
153 abort();
154 if (chk_calls != 5)
155 abort ();
157 /* Following have known destination and known length,
158 so if optimizing certainly shouldn't result in the checking
159 variants. */
160 chk_calls = 0;
161 if (!stpncpy (a.buf1 + 2, "", 3))
162 abort ();
163 if (!stpncpy (a.buf1 + 2, "", 0))
164 abort ();
165 if (!stpncpy (r, "a", 1))
166 abort ();
167 if (!stpncpy (r, "a", 3))
168 abort ();
169 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
170 if (!stpncpy (r, s1 + 1, 3))
171 abort ();
172 if (!stpncpy (r, s1 + 1, 2))
173 abort ();
174 r = buf3;
175 l = "abc";
176 l2 = 4;
177 for (i = 0; i < 4; ++i)
179 if (i == l1 - 1)
180 r = &a.buf1[1], l = "e", l2 = 2;
181 else if (i == l1)
182 r = &a.buf2[7], l = "gh", l2 = 3;
183 else if (i == l1 + 1)
184 r = &buf3[5], l = "jkl", l2 = 4;
185 else if (i == l1 + 2)
186 r = &a.buf1[9], l = "", l2 = 1;
188 if (!stpncpy (r, "", 1))
189 abort ();
190 /* Here, strlen (l) + 1 is known to be at most 4 and
191 __builtin_object_size (&buf3[16], 0) is 4, so this doesn't need
192 runtime checking. */
193 if (!stpncpy (&buf3[16], l, l2))
194 abort ();
195 if (!stpncpy (&buf3[15], "abc", l2))
196 abort ();
197 if (!stpncpy (&buf3[10], "fghij", l2))
198 abort ();
199 if (chk_calls)
200 abort ();
201 chk_calls = 0;
204 /* Test whether runtime and/or compile time checking catches
205 buffer overflows. */
206 void
207 __attribute__((noinline))
208 test4 (void)
210 struct A { char buf1[10]; char buf2[10]; } a;
211 char buf3[20];
213 chk_fail_allowed = 1;
214 /* Runtime checks. */
215 if (__builtin_setjmp (chk_fail_buf) == 0)
217 if (stpncpy (&a.buf2[9], s2 + 4, l1 + 1))
218 // returned value used to prevent stpncpy calls
219 // to be rewritten in strncpy calls
220 i++;
221 abort ();
223 if (__builtin_setjmp (chk_fail_buf) == 0)
225 if (stpncpy (&a.buf2[7], s3, l1 + 4))
226 i++;
227 abort ();
229 /* This should be detectable at compile time already. */
230 if (__builtin_setjmp (chk_fail_buf) == 0)
232 if (stpncpy (&buf3[19], "abc", 2))
233 i++;
234 abort ();
236 if (__builtin_setjmp (chk_fail_buf) == 0)
238 if (stpncpy (&buf3[18], "", 3))
239 i++;
240 abort ();
242 chk_fail_allowed = 0;
245 void
246 main_test (void)
248 #ifndef __OPTIMIZE__
249 /* Object size checking is only intended for -O[s123]. */
250 return;
251 #endif
252 __asm ("" : "=r" (s2) : "0" (s2));
253 __asm ("" : "=r" (s3) : "0" (s3));
254 __asm ("" : "=r" (l1) : "0" (l1));
255 test1 ();
257 s4 = p;
258 test2 ();
259 test3 ();
260 test4 ();