]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-chk.c
* builtin-attrs.def (DEF_ATTR_FOR_INT): Add for 5 and 6.
[thirdparty/gcc.git] / gcc / testsuite / gcc.c-torture / execute / builtins / strcpy-chk.c
1 /* Copyright (C) 2004, 2005 Free Software Foundation.
2
3 Ensure builtin __strcpy_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 *strcpy (char *, const char *);
10 extern int memcmp (const void *, const void *, size_t);
11
12 #include "chk.h"
13
14 const char s1[] = "123";
15 char p[32] = "";
16 char *s2 = "defg";
17 char *s3 = "FGH";
18 char *s4;
19 size_t l1 = 1;
20
21 void
22 __attribute__((noinline))
23 test1 (void)
24 {
25 chk_calls = 0;
26 #ifndef __OPTIMIZE_SIZE__
27 strcpy_disallowed = 1;
28 #else
29 strcpy_disallowed = 0;
30 #endif
31
32 if (strcpy (p, "abcde") != p || memcmp (p, "abcde", 6))
33 abort ();
34 if (strcpy (p + 16, "vwxyz" + 1) != p + 16 || memcmp (p + 16, "wxyz", 5))
35 abort ();
36 if (strcpy (p + 1, "") != p + 1 || memcmp (p, "a\0cde", 6))
37 abort ();
38 if (strcpy (p + 3, "fghij") != p + 3 || memcmp (p, "a\0cfghij", 9))
39 abort ();
40
41 /* Test at least one instance of the __builtin_ style. We do this
42 to ensure that it works and that the prototype is correct. */
43 if (__builtin_strcpy (p, "abcde") != p || memcmp (p, "abcde", 6))
44 abort ();
45
46 strcpy_disallowed = 0;
47 if (chk_calls)
48 abort ();
49 }
50
51 #ifndef MAX_OFFSET
52 #define MAX_OFFSET (sizeof (long long))
53 #endif
54
55 #ifndef MAX_COPY
56 #define MAX_COPY (10 * sizeof (long long))
57 #endif
58
59 #ifndef MAX_EXTRA
60 #define MAX_EXTRA (sizeof (long long))
61 #endif
62
63 #define MAX_LENGTH (MAX_OFFSET + MAX_COPY + 1 + MAX_EXTRA)
64
65 /* Use a sequence length that is not divisible by two, to make it more
66 likely to detect when words are mixed up. */
67 #define SEQUENCE_LENGTH 31
68
69 static union {
70 char buf[MAX_LENGTH];
71 long long align_int;
72 long double align_fp;
73 } u1, u2;
74
75 void
76 __attribute__((noinline))
77 test2 (void)
78 {
79 int off1, off2, len, i;
80 char *p, *q, c;
81
82 for (off1 = 0; off1 < MAX_OFFSET; off1++)
83 for (off2 = 0; off2 < MAX_OFFSET; off2++)
84 for (len = 1; len < MAX_COPY; len++)
85 {
86 for (i = 0, c = 'A'; i < MAX_LENGTH; i++, c++)
87 {
88 u1.buf[i] = 'a';
89 if (c >= 'A' + SEQUENCE_LENGTH)
90 c = 'A';
91 u2.buf[i] = c;
92 }
93 u2.buf[off2 + len] = '\0';
94
95 p = strcpy (u1.buf + off1, u2.buf + off2);
96 if (p != u1.buf + off1)
97 abort ();
98
99 q = u1.buf;
100 for (i = 0; i < off1; i++, q++)
101 if (*q != 'a')
102 abort ();
103
104 for (i = 0, c = 'A' + off2; i < len; i++, q++, c++)
105 {
106 if (c >= 'A' + SEQUENCE_LENGTH)
107 c = 'A';
108 if (*q != c)
109 abort ();
110 }
111
112 if (*q++ != '\0')
113 abort ();
114 for (i = 0; i < MAX_EXTRA; i++, q++)
115 if (*q != 'a')
116 abort ();
117 }
118 }
119
120 /* Test whether compile time checking is done where it should
121 and so is runtime object size checking. */
122 void
123 __attribute__((noinline))
124 test3 (void)
125 {
126 struct A { char buf1[10]; char buf2[10]; } a;
127 char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
128 char buf3[20];
129 int i;
130 const char *l;
131
132 /* The following calls should do runtime checking
133 - source length is not known, but destination is. */
134 chk_calls = 0;
135 strcpy (a.buf1 + 2, s3 + 3);
136 strcpy (r, s3 + 2);
137 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
138 strcpy (r, s2 + 2);
139 strcpy (r + 2, s3 + 3);
140 r = buf3;
141 for (i = 0; i < 4; ++i)
142 {
143 if (i == l1 - 1)
144 r = &a.buf1[1];
145 else if (i == l1)
146 r = &a.buf2[7];
147 else if (i == l1 + 1)
148 r = &buf3[5];
149 else if (i == l1 + 2)
150 r = &a.buf1[9];
151 }
152 strcpy (r, s2 + 4);
153 if (chk_calls != 5)
154 abort ();
155
156 /* Following have known destination and known source length,
157 so if optimizing certainly shouldn't result in the checking
158 variants. */
159 chk_calls = 0;
160 strcpy (a.buf1 + 2, "");
161 strcpy (r, "a");
162 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
163 strcpy (r, s1 + 1);
164 r = buf3;
165 l = "abc";
166 for (i = 0; i < 4; ++i)
167 {
168 if (i == l1 - 1)
169 r = &a.buf1[1], l = "e";
170 else if (i == l1)
171 r = &a.buf2[7], l = "gh";
172 else if (i == l1 + 1)
173 r = &buf3[5], l = "jkl";
174 else if (i == l1 + 2)
175 r = &a.buf1[9], l = "";
176 }
177 strcpy (r, "");
178 /* Here, strlen (l) + 1 is known to be at most 4 and
179 __builtin_object_size (&buf3[16], 0) is 4, so this doesn't need
180 runtime checking. */
181 strcpy (&buf3[16], l);
182 /* Unknown destination and source, no checking. */
183 strcpy (s4, s3);
184 if (chk_calls)
185 abort ();
186 chk_calls = 0;
187 }
188
189 /* Test whether runtime and/or compile time checking catches
190 buffer overflows. */
191 void
192 __attribute__((noinline))
193 test4 (void)
194 {
195 struct A { char buf1[10]; char buf2[10]; } a;
196 char buf3[20];
197
198 chk_fail_allowed = 1;
199 /* Runtime checks. */
200 if (__builtin_setjmp (chk_fail_buf) == 0)
201 {
202 strcpy (&a.buf2[9], s2 + 3);
203 abort ();
204 }
205 if (__builtin_setjmp (chk_fail_buf) == 0)
206 {
207 strcpy (&a.buf2[7], s3 + strlen (s3) - 3);
208 abort ();
209 }
210 /* This should be detectable at compile time already. */
211 if (__builtin_setjmp (chk_fail_buf) == 0)
212 {
213 strcpy (&buf3[19], "a");
214 abort ();
215 }
216 chk_fail_allowed = 0;
217 }
218
219 void
220 main_test (void)
221 {
222 #ifndef __OPTIMIZE__
223 /* Object size checking is only intended for -O[s123]. */
224 return;
225 #endif
226 __asm ("" : "=r" (s2) : "0" (s2));
227 __asm ("" : "=r" (s3) : "0" (s3));
228 __asm ("" : "=r" (l1) : "0" (l1));
229 test1 ();
230 test2 ();
231 s4 = p;
232 test3 ();
233 test4 ();
234 }