PR middle-end/77357 - strlen of constant strings not folded
[official-gcc.git] / gcc / testsuite / gcc.c-torture / execute / builtins / memmove-chk.c
blob73b35883ed1f88583de9a62a2ffa71ac8b01166d
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 void *memmove (void *, const void *, size_t);
10 extern int memcmp (const void *, const void *, size_t);
12 #include "chk.h"
14 const char s1[] = "123";
15 char p[32] = "";
16 volatile char *s2 = "defg"; /* prevent constant propagation to happen when whole program assumptions are made. */
17 volatile char *s3 = "FGH"; /* prevent constant propagation to happen when whole program assumptions are made. */
18 volatile size_t l1 = 1; /* prevent constant propagation to happen when whole program assumptions are made. */
20 void
21 __attribute__((noinline))
22 test1 (void)
24 int i;
26 #if defined __i386__ || defined __x86_64__
27 /* The functions below might not be optimized into direct stores on all
28 arches. It depends on how many instructions would be generated and
29 what limits the architecture chooses in STORE_BY_PIECES_P. */
30 memmove_disallowed = 1;
31 memcpy_disallowed = 1;
32 #endif
34 /* All the memmove calls in this routine except last have fixed length, so
35 object size checking should be done at compile time if optimizing. */
36 chk_calls = 0;
38 if (memmove (p, "ABCDE", 6) != p || memcmp (p, "ABCDE", 6))
39 abort ();
40 if (memmove (p + 16, "VWX" + 1, 2) != p + 16
41 || memcmp (p + 16, "WX\0\0", 5))
42 abort ();
43 if (memmove (p + 1, "", 1) != p + 1 || memcmp (p, "A\0CDE", 6))
44 abort ();
45 if (memmove (p + 3, "FGHI", 4) != p + 3 || memcmp (p, "A\0CFGHI", 8))
46 abort ();
48 i = 8;
49 memmove (p + 20, "qrstu", 6);
50 memmove (p + 25, "QRSTU", 6);
51 if (memmove (p + 25 + 1, s1, 3) != p + 25 + 1
52 || memcmp (p + 25, "Q123U", 6))
53 abort ();
55 if (memmove (memmove (p, "abcdEFG", 4) + 4, "efg", 4) != p + 4
56 || memcmp (p, "abcdefg", 8))
57 abort();
59 /* Test at least one instance of the __builtin_ style. We do this
60 to ensure that it works and that the prototype is correct. */
61 if (__builtin_memmove (p, "ABCDE", 6) != p || memcmp (p, "ABCDE", 6))
62 abort ();
64 memmove (p + 5, s3, 1);
65 if (memcmp (p, "ABCDEFg", 8))
66 abort ();
68 memmove_disallowed = 0;
69 memcpy_disallowed = 0;
70 if (chk_calls)
71 abort ();
72 chk_calls = 0;
74 memmove (p + 6, s1 + 1, l1);
75 if (memcmp (p, "ABCDEF2", 8))
76 abort ();
78 /* The above memmove copies into an object with known size, but
79 unknown length, so it should be a __memmove_chk call. */
80 if (chk_calls != 1)
81 abort ();
84 long buf1[64];
85 char *buf2 = (char *) (buf1 + 32);
86 long buf5[20];
87 char buf7[20];
89 void
90 __attribute__((noinline))
91 test2_sub (long *buf3, char *buf4, char *buf6, int n)
93 int i = 0;
95 /* All the memmove/__builtin_memmove/__builtin___memmove_chk
96 calls in this routine are either fixed length, or have
97 side-effects in __builtin_object_size arguments, or
98 dst doesn't point into a known object. */
99 chk_calls = 0;
101 /* These should probably be handled by store_by_pieces on most arches. */
102 if (memmove (buf1, "ABCDEFGHI", 9) != (char *) buf1
103 || memcmp (buf1, "ABCDEFGHI\0", 11))
104 abort ();
106 if (memmove (buf1, "abcdefghijklmnopq", 17) != (char *) buf1
107 || memcmp (buf1, "abcdefghijklmnopq\0", 19))
108 abort ();
110 if (__builtin_memmove (buf3, "ABCDEF", 6) != (char *) buf1
111 || memcmp (buf1, "ABCDEFghijklmnopq\0", 19))
112 abort ();
114 if (__builtin_memmove (buf3, "a", 1) != (char *) buf1
115 || memcmp (buf1, "aBCDEFghijklmnopq\0", 19))
116 abort ();
118 if (memmove ((char *) buf3 + 2, "bcd" + ++i, 2) != (char *) buf1 + 2
119 || memcmp (buf1, "aBcdEFghijklmnopq\0", 19)
120 || i != 1)
121 abort ();
123 /* These should probably be handled by move_by_pieces on most arches. */
124 if (memmove ((char *) buf3 + 4, buf5, 6) != (char *) buf1 + 4
125 || memcmp (buf1, "aBcdRSTUVWklmnopq\0", 19))
126 abort ();
128 if (__builtin_memmove ((char *) buf1 + ++i + 8, (char *) buf5 + 1, 1)
129 != (char *) buf1 + 10
130 || memcmp (buf1, "aBcdRSTUVWSlmnopq\0", 19)
131 || i != 2)
132 abort ();
134 if (memmove ((char *) buf3 + 14, buf6, 2) != (char *) buf1 + 14
135 || memcmp (buf1, "aBcdRSTUVWSlmnrsq\0", 19))
136 abort ();
138 if (memmove (buf3, buf5, 8) != (char *) buf1
139 || memcmp (buf1, "RSTUVWXYVWSlmnrsq\0", 19))
140 abort ();
142 if (memmove (buf3, buf5, 17) != (char *) buf1
143 || memcmp (buf1, "RSTUVWXYZ01234567\0", 19))
144 abort ();
146 __builtin_memmove (buf3, "aBcdEFghijklmnopq\0", 19);
148 /* These should be handled either by movmemendM or memmove
149 call. */
151 /* buf3 points to an unknown object, so __memmove_chk should not be done. */
152 if (memmove ((char *) buf3 + 4, buf5, n + 6) != (char *) buf1 + 4
153 || memcmp (buf1, "aBcdRSTUVWklmnopq\0", 19))
154 abort ();
156 /* This call has side-effects in dst, therefore no checking. */
157 if (__builtin___memmove_chk ((char *) buf1 + ++i + 8, (char *) buf5 + 1,
158 n + 1, os ((char *) buf1 + ++i + 8))
159 != (char *) buf1 + 11
160 || memcmp (buf1, "aBcdRSTUVWkSmnopq\0", 19)
161 || i != 3)
162 abort ();
164 if (memmove ((char *) buf3 + 14, buf6, n + 2) != (char *) buf1 + 14
165 || memcmp (buf1, "aBcdRSTUVWkSmnrsq\0", 19))
166 abort ();
168 i = 1;
170 /* These might be handled by store_by_pieces. */
171 if (memmove (buf2, "ABCDEFGHI", 9) != buf2
172 || memcmp (buf2, "ABCDEFGHI\0", 11))
173 abort ();
175 if (memmove (buf2, "abcdefghijklmnopq", 17) != buf2
176 || memcmp (buf2, "abcdefghijklmnopq\0", 19))
177 abort ();
179 if (__builtin_memmove (buf4, "ABCDEF", 6) != buf2
180 || memcmp (buf2, "ABCDEFghijklmnopq\0", 19))
181 abort ();
183 if (__builtin_memmove (buf4, "a", 1) != buf2
184 || memcmp (buf2, "aBCDEFghijklmnopq\0", 19))
185 abort ();
187 if (memmove (buf4 + 2, "bcd" + i++, 2) != buf2 + 2
188 || memcmp (buf2, "aBcdEFghijklmnopq\0", 19)
189 || i != 2)
190 abort ();
192 /* These might be handled by move_by_pieces. */
193 if (memmove (buf4 + 4, buf7, 6) != buf2 + 4
194 || memcmp (buf2, "aBcdRSTUVWklmnopq\0", 19))
195 abort ();
197 /* Side effect. */
198 if (__builtin___memmove_chk (buf2 + i++ + 8, buf7 + 1, 1,
199 os (buf2 + i++ + 8))
200 != buf2 + 10
201 || memcmp (buf2, "aBcdRSTUVWSlmnopq\0", 19)
202 || i != 3)
203 abort ();
205 if (memmove (buf4 + 14, buf6, 2) != buf2 + 14
206 || memcmp (buf2, "aBcdRSTUVWSlmnrsq\0", 19))
207 abort ();
209 __builtin_memmove (buf4, "aBcdEFghijklmnopq\0", 19);
211 /* These should be handled either by movmemendM or memmove
212 call. */
213 if (memmove (buf4 + 4, buf7, n + 6) != buf2 + 4
214 || memcmp (buf2, "aBcdRSTUVWklmnopq\0", 19))
215 abort ();
217 /* Side effect. */
218 if (__builtin___memmove_chk (buf2 + i++ + 8, buf7 + 1, n + 1,
219 os (buf2 + i++ + 8))
220 != buf2 + 11
221 || memcmp (buf2, "aBcdRSTUVWkSmnopq\0", 19)
222 || i != 4)
223 abort ();
225 if (memmove (buf4 + 14, buf6, n + 2) != buf2 + 14
226 || memcmp (buf2, "aBcdRSTUVWkSmnrsq\0", 19))
227 abort ();
229 if (chk_calls)
230 abort ();
233 void
234 __attribute__((noinline))
235 test2 (void)
237 long *x;
238 char *y;
239 int z;
240 __builtin_memmove (buf5, "RSTUVWXYZ0123456789", 20);
241 __builtin_memmove (buf7, "RSTUVWXYZ0123456789", 20);
242 __asm ("" : "=r" (x) : "0" (buf1));
243 __asm ("" : "=r" (y) : "0" (buf2));
244 __asm ("" : "=r" (z) : "0" (0));
245 test2_sub (x, y, "rstuvwxyz", z);
248 static const struct foo
250 char *s;
251 double d;
252 long l;
253 } foo[] =
255 { "hello world1", 3.14159, 101L },
256 { "hello world2", 3.14159, 102L },
257 { "hello world3", 3.14159, 103L },
258 { "hello world4", 3.14159, 104L },
259 { "hello world5", 3.14159, 105L },
260 { "hello world6", 3.14159, 106L }
263 static const struct bar
265 char *s;
266 const struct foo f[3];
267 } bar[] =
270 "hello world10",
272 { "hello1", 3.14159, 201L },
273 { "hello2", 3.14159, 202L },
274 { "hello3", 3.14159, 203L },
278 "hello world11",
280 { "hello4", 3.14159, 204L },
281 { "hello5", 3.14159, 205L },
282 { "hello6", 3.14159, 206L },
287 static const int baz[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
289 void
290 __attribute__((noinline))
291 test3 (void)
293 const char *s;
294 struct foo f1[sizeof foo/sizeof*foo];
295 struct bar b1[sizeof bar/sizeof*bar];
296 int bz[sizeof baz/sizeof*baz];
298 /* All the memmove/__builtin_memmove calls in this routine have fixed
299 length. */
300 chk_calls = 0;
302 /* All the *memmove calls below have src in read-only memory, so all
303 of them should be optimized into memcpy. */
304 memmove_disallowed = 1;
305 if (memmove (f1, foo, sizeof (foo)) != f1 || memcmp (f1, foo, sizeof (foo)))
306 abort ();
307 if (memmove (b1, bar, sizeof (bar)) != b1 || memcmp (b1, bar, sizeof (bar)))
308 abort ();
309 memmove (bz, baz, sizeof (baz));
310 if (memcmp (bz, baz, sizeof (baz)))
311 abort ();
313 if (memmove (p, "abcde", 6) != p || memcmp (p, "abcde", 6))
314 abort ();
315 s = s1;
316 if (memmove (p + 2, ++s, 0) != p + 2 || memcmp (p, "abcde", 6) || s != s1 + 1)
317 abort ();
318 if (__builtin_memmove (p + 3, "", 1) != p + 3 || memcmp (p, "abc\0e", 6))
319 abort ();
320 memmove (p + 2, "fghijk", 4);
321 if (memcmp (p, "abfghi", 7))
322 abort ();
323 s = s1 + 1;
324 memmove (p + 1, s++, 0);
325 if (memcmp (p, "abfghi", 7) || s != s1 + 2)
326 abort ();
327 __builtin_memmove (p + 4, "ABCDE", 1);
328 if (memcmp (p, "abfgAi", 7))
329 abort ();
331 /* memmove with length 1 can be optimized into memcpy if it can be
332 expanded inline. */
333 if (memmove (p + 2, p + 3, 1) != p + 2)
334 abort ();
335 if (memcmp (p, "abggAi", 7))
336 abort ();
338 if (chk_calls)
339 abort ();
340 memmove_disallowed = 0;
343 /* Test whether compile time checking is done where it should
344 and so is runtime object size checking. */
345 void
346 __attribute__((noinline))
347 test4 (void)
349 struct A { char buf1[10]; char buf2[10]; } a;
350 char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
351 char buf3[20];
352 int i;
353 size_t l;
355 /* The following calls should do runtime checking
356 - length is not known, but destination is. */
357 chk_calls = 0;
358 memmove (a.buf1 + 2, s3, l1);
359 memmove (r, s3, l1 + 1);
360 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
361 memmove (r, s2, l1 + 2);
362 memmove (r + 2, s3, l1);
363 r = buf3;
364 for (i = 0; i < 4; ++i)
366 if (i == l1 - 1)
367 r = &a.buf1[1];
368 else if (i == l1)
369 r = &a.buf2[7];
370 else if (i == l1 + 1)
371 r = &buf3[5];
372 else if (i == l1 + 2)
373 r = &a.buf1[9];
375 memmove (r, s2, l1);
376 if (chk_calls != 5)
377 abort ();
379 /* Following have known destination and known length,
380 so if optimizing certainly shouldn't result in the checking
381 variants. */
382 chk_calls = 0;
383 memmove (a.buf1 + 2, s3, 1);
384 memmove (r, s3, 2);
385 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
386 memmove (r, s2, 3);
387 r = buf3;
388 l = 4;
389 for (i = 0; i < 4; ++i)
391 if (i == l1 - 1)
392 r = &a.buf1[1], l = 2;
393 else if (i == l1)
394 r = &a.buf2[7], l = 3;
395 else if (i == l1 + 1)
396 r = &buf3[5], l = 4;
397 else if (i == l1 + 2)
398 r = &a.buf1[9], l = 1;
400 memmove (r, s2, 1);
401 /* Here, l is known to be at most 4 and __builtin_object_size (&buf3[16], 0)
402 is 4, so this doesn't need runtime checking. */
403 memmove (&buf3[16], s2, l);
404 if (chk_calls)
405 abort ();
406 chk_calls = 0;
409 /* Test whether runtime and/or compile time checking catches
410 buffer overflows. */
411 void
412 __attribute__((noinline))
413 test5 (void)
415 struct A { char buf1[10]; char buf2[10]; } a;
416 char buf3[20];
418 chk_fail_allowed = 1;
419 /* Runtime checks. */
420 if (__builtin_setjmp (chk_fail_buf) == 0)
422 memmove (&a.buf2[9], s2, l1 + 1);
423 abort ();
425 if (__builtin_setjmp (chk_fail_buf) == 0)
427 memmove (&a.buf2[7], s3, strlen (s3) + 1);
428 abort ();
430 /* This should be detectable at compile time already. */
431 if (__builtin_setjmp (chk_fail_buf) == 0)
433 memmove (&buf3[19], "ab", 2);
434 abort ();
436 chk_fail_allowed = 0;
439 #ifndef MAX_OFFSET
440 #define MAX_OFFSET (sizeof (long long))
441 #endif
443 #ifndef MAX_COPY
444 #define MAX_COPY (10 * sizeof (long long))
445 #endif
447 #ifndef MAX_EXTRA
448 #define MAX_EXTRA (sizeof (long long))
449 #endif
451 #define MAX_LENGTH (MAX_OFFSET + MAX_COPY + MAX_EXTRA)
453 /* Use a sequence length that is not divisible by two, to make it more
454 likely to detect when words are mixed up. */
455 #define SEQUENCE_LENGTH 31
457 static union {
458 char buf[MAX_LENGTH];
459 long long align_int;
460 long double align_fp;
461 } u1, u2;
463 void
464 __attribute__((noinline))
465 test6 (void)
467 int off1, off2, len, i;
468 char *p, *q, c;
470 for (off1 = 0; off1 < MAX_OFFSET; off1++)
471 for (off2 = 0; off2 < MAX_OFFSET; off2++)
472 for (len = 1; len < MAX_COPY; len++)
474 for (i = 0, c = 'A'; i < MAX_LENGTH; i++, c++)
476 u1.buf[i] = 'a';
477 if (c >= 'A' + SEQUENCE_LENGTH)
478 c = 'A';
479 u2.buf[i] = c;
482 p = memmove (u1.buf + off1, u2.buf + off2, len);
483 if (p != u1.buf + off1)
484 abort ();
486 q = u1.buf;
487 for (i = 0; i < off1; i++, q++)
488 if (*q != 'a')
489 abort ();
491 for (i = 0, c = 'A' + off2; i < len; i++, q++, c++)
493 if (c >= 'A' + SEQUENCE_LENGTH)
494 c = 'A';
495 if (*q != c)
496 abort ();
499 for (i = 0; i < MAX_EXTRA; i++, q++)
500 if (*q != 'a')
501 abort ();
505 #define TESTSIZE 80
507 char srcb[TESTSIZE] __attribute__ ((aligned));
508 char dstb[TESTSIZE] __attribute__ ((aligned));
510 void
511 __attribute__((noinline))
512 check (char *test, char *match, int n)
514 if (memcmp (test, match, n))
515 abort ();
518 #define TN(n) \
519 { memset (dstb, 0, n); memmove (dstb, srcb, n); check (dstb, srcb, n); }
520 #define T(n) \
521 TN (n) \
522 TN ((n) + 1) \
523 TN ((n) + 2) \
524 TN ((n) + 3)
526 void
527 __attribute__((noinline))
528 test7 (void)
530 int i;
532 chk_calls = 0;
534 for (i = 0; i < sizeof (srcb); ++i)
535 srcb[i] = 'a' + i % 26;
537 T (0);
538 T (4);
539 T (8);
540 T (12);
541 T (16);
542 T (20);
543 T (24);
544 T (28);
545 T (32);
546 T (36);
547 T (40);
548 T (44);
549 T (48);
550 T (52);
551 T (56);
552 T (60);
553 T (64);
554 T (68);
555 T (72);
556 T (76);
558 /* All memmove calls in this routine have constant arguments. */
559 if (chk_calls)
560 abort ();
563 void
564 main_test (void)
566 #ifndef __OPTIMIZE__
567 /* Object size checking is only intended for -O[s123]. */
568 return;
569 #endif
570 __asm ("" : "=r" (l1) : "0" (l1));
571 test1 ();
572 test2 ();
573 __builtin_memset (p, '\0', sizeof (p));
574 test3 ();
575 test4 ();
576 test5 ();
577 test6 ();
578 test7 ();