PR inline-asm/84742
[official-gcc.git] / gcc / testsuite / gcc.c-torture / execute / builtins / memcpy-chk.c
blob5b245e58e22b697f7050d5d2474ab14db6ff621c
1 /* Copyright (C) 2004, 2005 Free Software Foundation.
3 Ensure builtin __memcpy_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 int memcmp (const void *, const void *, size_t);
11 #include "chk.h"
13 const char s1[] = "123";
14 char p[32] = "";
15 volatile char *s2 = "defg"; /* prevent constant propagation to happen when whole program assumptions are made. */
16 volatile char *s3 = "FGH"; /* prevent constant propagation to happen when whole program assumptions are made. */
17 volatile size_t l1 = 1; /* prevent constant propagation to happen when whole program assumptions are made. */
19 void
20 __attribute__((noinline))
21 test1 (void)
23 int i;
25 #if defined __i386__ || defined __x86_64__
26 /* The functions below might not be optimized into direct stores on all
27 arches. It depends on how many instructions would be generated and
28 what limits the architecture chooses in STORE_BY_PIECES_P. */
29 memcpy_disallowed = 1;
30 #endif
32 /* All the memcpy calls in this routine except last have fixed length, so
33 object size checking should be done at compile time if optimizing. */
34 chk_calls = 0;
36 if (memcpy (p, "ABCDE", 6) != p || memcmp (p, "ABCDE", 6))
37 abort ();
38 if (memcpy (p + 16, "VWX" + 1, 2) != p + 16
39 || memcmp (p + 16, "WX\0\0", 5))
40 abort ();
41 if (memcpy (p + 1, "", 1) != p + 1 || memcmp (p, "A\0CDE", 6))
42 abort ();
43 if (memcpy (p + 3, "FGHI", 4) != p + 3 || memcmp (p, "A\0CFGHI", 8))
44 abort ();
46 i = 8;
47 memcpy (p + 20, "qrstu", 6);
48 memcpy (p + 25, "QRSTU", 6);
49 if (memcpy (p + 25 + 1, s1, 3) != p + 25 + 1
50 || memcmp (p + 25, "Q123U", 6))
51 abort ();
53 if (memcpy (memcpy (p, "abcdEFG", 4) + 4, "efg", 4) != p + 4
54 || memcmp (p, "abcdefg", 8))
55 abort();
57 /* Test at least one instance of the __builtin_ style. We do this
58 to ensure that it works and that the prototype is correct. */
59 if (__builtin_memcpy (p, "ABCDE", 6) != p || memcmp (p, "ABCDE", 6))
60 abort ();
62 memcpy (p + 5, s3, 1);
63 if (memcmp (p, "ABCDEFg", 8))
64 abort ();
66 memcpy_disallowed = 0;
67 if (chk_calls)
68 abort ();
69 chk_calls = 0;
71 memcpy (p + 6, s1 + 1, l1);
72 if (memcmp (p, "ABCDEF2", 8))
73 abort ();
75 /* The above memcpy copies into an object with known size, but
76 unknown length, so it should be a __memcpy_chk call. */
77 if (chk_calls != 1)
78 abort ();
81 long buf1[64];
82 char *buf2 = (char *) (buf1 + 32);
83 long buf5[20];
84 char buf7[20];
86 void
87 __attribute__((noinline))
88 test2_sub (long *buf3, char *buf4, char *buf6, int n)
90 int i = 0;
92 /* All the memcpy/__builtin_memcpy/__builtin___memcpy_chk
93 calls in this routine are either fixed length, or have
94 side-effects in __builtin_object_size arguments, or
95 dst doesn't point into a known object. */
96 chk_calls = 0;
98 /* These should probably be handled by store_by_pieces on most arches. */
99 if (memcpy (buf1, "ABCDEFGHI", 9) != (char *) buf1
100 || memcmp (buf1, "ABCDEFGHI\0", 11))
101 abort ();
103 if (memcpy (buf1, "abcdefghijklmnopq", 17) != (char *) buf1
104 || memcmp (buf1, "abcdefghijklmnopq\0", 19))
105 abort ();
107 if (__builtin_memcpy (buf3, "ABCDEF", 6) != (char *) buf1
108 || memcmp (buf1, "ABCDEFghijklmnopq\0", 19))
109 abort ();
111 if (__builtin_memcpy (buf3, "a", 1) != (char *) buf1
112 || memcmp (buf1, "aBCDEFghijklmnopq\0", 19))
113 abort ();
115 if (memcpy ((char *) buf3 + 2, "bcd" + ++i, 2) != (char *) buf1 + 2
116 || memcmp (buf1, "aBcdEFghijklmnopq\0", 19)
117 || i != 1)
118 abort ();
120 /* These should probably be handled by move_by_pieces on most arches. */
121 if (memcpy ((char *) buf3 + 4, buf5, 6) != (char *) buf1 + 4
122 || memcmp (buf1, "aBcdRSTUVWklmnopq\0", 19))
123 abort ();
125 if (__builtin_memcpy ((char *) buf1 + ++i + 8, (char *) buf5 + 1, 1)
126 != (char *) buf1 + 10
127 || memcmp (buf1, "aBcdRSTUVWSlmnopq\0", 19)
128 || i != 2)
129 abort ();
131 if (memcpy ((char *) buf3 + 14, buf6, 2) != (char *) buf1 + 14
132 || memcmp (buf1, "aBcdRSTUVWSlmnrsq\0", 19))
133 abort ();
135 if (memcpy (buf3, buf5, 8) != (char *) buf1
136 || memcmp (buf1, "RSTUVWXYVWSlmnrsq\0", 19))
137 abort ();
139 if (memcpy (buf3, buf5, 17) != (char *) buf1
140 || memcmp (buf1, "RSTUVWXYZ01234567\0", 19))
141 abort ();
143 __builtin_memcpy (buf3, "aBcdEFghijklmnopq\0", 19);
145 /* These should be handled either by movmemendM or memcpy
146 call. */
148 /* buf3 points to an unknown object, so __memcpy_chk should not be done. */
149 if (memcpy ((char *) buf3 + 4, buf5, n + 6) != (char *) buf1 + 4
150 || memcmp (buf1, "aBcdRSTUVWklmnopq\0", 19))
151 abort ();
153 /* This call has side-effects in dst, therefore no checking. */
154 if (__builtin___memcpy_chk ((char *) buf1 + ++i + 8, (char *) buf5 + 1,
155 n + 1, os ((char *) buf1 + ++i + 8))
156 != (char *) buf1 + 11
157 || memcmp (buf1, "aBcdRSTUVWkSmnopq\0", 19)
158 || i != 3)
159 abort ();
161 if (memcpy ((char *) buf3 + 14, buf6, n + 2) != (char *) buf1 + 14
162 || memcmp (buf1, "aBcdRSTUVWkSmnrsq\0", 19))
163 abort ();
165 i = 1;
167 /* These might be handled by store_by_pieces. */
168 if (memcpy (buf2, "ABCDEFGHI", 9) != buf2
169 || memcmp (buf2, "ABCDEFGHI\0", 11))
170 abort ();
172 if (memcpy (buf2, "abcdefghijklmnopq", 17) != buf2
173 || memcmp (buf2, "abcdefghijklmnopq\0", 19))
174 abort ();
176 if (__builtin_memcpy (buf4, "ABCDEF", 6) != buf2
177 || memcmp (buf2, "ABCDEFghijklmnopq\0", 19))
178 abort ();
180 if (__builtin_memcpy (buf4, "a", 1) != buf2
181 || memcmp (buf2, "aBCDEFghijklmnopq\0", 19))
182 abort ();
184 if (memcpy (buf4 + 2, "bcd" + i++, 2) != buf2 + 2
185 || memcmp (buf2, "aBcdEFghijklmnopq\0", 19)
186 || i != 2)
187 abort ();
189 /* These might be handled by move_by_pieces. */
190 if (memcpy (buf4 + 4, buf7, 6) != buf2 + 4
191 || memcmp (buf2, "aBcdRSTUVWklmnopq\0", 19))
192 abort ();
194 /* Side effect. */
195 if (__builtin___memcpy_chk (buf2 + i++ + 8, buf7 + 1, 1,
196 os (buf2 + i++ + 8))
197 != buf2 + 10
198 || memcmp (buf2, "aBcdRSTUVWSlmnopq\0", 19)
199 || i != 3)
200 abort ();
202 if (memcpy (buf4 + 14, buf6, 2) != buf2 + 14
203 || memcmp (buf2, "aBcdRSTUVWSlmnrsq\0", 19))
204 abort ();
206 __builtin_memcpy (buf4, "aBcdEFghijklmnopq\0", 19);
208 /* These should be handled either by movmemendM or memcpy
209 call. */
210 if (memcpy (buf4 + 4, buf7, n + 6) != buf2 + 4
211 || memcmp (buf2, "aBcdRSTUVWklmnopq\0", 19))
212 abort ();
214 /* Side effect. */
215 if (__builtin___memcpy_chk (buf2 + i++ + 8, buf7 + 1, n + 1,
216 os (buf2 + i++ + 8))
217 != buf2 + 11
218 || memcmp (buf2, "aBcdRSTUVWkSmnopq\0", 19)
219 || i != 4)
220 abort ();
222 if (memcpy (buf4 + 14, buf6, n + 2) != buf2 + 14
223 || memcmp (buf2, "aBcdRSTUVWkSmnrsq\0", 19))
224 abort ();
226 if (chk_calls)
227 abort ();
230 void
231 __attribute__((noinline))
232 test2 (void)
234 long *x;
235 char *y;
236 int z;
237 __builtin_memcpy (buf5, "RSTUVWXYZ0123456789", 20);
238 __builtin_memcpy (buf7, "RSTUVWXYZ0123456789", 20);
239 __asm ("" : "=r" (x) : "0" (buf1));
240 __asm ("" : "=r" (y) : "0" (buf2));
241 __asm ("" : "=r" (z) : "0" (0));
242 test2_sub (x, y, "rstuvwxyz", z);
245 /* Test whether compile time checking is done where it should
246 and so is runtime object size checking. */
247 void
248 __attribute__((noinline))
249 test3 (void)
251 struct A { char buf1[10]; char buf2[10]; } a;
252 char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
253 char buf3[20];
254 int i;
255 size_t l;
257 /* The following calls should do runtime checking
258 - length is not known, but destination is. */
259 chk_calls = 0;
260 memcpy (a.buf1 + 2, s3, l1);
261 memcpy (r, s3, l1 + 1);
262 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
263 memcpy (r, s2, l1 + 2);
264 memcpy (r + 2, s3, l1);
265 r = buf3;
266 for (i = 0; i < 4; ++i)
268 if (i == l1 - 1)
269 r = &a.buf1[1];
270 else if (i == l1)
271 r = &a.buf2[7];
272 else if (i == l1 + 1)
273 r = &buf3[5];
274 else if (i == l1 + 2)
275 r = &a.buf1[9];
277 memcpy (r, s2, l1);
278 if (chk_calls != 5)
279 abort ();
281 /* Following have known destination and known length,
282 so if optimizing certainly shouldn't result in the checking
283 variants. */
284 chk_calls = 0;
285 memcpy (a.buf1 + 2, s3, 1);
286 memcpy (r, s3, 2);
287 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
288 memcpy (r, s2, 3);
289 r = buf3;
290 l = 4;
291 for (i = 0; i < 4; ++i)
293 if (i == l1 - 1)
294 r = &a.buf1[1], l = 2;
295 else if (i == l1)
296 r = &a.buf2[7], l = 3;
297 else if (i == l1 + 1)
298 r = &buf3[5], l = 4;
299 else if (i == l1 + 2)
300 r = &a.buf1[9], l = 1;
302 memcpy (r, s2, 1);
303 /* Here, l is known to be at most 4 and __builtin_object_size (&buf3[16], 0)
304 is 4, so this doesn't need runtime checking. */
305 memcpy (&buf3[16], s2, l);
306 if (chk_calls)
307 abort ();
308 chk_calls = 0;
311 /* Test whether runtime and/or compile time checking catches
312 buffer overflows. */
313 void
314 __attribute__((noinline))
315 test4 (void)
317 struct A { char buf1[10]; char buf2[10]; } a;
318 char buf3[20];
320 chk_fail_allowed = 1;
321 /* Runtime checks. */
322 if (__builtin_setjmp (chk_fail_buf) == 0)
324 memcpy (&a.buf2[9], s2, l1 + 1);
325 abort ();
327 if (__builtin_setjmp (chk_fail_buf) == 0)
329 memcpy (&a.buf2[7], s3, strlen (s3) + 1);
330 abort ();
332 /* This should be detectable at compile time already. */
333 if (__builtin_setjmp (chk_fail_buf) == 0)
335 memcpy (&buf3[19], "ab", 2);
336 abort ();
338 chk_fail_allowed = 0;
341 #ifndef MAX_OFFSET
342 #define MAX_OFFSET (sizeof (long long))
343 #endif
345 #ifndef MAX_COPY
346 #define MAX_COPY (10 * sizeof (long long))
347 #endif
349 #ifndef MAX_EXTRA
350 #define MAX_EXTRA (sizeof (long long))
351 #endif
353 #define MAX_LENGTH (MAX_OFFSET + MAX_COPY + MAX_EXTRA)
355 /* Use a sequence length that is not divisible by two, to make it more
356 likely to detect when words are mixed up. */
357 #define SEQUENCE_LENGTH 31
359 static union {
360 char buf[MAX_LENGTH];
361 long long align_int;
362 long double align_fp;
363 } u1, u2;
365 void
366 __attribute__((noinline))
367 test5 (void)
369 int off1, off2, len, i;
370 char *p, *q, c;
372 for (off1 = 0; off1 < MAX_OFFSET; off1++)
373 for (off2 = 0; off2 < MAX_OFFSET; off2++)
374 for (len = 1; len < MAX_COPY; len++)
376 for (i = 0, c = 'A'; i < MAX_LENGTH; i++, c++)
378 u1.buf[i] = 'a';
379 if (c >= 'A' + SEQUENCE_LENGTH)
380 c = 'A';
381 u2.buf[i] = c;
384 p = memcpy (u1.buf + off1, u2.buf + off2, len);
385 if (p != u1.buf + off1)
386 abort ();
388 q = u1.buf;
389 for (i = 0; i < off1; i++, q++)
390 if (*q != 'a')
391 abort ();
393 for (i = 0, c = 'A' + off2; i < len; i++, q++, c++)
395 if (c >= 'A' + SEQUENCE_LENGTH)
396 c = 'A';
397 if (*q != c)
398 abort ();
401 for (i = 0; i < MAX_EXTRA; i++, q++)
402 if (*q != 'a')
403 abort ();
407 #define TESTSIZE 80
409 char srcb[TESTSIZE] __attribute__ ((aligned));
410 char dstb[TESTSIZE] __attribute__ ((aligned));
412 void
413 __attribute__((noinline))
414 check (char *test, char *match, int n)
416 if (memcmp (test, match, n))
417 abort ();
420 #define TN(n) \
421 { memset (dstb, 0, n); memcpy (dstb, srcb, n); check (dstb, srcb, n); }
422 #define T(n) \
423 TN (n) \
424 TN ((n) + 1) \
425 TN ((n) + 2) \
426 TN ((n) + 3)
428 void
429 __attribute__((noinline))
430 test6 (void)
432 int i;
434 chk_calls = 0;
436 for (i = 0; i < sizeof (srcb); ++i)
437 srcb[i] = 'a' + i % 26;
439 T (0);
440 T (4);
441 T (8);
442 T (12);
443 T (16);
444 T (20);
445 T (24);
446 T (28);
447 T (32);
448 T (36);
449 T (40);
450 T (44);
451 T (48);
452 T (52);
453 T (56);
454 T (60);
455 T (64);
456 T (68);
457 T (72);
458 T (76);
460 /* All memcpy calls in this routine have constant arguments. */
461 if (chk_calls)
462 abort ();
465 void
466 main_test (void)
468 #ifndef __OPTIMIZE__
469 /* Object size checking is only intended for -O[s123]. */
470 return;
471 #endif
472 __asm ("" : "=r" (l1) : "0" (l1));
473 test1 ();
474 test2 ();
475 test3 ();
476 test4 ();
477 test5 ();
478 test6 ();