1 /* Copyright (C) 2004, 2005, 2011 Free Software Foundation.
3 Ensure builtin __stpncpy_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 *stpncpy (char *, const char *, size_t);
10 extern int memcmp (const void *, const void *, size_t);
11 extern int strcmp (const char *, const char *);
12 extern int strncmp (const char *, const char *, size_t);
13 extern void *memset (void *, int, size_t);
17 const char s1
[] = "123";
19 char * volatile s2
= "defg"; /* prevent constant propagation to happen when whole program assumptions are made. */
20 char * volatile s3
= "FGH"; /* prevent constant propagation to happen when whole program assumptions are made. */
22 volatile size_t l1
= 1; /* prevent constant propagation to happen when whole program assumptions are made. */
26 __attribute__((noinline
))
29 const char *const src
= "hello world";
35 memset (dst
, 0, sizeof (dst
));
36 if (stpncpy (dst
, src
, 4) != dst
+4 || strncmp (dst
, src
, 4))
39 memset (dst
, 0, sizeof (dst
));
40 if (stpncpy (dst
+16, src
, 4) != dst
+20 || strncmp (dst
+16, src
, 4))
43 memset (dst
, 0, sizeof (dst
));
44 if (stpncpy (dst
+32, src
+5, 4) != dst
+36 || strncmp (dst
+32, src
+5, 4))
47 memset (dst
, 0, sizeof (dst
));
49 if (stpncpy (++dst2
, src
+5, 4) != dst
+5 || strncmp (dst2
, src
+5, 4)
53 memset (dst
, 0, sizeof (dst
));
54 if (stpncpy (dst
, src
, 0) != dst
|| strcmp (dst
, ""))
57 memset (dst
, 0, sizeof (dst
));
58 dst2
= dst
; src2
= src
;
59 if (stpncpy (++dst2
, ++src2
, 0) != dst
+1 || strcmp (dst2
, "")
60 || dst2
!= dst
+1 || src2
!= src
+1)
63 memset (dst
, 0, sizeof (dst
));
64 dst2
= dst
; src2
= src
;
65 if (stpncpy (++dst2
+5, ++src2
+5, 0) != dst
+6 || strcmp (dst2
+5, "")
66 || dst2
!= dst
+1 || src2
!= src
+1)
69 memset (dst
, 0, sizeof (dst
));
70 if (stpncpy (dst
, src
, 12) != dst
+11 || strcmp (dst
, src
))
73 /* Test at least one instance of the __builtin_ style. We do this
74 to ensure that it works and that the prototype is correct. */
75 memset (dst
, 0, sizeof (dst
));
76 if (__builtin_stpncpy (dst
, src
, 4) != dst
+4 || strncmp (dst
, src
, 4))
79 memset (dst
, 0, sizeof (dst
));
80 if (stpncpy (dst
, i
++ ? "xfoo" + 1 : "bar", 4) != dst
+3
81 || strcmp (dst
, "bar")
85 /* If return value of stpncpy is ignored, it should be optimized into
87 stpncpy_disallowed
= 1;
88 stpncpy (dst
+ 1, src
, 4);
89 stpncpy_disallowed
= 0;
90 if (strncmp (dst
+ 1, src
, 4))
98 __attribute__((noinline
))
103 /* No runtime checking should be done here, both destination
104 and length are unknown. */
105 size_t cpy_length
= l1
< 4 ? l1
+ 1 : 4;
106 if (stpncpy (s4
, "abcd", l1
+ 1) != s4
+ cpy_length
|| strncmp (s4
, "abcd", cpy_length
))
113 /* Test whether compile time checking is done where it should
114 and so is runtime object size checking. */
116 __attribute__((noinline
))
119 struct A
{ char buf1
[10]; char buf2
[10]; } a
;
120 char *r
= l1
== 1 ? &a
.buf1
[5] : &a
.buf2
[4];
126 /* The following calls should do runtime checking
127 - source length is not known, but destination is.
128 The returned value is checked so that stpncpy calls
129 are not rewritten to strncpy calls. */
131 if (!stpncpy (a
.buf1
+ 2, s3
+ 3, l1
))
133 if (!stpncpy (r
, s3
+ 2, l1
+ 2))
135 r
= l1
== 1 ? __builtin_alloca (4) : &a
.buf2
[7];
136 if (!stpncpy (r
, s2
+ 2, l1
+ 2))
138 if (!stpncpy (r
+ 2, s3
+ 3, l1
))
141 for (i
= 0; i
< 4; ++i
)
147 else if (i
== l1
+ 1)
149 else if (i
== l1
+ 2)
152 if (!stpncpy (r
, s2
+ 4, l1
))
157 /* Following have known destination and known length,
158 so if optimizing certainly shouldn't result in the checking
161 if (!stpncpy (a
.buf1
+ 2, "", 3))
163 if (!stpncpy (a
.buf1
+ 2, "", 0))
165 if (!stpncpy (r
, "a", 1))
167 if (!stpncpy (r
, "a", 3))
169 r
= l1
== 1 ? __builtin_alloca (4) : &a
.buf2
[7];
170 if (!stpncpy (r
, s1
+ 1, 3))
172 if (!stpncpy (r
, s1
+ 1, 2))
177 for (i
= 0; i
< 4; ++i
)
180 r
= &a
.buf1
[1], l
= "e", l2
= 2;
182 r
= &a
.buf2
[7], l
= "gh", l2
= 3;
183 else if (i
== l1
+ 1)
184 r
= &buf3
[5], l
= "jkl", l2
= 4;
185 else if (i
== l1
+ 2)
186 r
= &a
.buf1
[9], l
= "", l2
= 1;
188 if (!stpncpy (r
, "", 1))
190 /* Here, strlen (l) + 1 is known to be at most 4 and
191 __builtin_object_size (&buf3[16], 0) is 4, so this doesn't need
193 if (!stpncpy (&buf3
[16], l
, l2
))
195 if (!stpncpy (&buf3
[15], "abc", l2
))
197 if (!stpncpy (&buf3
[10], "fghij", l2
))
204 /* Test whether runtime and/or compile time checking catches
207 __attribute__((noinline
))
210 struct A
{ char buf1
[10]; char buf2
[10]; } a
;
213 chk_fail_allowed
= 1;
214 /* Runtime checks. */
215 if (__builtin_setjmp (chk_fail_buf
) == 0)
217 if (stpncpy (&a
.buf2
[9], s2
+ 4, l1
+ 1))
218 // returned value used to prevent stpncpy calls
219 // to be rewritten in strncpy calls
223 if (__builtin_setjmp (chk_fail_buf
) == 0)
225 if (stpncpy (&a
.buf2
[7], s3
, l1
+ 4))
229 /* This should be detectable at compile time already. */
230 if (__builtin_setjmp (chk_fail_buf
) == 0)
232 if (stpncpy (&buf3
[19], "abc", 2))
236 if (__builtin_setjmp (chk_fail_buf
) == 0)
238 if (stpncpy (&buf3
[18], "", 3))
242 chk_fail_allowed
= 0;
249 /* Object size checking is only intended for -O[s123]. */
252 __asm ("" : "=r" (s2
) : "0" (s2
));
253 __asm ("" : "=r" (s3
) : "0" (s3
));
254 __asm ("" : "=r" (l1
) : "0" (l1
));