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);
14 const char s1
[] = "123";
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. */
21 __attribute__((noinline
))
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;
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. */
38 if (memmove (p
, "ABCDE", 6) != p
|| memcmp (p
, "ABCDE", 6))
40 if (memmove (p
+ 16, "VWX" + 1, 2) != p
+ 16
41 || memcmp (p
+ 16, "WX\0\0", 5))
43 if (memmove (p
+ 1, "", 1) != p
+ 1 || memcmp (p
, "A\0CDE", 6))
45 if (memmove (p
+ 3, "FGHI", 4) != p
+ 3 || memcmp (p
, "A\0CFGHI", 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))
55 if (memmove (memmove (p
, "abcdEFG", 4) + 4, "efg", 4) != p
+ 4
56 || memcmp (p
, "abcdefg", 8))
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))
64 memmove (p
+ 5, s3
, 1);
65 if (memcmp (p
, "ABCDEFg", 8))
68 memmove_disallowed
= 0;
69 memcpy_disallowed
= 0;
74 memmove (p
+ 6, s1
+ 1, l1
);
75 if (memcmp (p
, "ABCDEF2", 8))
78 /* The above memmove copies into an object with known size, but
79 unknown length, so it should be a __memmove_chk call. */
85 char *buf2
= (char *) (buf1
+ 32);
90 __attribute__((noinline
))
91 test2_sub (long *buf3
, char *buf4
, char *buf6
, int n
)
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. */
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))
106 if (memmove (buf1
, "abcdefghijklmnopq", 17) != (char *) buf1
107 || memcmp (buf1
, "abcdefghijklmnopq\0", 19))
110 if (__builtin_memmove (buf3
, "ABCDEF", 6) != (char *) buf1
111 || memcmp (buf1
, "ABCDEFghijklmnopq\0", 19))
114 if (__builtin_memmove (buf3
, "a", 1) != (char *) buf1
115 || memcmp (buf1
, "aBCDEFghijklmnopq\0", 19))
118 if (memmove ((char *) buf3
+ 2, "bcd" + ++i
, 2) != (char *) buf1
+ 2
119 || memcmp (buf1
, "aBcdEFghijklmnopq\0", 19)
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))
128 if (__builtin_memmove ((char *) buf1
+ ++i
+ 8, (char *) buf5
+ 1, 1)
129 != (char *) buf1
+ 10
130 || memcmp (buf1
, "aBcdRSTUVWSlmnopq\0", 19)
134 if (memmove ((char *) buf3
+ 14, buf6
, 2) != (char *) buf1
+ 14
135 || memcmp (buf1
, "aBcdRSTUVWSlmnrsq\0", 19))
138 if (memmove (buf3
, buf5
, 8) != (char *) buf1
139 || memcmp (buf1
, "RSTUVWXYVWSlmnrsq\0", 19))
142 if (memmove (buf3
, buf5
, 17) != (char *) buf1
143 || memcmp (buf1
, "RSTUVWXYZ01234567\0", 19))
146 __builtin_memmove (buf3
, "aBcdEFghijklmnopq\0", 19);
148 /* These should be handled either by movmemendM or memmove
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))
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)
164 if (memmove ((char *) buf3
+ 14, buf6
, n
+ 2) != (char *) buf1
+ 14
165 || memcmp (buf1
, "aBcdRSTUVWkSmnrsq\0", 19))
170 /* These might be handled by store_by_pieces. */
171 if (memmove (buf2
, "ABCDEFGHI", 9) != buf2
172 || memcmp (buf2
, "ABCDEFGHI\0", 11))
175 if (memmove (buf2
, "abcdefghijklmnopq", 17) != buf2
176 || memcmp (buf2
, "abcdefghijklmnopq\0", 19))
179 if (__builtin_memmove (buf4
, "ABCDEF", 6) != buf2
180 || memcmp (buf2
, "ABCDEFghijklmnopq\0", 19))
183 if (__builtin_memmove (buf4
, "a", 1) != buf2
184 || memcmp (buf2
, "aBCDEFghijklmnopq\0", 19))
187 if (memmove (buf4
+ 2, "bcd" + i
++, 2) != buf2
+ 2
188 || memcmp (buf2
, "aBcdEFghijklmnopq\0", 19)
192 /* These might be handled by move_by_pieces. */
193 if (memmove (buf4
+ 4, buf7
, 6) != buf2
+ 4
194 || memcmp (buf2
, "aBcdRSTUVWklmnopq\0", 19))
198 if (__builtin___memmove_chk (buf2
+ i
++ + 8, buf7
+ 1, 1,
201 || memcmp (buf2
, "aBcdRSTUVWSlmnopq\0", 19)
205 if (memmove (buf4
+ 14, buf6
, 2) != buf2
+ 14
206 || memcmp (buf2
, "aBcdRSTUVWSlmnrsq\0", 19))
209 __builtin_memmove (buf4
, "aBcdEFghijklmnopq\0", 19);
211 /* These should be handled either by movmemendM or memmove
213 if (memmove (buf4
+ 4, buf7
, n
+ 6) != buf2
+ 4
214 || memcmp (buf2
, "aBcdRSTUVWklmnopq\0", 19))
218 if (__builtin___memmove_chk (buf2
+ i
++ + 8, buf7
+ 1, n
+ 1,
221 || memcmp (buf2
, "aBcdRSTUVWkSmnopq\0", 19)
225 if (memmove (buf4
+ 14, buf6
, n
+ 2) != buf2
+ 14
226 || memcmp (buf2
, "aBcdRSTUVWkSmnrsq\0", 19))
234 __attribute__((noinline
))
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
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
266 const struct foo f
[3];
272 { "hello1", 3.14159, 201L },
273 { "hello2", 3.14159, 202L },
274 { "hello3", 3.14159, 203L },
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 };
290 __attribute__((noinline
))
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
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
)))
307 if (memmove (b1
, bar
, sizeof (bar
)) != b1
|| memcmp (b1
, bar
, sizeof (bar
)))
309 memmove (bz
, baz
, sizeof (baz
));
310 if (memcmp (bz
, baz
, sizeof (baz
)))
313 if (memmove (p
, "abcde", 6) != p
|| memcmp (p
, "abcde", 6))
316 if (memmove (p
+ 2, ++s
, 0) != p
+ 2 || memcmp (p
, "abcde", 6) || s
!= s1
+ 1)
318 if (__builtin_memmove (p
+ 3, "", 1) != p
+ 3 || memcmp (p
, "abc\0e", 6))
320 memmove (p
+ 2, "fghijk", 4);
321 if (memcmp (p
, "abfghi", 7))
324 memmove (p
+ 1, s
++, 0);
325 if (memcmp (p
, "abfghi", 7) || s
!= s1
+ 2)
327 __builtin_memmove (p
+ 4, "ABCDE", 1);
328 if (memcmp (p
, "abfgAi", 7))
331 /* memmove with length 1 can be optimized into memcpy if it can be
333 if (memmove (p
+ 2, p
+ 3, 1) != p
+ 2)
335 if (memcmp (p
, "abggAi", 7))
340 memmove_disallowed
= 0;
343 /* Test whether compile time checking is done where it should
344 and so is runtime object size checking. */
346 __attribute__((noinline
))
349 struct A
{ char buf1
[10]; char buf2
[10]; } a
;
350 char *r
= l1
== 1 ? &a
.buf1
[5] : &a
.buf2
[4];
355 /* The following calls should do runtime checking
356 - length is not known, but destination is. */
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
);
364 for (i
= 0; i
< 4; ++i
)
370 else if (i
== l1
+ 1)
372 else if (i
== l1
+ 2)
379 /* Following have known destination and known length,
380 so if optimizing certainly shouldn't result in the checking
383 memmove (a
.buf1
+ 2, s3
, 1);
385 r
= l1
== 1 ? __builtin_alloca (4) : &a
.buf2
[7];
389 for (i
= 0; i
< 4; ++i
)
392 r
= &a
.buf1
[1], l
= 2;
394 r
= &a
.buf2
[7], l
= 3;
395 else if (i
== l1
+ 1)
397 else if (i
== l1
+ 2)
398 r
= &a
.buf1
[9], l
= 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
);
409 /* Test whether runtime and/or compile time checking catches
412 __attribute__((noinline
))
415 struct A
{ char buf1
[10]; char buf2
[10]; } a
;
418 chk_fail_allowed
= 1;
419 /* Runtime checks. */
420 if (__builtin_setjmp (chk_fail_buf
) == 0)
422 memmove (&a
.buf2
[9], s2
, l1
+ 1);
425 if (__builtin_setjmp (chk_fail_buf
) == 0)
427 memmove (&a
.buf2
[7], s3
, strlen (s3
) + 1);
430 /* This should be detectable at compile time already. */
431 if (__builtin_setjmp (chk_fail_buf
) == 0)
433 memmove (&buf3
[19], "ab", 2);
436 chk_fail_allowed
= 0;
440 #define MAX_OFFSET (sizeof (long long))
444 #define MAX_COPY (10 * sizeof (long long))
448 #define MAX_EXTRA (sizeof (long long))
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
458 char buf
[MAX_LENGTH
];
460 long double align_fp
;
464 __attribute__((noinline
))
467 int off1
, off2
, len
, i
;
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
++)
477 if (c
>= 'A' + SEQUENCE_LENGTH
)
482 p
= memmove (u1
.buf
+ off1
, u2
.buf
+ off2
, len
);
483 if (p
!= u1
.buf
+ off1
)
487 for (i
= 0; i
< off1
; i
++, q
++)
491 for (i
= 0, c
= 'A' + off2
; i
< len
; i
++, q
++, c
++)
493 if (c
>= 'A' + SEQUENCE_LENGTH
)
499 for (i
= 0; i
< MAX_EXTRA
; i
++, q
++)
507 char srcb
[TESTSIZE
] __attribute__ ((aligned
));
508 char dstb
[TESTSIZE
] __attribute__ ((aligned
));
511 __attribute__((noinline
))
512 check (char *test
, char *match
, int n
)
514 if (memcmp (test
, match
, n
))
519 { memset (dstb, 0, n); memmove (dstb, srcb, n); check (dstb, srcb, n); }
527 __attribute__((noinline
))
534 for (i
= 0; i
< sizeof (srcb
); ++i
)
535 srcb
[i
] = 'a' + i
% 26;
558 /* All memmove calls in this routine have constant arguments. */
567 /* Object size checking is only intended for -O[s123]. */
570 __asm ("" : "=r" (l1
) : "0" (l1
));
573 __builtin_memset (p
, '\0', sizeof (p
));