1 /* Copyright (C) 2004, 2005 Free Software Foundation.
3 Ensure builtin __strncat_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 char *strncat (char *, const char *, size_t);
11 extern int memcmp (const void *, const void *, size_t);
12 extern char *strcpy (char *, const char *);
13 extern int strcmp (const char *, const char *);
14 extern void *memset (void *, int, size_t);
18 const char s1
[] = "123";
28 __attribute__((noinline
))
31 const char *const s1
= "hello world";
32 const char *const s2
= "";
36 /* Following strncat calls should be all optimized out. */
38 strncat_disallowed
= 1;
39 strcat_disallowed
= 1;
41 if (strncat (dst
, "", 100) != dst
|| strcmp (dst
, s1
))
44 if (strncat (dst
, s2
, 100) != dst
|| strcmp (dst
, s1
))
46 strcpy (dst
, s1
); d2
= dst
;
47 if (strncat (++d2
, s2
, 100) != dst
+1 || d2
!= dst
+1 || strcmp (dst
, s1
))
49 strcpy (dst
, s1
); d2
= dst
;
50 if (strncat (++d2
+5, s2
, 100) != dst
+6 || d2
!= dst
+1 || strcmp (dst
, s1
))
52 strcpy (dst
, s1
); d2
= dst
;
53 if (strncat (++d2
+5, s1
+11, 100) != dst
+6 || d2
!= dst
+1 || strcmp (dst
, s1
))
55 strcpy (dst
, s1
); d2
= dst
;
56 if (strncat (++d2
+5, s1
, 0) != dst
+6 || d2
!= dst
+1 || strcmp (dst
, s1
))
58 strcpy (dst
, s1
); d2
= dst
; s3
= s1
;
59 if (strncat (++d2
+5, ++s3
, 0) != dst
+6 || d2
!= dst
+1 || strcmp (dst
, s1
)
62 strcpy (dst
, s1
); d2
= dst
;
63 if (strncat (++d2
+5, "", ++x
) != dst
+6 || d2
!= dst
+1 || x
!= 124
68 strcat_disallowed
= 0;
70 /* These __strncat_chk calls should be optimized into __strcat_chk,
71 as strlen (src) <= len. */
73 if (strncat (dst
, "foo", 3) != dst
|| strcmp (dst
, "hello worldfoo"))
76 if (strncat (dst
, "foo", 100) != dst
|| strcmp (dst
, "hello worldfoo"))
79 if (strncat (dst
, s1
, 100) != dst
|| strcmp (dst
, "hello worldhello world"))
85 /* The following calls have side-effects in dest, so are not checked. */
86 strcpy (dst
, s1
); d2
= dst
;
87 if (__builtin___strncat_chk (++d2
, s1
, 100, os (++d2
)) != dst
+1
88 || d2
!= dst
+1 || strcmp (dst
, "hello worldhello world"))
90 strcpy (dst
, s1
); d2
= dst
;
91 if (__builtin___strncat_chk (++d2
+5, s1
, 100, os (++d2
+5)) != dst
+6
92 || d2
!= dst
+1 || strcmp (dst
, "hello worldhello world"))
94 strcpy (dst
, s1
); d2
= dst
;
95 if (__builtin___strncat_chk (++d2
+5, s1
+5, 100, os (++d2
+5)) != dst
+6
96 || d2
!= dst
+1 || strcmp (dst
, "hello world world"))
102 strcat_disallowed
= 1;
104 /* Test at least one instance of the __builtin_ style. We do this
105 to ensure that it works and that the prototype is correct. */
107 if (__builtin_strncat (dst
, "", 100) != dst
|| strcmp (dst
, s1
))
112 strncat_disallowed
= 0;
113 strcat_disallowed
= 0;
116 /* Test whether compile time checking is done where it should
117 and so is runtime object size checking. */
119 __attribute__((noinline
))
122 struct A
{ char buf1
[10]; char buf2
[10]; } a
;
123 char *r
= l1
== 1 ? &a
.buf1
[5] : &a
.buf2
[4];
127 /* The following calls should do runtime checking. */
128 memset (&a
, '\0', sizeof (a
));
130 __asm
__volatile ("" : : "r" (s5
) : "memory");
132 strncat (a
.buf1
+ 2, s3
+ 3, l1
- 1);
133 strncat (r
, s3
+ 2, l1
);
134 r
= l1
== 1 ? __builtin_alloca (4) : &a
.buf2
[7];
136 __asm
__volatile ("" : : "r" (r
) : "memory");
137 strncat (r
, s2
+ 2, l1
+ 1);
138 strncat (r
+ 2, s3
+ 3, l1
- 1);
140 for (i
= 0; i
< 4; ++i
)
146 else if (i
== l1
+ 1)
148 else if (i
== l1
+ 2)
151 strncat (r
, s2
+ 4, l1
);
155 /* Following have known destination and known source length,
156 but we don't know the length of dest string, so runtime checking
158 memset (&a
, '\0', sizeof (a
));
161 __asm
__volatile ("" : : "r" (s5
) : "memory");
162 strncat (a
.buf1
+ 2, "a", 5);
163 strncat (r
, "def", 0);
164 r
= l1
== 1 ? __builtin_alloca (4) : &a
.buf2
[7];
166 __asm
__volatile ("" : : "r" (r
) : "memory");
167 strncat (r
, s1
+ 1, 2);
171 strcat_disallowed
= 1;
172 /* Unknown destination and source, no checking. */
173 strncat (s4
, s3
, l1
+ 1);
174 strcat_disallowed
= 0;
179 /* Test whether runtime and/or compile time checking catches
182 __attribute__((noinline
))
185 struct A
{ char buf1
[10]; char buf2
[10]; } a
;
188 memset (&a
, '\0', sizeof (a
));
189 memset (buf3
, '\0', sizeof (buf3
));
191 __asm
__volatile ("" : : "r" (s5
) : "memory");
193 __asm
__volatile ("" : : "r" (s5
) : "memory");
194 chk_fail_allowed
= 1;
195 /* Runtime checks. */
196 if (__builtin_setjmp (chk_fail_buf
) == 0)
198 strncat (&a
.buf2
[9], s2
+ 3, 4);
201 if (__builtin_setjmp (chk_fail_buf
) == 0)
203 strncat (&a
.buf2
[7], s3
+ strlen (s3
) - 3, 3);
206 if (__builtin_setjmp (chk_fail_buf
) == 0)
208 strncat (&buf3
[19], "abcde", 1);
211 chk_fail_allowed
= 0;
218 /* Object size checking is only intended for -O[s123]. */
221 __asm ("" : "=r" (s2
) : "0" (s2
));
222 __asm ("" : "=r" (s3
) : "0" (s3
));
223 __asm ("" : "=r" (l1
) : "0" (l1
));
226 memset (p
, '\0', sizeof (p
));