1 /* Copyright (C) 2004, 2005 Free Software Foundation.
3 Ensure builtin __strcat_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 *strcat (char *, const char *);
10 extern int memcmp (const void *, const void *, size_t);
11 extern char *strcpy (char *, const char *);
12 extern int strcmp (const char *, const char *);
13 extern void *memset (void *, int, size_t);
14 #define RESET_DST_WITH(FILLER) \
15 do { memset (dst, 'X', sizeof (dst)); strcpy (dst, (FILLER)); } while (0)
19 const char s1
[] = "123";
28 __attribute__((noinline
))
31 const char *const x1
= "hello world";
32 const char *const x2
= "";
36 strcat_disallowed
= 1;
37 /* Following strcat calls should be optimized out at compile time. */
39 if (strcat (dst
, "") != dst
|| strcmp (dst
, x1
))
42 if (strcat (dst
, x2
) != dst
|| strcmp (dst
, x1
))
44 RESET_DST_WITH (x1
); d2
= dst
;
45 if (strcat (++d2
, x2
) != dst
+1 || d2
!= dst
+1 || strcmp (dst
, x1
))
47 RESET_DST_WITH (x1
); d2
= dst
;
48 if (strcat (++d2
+5, x2
) != dst
+6 || d2
!= dst
+1 || strcmp (dst
, x1
))
50 RESET_DST_WITH (x1
); d2
= dst
;
51 if (strcat (++d2
+5, x1
+11) != dst
+6 || d2
!= dst
+1 || strcmp (dst
, x1
))
55 strcat_disallowed
= 0;
58 if (strcat (dst
, " 1111") != dst
59 || memcmp (dst
, "hello world 1111\0XXX", 20))
63 if (strcat (dst
+5, " 2222") != dst
+5
64 || memcmp (dst
, "hello world 2222\0XXX", 20))
67 RESET_DST_WITH (x1
); d2
= dst
;
68 if (strcat (++d2
+5, " 3333") != dst
+6 || d2
!= dst
+1
69 || memcmp (dst
, "hello world 3333\0XXX", 20))
73 strcat (strcat (strcat (strcat (strcat (strcat (dst
, ": this "), ""),
74 "is "), "a "), "test"), ".");
75 if (memcmp (dst
, "hello world: this is a test.\0X", 30))
79 strcat_disallowed
= 1;
80 /* Test at least one instance of the __builtin_ style. We do this
81 to ensure that it works and that the prototype is correct. */
83 if (__builtin_strcat (dst
, "") != dst
|| strcmp (dst
, x1
))
87 strcat_disallowed
= 0;
91 /* Test whether compile time checking is done where it should
92 and so is runtime object size checking. */
94 __attribute__((noinline
))
97 struct A
{ char buf1
[10]; char buf2
[10]; } a
;
98 char *r
= l1
== 1 ? &a
.buf1
[5] : &a
.buf2
[4];
102 /* The following calls should do runtime checking
103 - source length is not known, but destination is. */
104 memset (&a
, '\0', sizeof (a
));
106 __asm
__volatile ("" : : "r" (s5
) : "memory");
108 strcat (a
.buf1
+ 2, s3
+ 3);
110 r
= l1
== 1 ? __builtin_alloca (4) : &a
.buf2
[7];
112 __asm
__volatile ("" : : "r" (r
) : "memory");
114 strcat (r
+ 2, s3
+ 3);
116 for (i
= 0; i
< 4; ++i
)
122 else if (i
== l1
+ 1)
124 else if (i
== l1
+ 2)
131 /* Following have known destination and known source length,
132 but we don't know the length of dest string, so runtime checking
134 memset (&a
, '\0', sizeof (a
));
137 __asm
__volatile ("" : : "r" (s5
) : "memory");
138 strcat (a
.buf1
+ 2, "a");
140 r
= l1
== 1 ? __builtin_alloca (4) : &a
.buf2
[7];
142 __asm
__volatile ("" : : "r" (r
) : "memory");
147 /* Unknown destination and source, no checking. */
154 /* Test whether runtime and/or compile time checking catches
157 __attribute__((noinline
))
160 struct A
{ char buf1
[10]; char buf2
[10]; } a
;
163 memset (&a
, '\0', sizeof (a
));
164 memset (buf3
, '\0', sizeof (buf3
));
166 __asm
__volatile ("" : : "r" (s5
) : "memory");
168 __asm
__volatile ("" : : "r" (s5
) : "memory");
169 chk_fail_allowed
= 1;
170 /* Runtime checks. */
171 if (__builtin_setjmp (chk_fail_buf
) == 0)
173 strcat (&a
.buf2
[9], s2
+ 3);
176 if (__builtin_setjmp (chk_fail_buf
) == 0)
178 strcat (&a
.buf2
[7], s3
+ strlen (s3
) - 3);
181 if (__builtin_setjmp (chk_fail_buf
) == 0)
183 strcat (&buf3
[19], "a");
186 chk_fail_allowed
= 0;
193 /* Object size checking is only intended for -O[s123]. */
196 __asm ("" : "=r" (s2
) : "0" (s2
));
197 __asm ("" : "=r" (s3
) : "0" (s3
));
198 __asm ("" : "=r" (l1
) : "0" (l1
));
201 memset (p
, '\0', sizeof (p
));