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);
13 const char s1
[] = "123";
20 __attribute__((noinline
))
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;
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. */
36 if (memcpy (p
, "ABCDE", 6) != p
|| memcmp (p
, "ABCDE", 6))
38 if (memcpy (p
+ 16, "VWX" + 1, 2) != p
+ 16
39 || memcmp (p
+ 16, "WX\0\0", 5))
41 if (memcpy (p
+ 1, "", 1) != p
+ 1 || memcmp (p
, "A\0CDE", 6))
43 if (memcpy (p
+ 3, "FGHI", 4) != p
+ 3 || memcmp (p
, "A\0CFGHI", 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))
53 if (memcpy (memcpy (p
, "abcdEFG", 4) + 4, "efg", 4) != p
+ 4
54 || memcmp (p
, "abcdefg", 8))
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))
62 memcpy (p
+ 5, s3
, 1);
63 if (memcmp (p
, "ABCDEFg", 8))
66 memcpy_disallowed
= 0;
71 memcpy (p
+ 6, s1
+ 1, l1
);
72 if (memcmp (p
, "ABCDEF2", 8))
75 /* The above memcpy copies into an object with known size, but
76 unknown length, so it should be a __memcpy_chk call. */
82 char *buf2
= (char *) (buf1
+ 32);
87 __attribute__((noinline
))
88 test2_sub (long *buf3
, char *buf4
, char *buf6
, int n
)
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. */
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))
103 if (memcpy (buf1
, "abcdefghijklmnopq", 17) != (char *) buf1
104 || memcmp (buf1
, "abcdefghijklmnopq\0", 19))
107 if (__builtin_memcpy (buf3
, "ABCDEF", 6) != (char *) buf1
108 || memcmp (buf1
, "ABCDEFghijklmnopq\0", 19))
111 if (__builtin_memcpy (buf3
, "a", 1) != (char *) buf1
112 || memcmp (buf1
, "aBCDEFghijklmnopq\0", 19))
115 if (memcpy ((char *) buf3
+ 2, "bcd" + ++i
, 2) != (char *) buf1
+ 2
116 || memcmp (buf1
, "aBcdEFghijklmnopq\0", 19)
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))
125 if (__builtin_memcpy ((char *) buf1
+ ++i
+ 8, (char *) buf5
+ 1, 1)
126 != (char *) buf1
+ 10
127 || memcmp (buf1
, "aBcdRSTUVWSlmnopq\0", 19)
131 if (memcpy ((char *) buf3
+ 14, buf6
, 2) != (char *) buf1
+ 14
132 || memcmp (buf1
, "aBcdRSTUVWSlmnrsq\0", 19))
135 if (memcpy (buf3
, buf5
, 8) != (char *) buf1
136 || memcmp (buf1
, "RSTUVWXYVWSlmnrsq\0", 19))
139 if (memcpy (buf3
, buf5
, 17) != (char *) buf1
140 || memcmp (buf1
, "RSTUVWXYZ01234567\0", 19))
143 __builtin_memcpy (buf3
, "aBcdEFghijklmnopq\0", 19);
145 /* These should be handled either by movmemendM or memcpy
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))
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)
161 if (memcpy ((char *) buf3
+ 14, buf6
, n
+ 2) != (char *) buf1
+ 14
162 || memcmp (buf1
, "aBcdRSTUVWkSmnrsq\0", 19))
167 /* These might be handled by store_by_pieces. */
168 if (memcpy (buf2
, "ABCDEFGHI", 9) != buf2
169 || memcmp (buf2
, "ABCDEFGHI\0", 11))
172 if (memcpy (buf2
, "abcdefghijklmnopq", 17) != buf2
173 || memcmp (buf2
, "abcdefghijklmnopq\0", 19))
176 if (__builtin_memcpy (buf4
, "ABCDEF", 6) != buf2
177 || memcmp (buf2
, "ABCDEFghijklmnopq\0", 19))
180 if (__builtin_memcpy (buf4
, "a", 1) != buf2
181 || memcmp (buf2
, "aBCDEFghijklmnopq\0", 19))
184 if (memcpy (buf4
+ 2, "bcd" + i
++, 2) != buf2
+ 2
185 || memcmp (buf2
, "aBcdEFghijklmnopq\0", 19)
189 /* These might be handled by move_by_pieces. */
190 if (memcpy (buf4
+ 4, buf7
, 6) != buf2
+ 4
191 || memcmp (buf2
, "aBcdRSTUVWklmnopq\0", 19))
195 if (__builtin___memcpy_chk (buf2
+ i
++ + 8, buf7
+ 1, 1,
198 || memcmp (buf2
, "aBcdRSTUVWSlmnopq\0", 19)
202 if (memcpy (buf4
+ 14, buf6
, 2) != buf2
+ 14
203 || memcmp (buf2
, "aBcdRSTUVWSlmnrsq\0", 19))
206 __builtin_memcpy (buf4
, "aBcdEFghijklmnopq\0", 19);
208 /* These should be handled either by movmemendM or memcpy
210 if (memcpy (buf4
+ 4, buf7
, n
+ 6) != buf2
+ 4
211 || memcmp (buf2
, "aBcdRSTUVWklmnopq\0", 19))
215 if (__builtin___memcpy_chk (buf2
+ i
++ + 8, buf7
+ 1, n
+ 1,
218 || memcmp (buf2
, "aBcdRSTUVWkSmnopq\0", 19)
222 if (memcpy (buf4
+ 14, buf6
, n
+ 2) != buf2
+ 14
223 || memcmp (buf2
, "aBcdRSTUVWkSmnrsq\0", 19))
231 __attribute__((noinline
))
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. */
248 __attribute__((noinline
))
251 struct A
{ char buf1
[10]; char buf2
[10]; } a
;
252 char *r
= l1
== 1 ? &a
.buf1
[5] : &a
.buf2
[4];
257 /* The following calls should do runtime checking
258 - length is not known, but destination is. */
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
);
266 for (i
= 0; i
< 4; ++i
)
272 else if (i
== l1
+ 1)
274 else if (i
== l1
+ 2)
281 /* Following have known destination and known length,
282 so if optimizing certainly shouldn't result in the checking
285 memcpy (a
.buf1
+ 2, s3
, 1);
287 r
= l1
== 1 ? __builtin_alloca (4) : &a
.buf2
[7];
291 for (i
= 0; i
< 4; ++i
)
294 r
= &a
.buf1
[1], l
= 2;
296 r
= &a
.buf2
[7], l
= 3;
297 else if (i
== l1
+ 1)
299 else if (i
== l1
+ 2)
300 r
= &a
.buf1
[9], l
= 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
);
311 /* Test whether runtime and/or compile time checking catches
314 __attribute__((noinline
))
317 struct A
{ char buf1
[10]; char buf2
[10]; } a
;
320 chk_fail_allowed
= 1;
321 /* Runtime checks. */
322 if (__builtin_setjmp (chk_fail_buf
) == 0)
324 memcpy (&a
.buf2
[9], s2
, l1
+ 1);
327 if (__builtin_setjmp (chk_fail_buf
) == 0)
329 memcpy (&a
.buf2
[7], s3
, strlen (s3
) + 1);
332 /* This should be detectable at compile time already. */
333 if (__builtin_setjmp (chk_fail_buf
) == 0)
335 memcpy (&buf3
[19], "ab", 2);
338 chk_fail_allowed
= 0;
342 #define MAX_OFFSET (sizeof (long long))
346 #define MAX_COPY (10 * sizeof (long long))
350 #define MAX_EXTRA (sizeof (long long))
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
360 char buf
[MAX_LENGTH
];
362 long double align_fp
;
366 __attribute__((noinline
))
369 int off1
, off2
, len
, i
;
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
++)
379 if (c
>= 'A' + SEQUENCE_LENGTH
)
384 p
= memcpy (u1
.buf
+ off1
, u2
.buf
+ off2
, len
);
385 if (p
!= u1
.buf
+ off1
)
389 for (i
= 0; i
< off1
; i
++, q
++)
393 for (i
= 0, c
= 'A' + off2
; i
< len
; i
++, q
++, c
++)
395 if (c
>= 'A' + SEQUENCE_LENGTH
)
401 for (i
= 0; i
< MAX_EXTRA
; i
++, q
++)
409 char srcb
[TESTSIZE
] __attribute__ ((aligned
));
410 char dstb
[TESTSIZE
] __attribute__ ((aligned
));
413 __attribute__((noinline
))
414 check (char *test
, char *match
, int n
)
416 if (memcmp (test
, match
, n
))
421 { memset (dstb, 0, n); memcpy (dstb, srcb, n); check (dstb, srcb, n); }
429 __attribute__((noinline
))
436 for (i
= 0; i
< sizeof (srcb
); ++i
)
437 srcb
[i
] = 'a' + i
% 26;
460 /* All memcpy calls in this routine have constant arguments. */
469 /* Object size checking is only intended for -O[s123]. */
472 __asm ("" : "=r" (l1
) : "0" (l1
));