OSDN Git Service

Merge branch 'trunk' of git://gcc.gnu.org/git/gcc into rework
[pf3gnuchains/gcc-fork.git] / gcc / testsuite / gcc.c-torture / execute / builtins / strncpy-chk.c
1 /* Copyright (C) 2004, 2005  Free Software Foundation.
2
3    Ensure builtin __strncpy_chk performs correctly.  */
4
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 *strncpy (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);
14
15 #include "chk.h"
16
17 const char s1[] = "123";
18 char p[32] = "";
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.  */
21 char *s4;
22 volatile size_t l1 = 1;  /* prevent constant propagation to happen when whole program assumptions are made.  */
23 int i;
24
25 void
26 __attribute__((noinline))
27 test1 (void)
28 {
29   const char *const src = "hello world";
30   const char *src2;
31   char dst[64], *dst2;
32
33   strncpy_disallowed = 1;
34   chk_calls = 0;
35
36   memset (dst, 0, sizeof (dst));
37   if (strncpy (dst, src, 4) != dst || strncmp (dst, src, 4))
38     abort();
39
40   memset (dst, 0, sizeof (dst));
41   if (strncpy (dst+16, src, 4) != dst+16 || strncmp (dst+16, src, 4))
42     abort();
43
44   memset (dst, 0, sizeof (dst));
45   if (strncpy (dst+32, src+5, 4) != dst+32 || strncmp (dst+32, src+5, 4))
46     abort();
47
48   memset (dst, 0, sizeof (dst));
49   dst2 = dst;
50   if (strncpy (++dst2, src+5, 4) != dst+1 || strncmp (dst2, src+5, 4)
51       || dst2 != dst+1)
52     abort();
53
54   memset (dst, 0, sizeof (dst));
55   if (strncpy (dst, src, 0) != dst || strcmp (dst, ""))
56     abort();
57   
58   memset (dst, 0, sizeof (dst));
59   dst2 = dst; src2 = src;
60   if (strncpy (++dst2, ++src2, 0) != dst+1 || strcmp (dst2, "")
61       || dst2 != dst+1 || src2 != src+1)
62     abort();
63
64   memset (dst, 0, sizeof (dst));
65   dst2 = dst; src2 = src;
66   if (strncpy (++dst2+5, ++src2+5, 0) != dst+6 || strcmp (dst2+5, "")
67       || dst2 != dst+1 || src2 != src+1)
68     abort();
69
70   memset (dst, 0, sizeof (dst));
71   if (strncpy (dst, src, 12) != dst || strcmp (dst, src))
72     abort();
73
74   /* Test at least one instance of the __builtin_ style.  We do this
75      to ensure that it works and that the prototype is correct.  */
76   memset (dst, 0, sizeof (dst));
77   if (__builtin_strncpy (dst, src, 4) != dst || strncmp (dst, src, 4))
78     abort();
79
80   memset (dst, 0, sizeof (dst));
81   if (strncpy (dst, i++ ? "xfoo" + 1 : "bar", 4) != dst
82       || strcmp (dst, "bar")
83       || i != 1)
84     abort ();
85
86   if (chk_calls)
87     abort ();
88   strncpy_disallowed = 0;
89 }
90
91 void
92 __attribute__((noinline))
93 test2 (void)
94 {
95   chk_calls = 0;
96   /* No runtime checking should be done here, both destination
97      and length are unknown.  */
98   strncpy (s4, "abcd", l1 + 1);
99   if (chk_calls)
100     abort ();
101 }
102
103 /* Test whether compile time checking is done where it should
104    and so is runtime object size checking.  */
105 void
106 __attribute__((noinline))
107 test3 (void)
108 {
109   struct A { char buf1[10]; char buf2[10]; } a;
110   char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
111   char buf3[20];
112   int i;
113   const char *l;
114   size_t l2;
115
116   /* The following calls should do runtime checking
117      - source length is not known, but destination is.  */
118   chk_calls = 0;
119   strncpy (a.buf1 + 2, s3 + 3, l1);
120   strncpy (r, s3 + 2, l1 + 2);
121   r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
122   strncpy (r, s2 + 2, l1 + 2);
123   strncpy (r + 2, s3 + 3, l1);
124   r = buf3;
125   for (i = 0; i < 4; ++i)
126     {
127       if (i == l1 - 1)
128         r = &a.buf1[1];
129       else if (i == l1)
130         r = &a.buf2[7];
131       else if (i == l1 + 1)
132         r = &buf3[5];
133       else if (i == l1 + 2)
134         r = &a.buf1[9];
135     }
136   strncpy (r, s2 + 4, l1);
137   if (chk_calls != 5)
138     abort ();
139
140   /* Following have known destination and known length,
141      so if optimizing certainly shouldn't result in the checking
142      variants.  */
143   chk_calls = 0;
144   strncpy (a.buf1 + 2, "", 3);
145   strncpy (a.buf1 + 2, "", 0);
146   strncpy (r, "a", 1);
147   strncpy (r, "a", 3);
148   r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
149   strncpy (r, s1 + 1, 3);
150   strncpy (r, s1 + 1, 2);
151   r = buf3;
152   l = "abc";
153   l2 = 4;
154   for (i = 0; i < 4; ++i)
155     {
156       if (i == l1 - 1)
157         r = &a.buf1[1], l = "e", l2 = 2;
158       else if (i == l1)
159         r = &a.buf2[7], l = "gh", l2 = 3;
160       else if (i == l1 + 1)
161         r = &buf3[5], l = "jkl", l2 = 4;
162       else if (i == l1 + 2)
163         r = &a.buf1[9], l = "", l2 = 1;
164     }
165   strncpy (r, "", 1);
166   /* Here, strlen (l) + 1 is known to be at most 4 and
167      __builtin_object_size (&buf3[16], 0) is 4, so this doesn't need
168      runtime checking.  */
169   strncpy (&buf3[16], l, l2);
170   strncpy (&buf3[15], "abc", l2);
171   strncpy (&buf3[10], "fghij", l2);
172   if (chk_calls)
173     abort ();
174   chk_calls = 0;
175 }
176
177 /* Test whether runtime and/or compile time checking catches
178    buffer overflows.  */
179 void
180 __attribute__((noinline))
181 test4 (void)
182 {
183   struct A { char buf1[10]; char buf2[10]; } a;
184   char buf3[20];
185
186   chk_fail_allowed = 1;
187   /* Runtime checks.  */
188   if (__builtin_setjmp (chk_fail_buf) == 0)
189     {
190       strncpy (&a.buf2[9], s2 + 4, l1 + 1);
191       abort ();
192     }
193   if (__builtin_setjmp (chk_fail_buf) == 0)
194     {
195       strncpy (&a.buf2[7], s3, l1 + 4);
196       abort ();
197     }
198   /* This should be detectable at compile time already.  */
199   if (__builtin_setjmp (chk_fail_buf) == 0)
200     {
201       strncpy (&buf3[19], "abc", 2);
202       abort ();
203     }
204   if (__builtin_setjmp (chk_fail_buf) == 0)
205     {
206       strncpy (&buf3[18], "", 3);
207       abort ();
208     }
209   chk_fail_allowed = 0;
210 }
211
212 void
213 main_test (void)
214 {
215 #ifndef __OPTIMIZE__
216   /* Object size checking is only intended for -O[s123].  */
217   return;
218 #endif
219   __asm ("" : "=r" (s2) : "0" (s2));
220   __asm ("" : "=r" (s3) : "0" (s3));
221   __asm ("" : "=r" (l1) : "0" (l1));
222   test1 ();
223   s4 = p;
224   test2 ();
225   test3 ();
226   test4 ();
227 }