1 #include <stdarg.h>
2 #ifdef __unix__
3 #include <sys/types.h>
4 #endif
5
6 /* If some target has a Max alignment less than 16, please create
7 a #ifdef around the alignment and add your alignment. */
8 #ifdef __pdp11__
9 #define ALIGNMENT 2
10 #else
11 #define ALIGNMENT 16
12 #endif
13
14 extern void abort (void);
15
16 extern int inside_main;
17 void *chk_fail_buf[256] __attribute__((aligned (ALIGNMENT)));
18 volatile int chk_fail_allowed, chk_calls;
19 volatile int memcpy_disallowed, mempcpy_disallowed, memmove_disallowed;
20 volatile int memset_disallowed, strcpy_disallowed, stpcpy_disallowed;
21 volatile int strncpy_disallowed, stpncpy_disallowed, strcat_disallowed;
22 volatile int strncat_disallowed, sprintf_disallowed, vsprintf_disallowed;
23 volatile int snprintf_disallowed, vsnprintf_disallowed;
24 extern __SIZE_TYPE__ strlen (const char *);
25 extern int vsprintf (char *, const char *, va_list);
26
27 void __attribute__((noreturn))
28 __chk_fail (void)
29 {
30 if (chk_fail_allowed)
31 __builtin_longjmp (chk_fail_buf, 1);
32 abort ();
33 }
34
35 void *
36 memcpy (void *dst, const void *src, __SIZE_TYPE__ n)
37 {
38 const char *srcp;
39 char *dstp;
40
41 #ifdef __OPTIMIZE__
42 if (memcpy_disallowed && inside_main)
43 abort ();
44 #endif
45
46 srcp = src;
47 dstp = dst;
48 while (n-- != 0)
49 *dstp++ = *srcp++;
50
51 return dst;
52 }
53
54 void *
55 __memcpy_chk (void *dst, const void *src, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
56 {
57 /* If size is -1, GCC should always optimize the call into memcpy. */
58 if (size == (__SIZE_TYPE__) -1)
59 abort ();
60 ++chk_calls;
61 if (n > size)
62 __chk_fail ();
63 return memcpy (dst, src, n);
64 }
65
66 void *
67 mempcpy (void *dst, const void *src, __SIZE_TYPE__ n)
68 {
69 const char *srcp;
70 char *dstp;
71
72 #ifdef __OPTIMIZE__
73 if (mempcpy_disallowed && inside_main)
74 abort ();
75 #endif
76
77 srcp = src;
78 dstp = dst;
79 while (n-- != 0)
80 *dstp++ = *srcp++;
81
82 return dstp;
83 }
84
85 void *
86 __mempcpy_chk (void *dst, const void *src, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
87 {
88 /* If size is -1, GCC should always optimize the call into mempcpy. */
89 if (size == (__SIZE_TYPE__) -1)
90 abort ();
91 ++chk_calls;
92 if (n > size)
93 __chk_fail ();
94 return mempcpy (dst, src, n);
95 }
96
97 void *
98 memmove (void *dst, const void *src, __SIZE_TYPE__ n)
99 {
100 const char *srcp;
101 char *dstp;
102
103 #ifdef __OPTIMIZE__
104 if (memmove_disallowed && inside_main)
105 abort ();
106 #endif
107
108 srcp = src;
109 dstp = dst;
110 if (srcp < dstp)
111 while (n-- != 0)
112 dstp[n] = srcp[n];
113 else
114 while (n-- != 0)
115 *dstp++ = *srcp++;
116
117 return dst;
118 }
119
120 void *
121 __memmove_chk (void *dst, const void *src, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
122 {
123 /* If size is -1, GCC should always optimize the call into memmove. */
124 if (size == (__SIZE_TYPE__) -1)
125 abort ();
126 ++chk_calls;
127 if (n > size)
128 __chk_fail ();
129 return memmove (dst, src, n);
130 }
131
132 void *
133 memset (void *dst, int c, __SIZE_TYPE__ n)
134 {
135 while (n-- != 0)
136 n[(char *) dst] = c;
137
138 /* Single-byte memsets should be done inline when optimisation
139 is enabled. Do this after the copy in case we're being called to
140 initialize bss. */
141 #ifdef __OPTIMIZE__
142 if (memset_disallowed && inside_main && n < 2)
143 abort ();
144 #endif
145
146 return dst;
147 }
148
149 void *
150 __memset_chk (void *dst, int c, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
151 {
152 /* If size is -1, GCC should always optimize the call into memset. */
153 if (size == (__SIZE_TYPE__) -1)
154 abort ();
155 ++chk_calls;
156 if (n > size)
157 __chk_fail ();
158 return memset (dst, c, n);
159 }
160
161 char *
162 strcpy (char *d, const char *s)
163 {
164 char *r = d;
165 #ifdef __OPTIMIZE__
166 if (strcpy_disallowed && inside_main)
167 abort ();
168 #endif
169 while ((*d++ = *s++));
170 return r;
171 }
172
173 char *
174 __strcpy_chk (char *d, const char *s, __SIZE_TYPE__ size)
175 {
176 /* If size is -1, GCC should always optimize the call into strcpy. */
177 if (size == (__SIZE_TYPE__) -1)
178 abort ();
179 ++chk_calls;
180 if (strlen (s) >= size)
181 __chk_fail ();
182 return strcpy (d, s);
183 }
184
185 char *
186 stpcpy (char *dst, const char *src)
187 {
188 #ifdef __OPTIMIZE__
189 if (stpcpy_disallowed && inside_main)
190 abort ();
191 #endif
192
193 while (*src != 0)
194 *dst++ = *src++;
195
196 *dst = 0;
197 return dst;
198 }
199
200 char *
201 __stpcpy_chk (char *d, const char *s, __SIZE_TYPE__ size)
202 {
203 /* If size is -1, GCC should always optimize the call into stpcpy. */
204 if (size == (__SIZE_TYPE__) -1)
205 abort ();
206 ++chk_calls;
207 if (strlen (s) >= size)
208 __chk_fail ();
209 return stpcpy (d, s);
210 }
211
212 char *
213 stpncpy (char *dst, const char *src, __SIZE_TYPE__ n)
214 {
215 #ifdef __OPTIMIZE__
216 if (stpncpy_disallowed && inside_main)
217 abort ();
218 #endif
219
220 for (; *src && n; n--)
221 *dst++ = *src++;
222
223 char *ret = dst;
224
225 while (n--)
226 *dst++ = 0;
227
228 return ret;
229 }
230
231
232 char *
233 __stpncpy_chk (char *s1, const char *s2, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
234 {
235 /* If size is -1, GCC should always optimize the call into stpncpy. */
236 if (size == (__SIZE_TYPE__) -1)
237 abort ();
238 ++chk_calls;
239 if (n > size)
240 __chk_fail ();
241 return stpncpy (s1, s2, n);
242 }
243
244 char *
245 strncpy (char *s1, const char *s2, __SIZE_TYPE__ n)
246 {
247 char *dest = s1;
248 #ifdef __OPTIMIZE__
249 if (strncpy_disallowed && inside_main)
250 abort();
251 #endif
252 for (; *s2 && n; n--)
253 *s1++ = *s2++;
254 while (n--)
255 *s1++ = 0;
256 return dest;
257 }
258
259 char *
260 __strncpy_chk (char *s1, const char *s2, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
261 {
262 /* If size is -1, GCC should always optimize the call into strncpy. */
263 if (size == (__SIZE_TYPE__) -1)
264 abort ();
265 ++chk_calls;
266 if (n > size)
267 __chk_fail ();
268 return strncpy (s1, s2, n);
269 }
270
271 char *
272 strcat (char *dst, const char *src)
273 {
274 char *p = dst;
275
276 #ifdef __OPTIMIZE__
277 if (strcat_disallowed && inside_main)
278 abort ();
279 #endif
280
281 while (*p)
282 p++;
283 while ((*p++ = *src++))
284 ;
285 return dst;
286 }
287
288 char *
289 __strcat_chk (char *d, const char *s, __SIZE_TYPE__ size)
290 {
291 /* If size is -1, GCC should always optimize the call into strcat. */
292 if (size == (__SIZE_TYPE__) -1)
293 abort ();
294 ++chk_calls;
295 if (strlen (d) + strlen (s) >= size)
296 __chk_fail ();
297 return strcat (d, s);
298 }
299
300 char *
301 strncat (char *s1, const char *s2, __SIZE_TYPE__ n)
302 {
303 char *dest = s1;
304 char c;
305 #ifdef __OPTIMIZE__
306 if (strncat_disallowed && inside_main)
307 abort();
308 #endif
309 while (*s1) s1++;
310 c = '\0';
311 while (n > 0)
312 {
313 c = *s2++;
314 *s1++ = c;
315 if (c == '\0')
316 return dest;
317 n--;
318 }
319 if (c != '\0')
320 *s1 = '\0';
321 return dest;
322 }
323
324 char *
325 __strncat_chk (char *d, const char *s, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
326 {
327 __SIZE_TYPE__ len = strlen (d), n1 = n;
328 const char *s1 = s;
329
330 /* If size is -1, GCC should always optimize the call into strncat. */
331 if (size == (__SIZE_TYPE__) -1)
332 abort ();
333 ++chk_calls;
334 while (len < size && n1 > 0)
335 {
336 if (*s1++ == '\0')
337 break;
338 ++len;
339 --n1;
340 }
341
342 if (len >= size)
343 __chk_fail ();
344 return strncat (d, s, n);
345 }
346
347 /* No chk test in GCC testsuite needs more bytes than this.
348 As we can't expect vsnprintf to be available on the target,
349 assume 4096 bytes is enough. */
350 static char chk_sprintf_buf[4096];
351
352 int
353 __sprintf_chk (char *str, int flag, __SIZE_TYPE__ size, const char *fmt, ...)
354 {
355 int ret;
356 va_list ap;
357
358 /* If size is -1 and flag 0, GCC should always optimize the call into
359 sprintf. */
360 if (size == (__SIZE_TYPE__) -1 && flag == 0)
361 abort ();
362 ++chk_calls;
363 #ifdef __OPTIMIZE__
364 if (sprintf_disallowed && inside_main)
365 abort();
366 #endif
367 va_start (ap, fmt);
368 ret = vsprintf (chk_sprintf_buf, fmt, ap);
369 va_end (ap);
370 if (ret >= 0)
371 {
372 if (ret >= size)
373 __chk_fail ();
374 memcpy (str, chk_sprintf_buf, ret + 1);
375 }
376 return ret;
377 }
378
379 int
380 __vsprintf_chk (char *str, int flag, __SIZE_TYPE__ size, const char *fmt,
381 va_list ap)
382 {
383 int ret;
384
385 /* If size is -1 and flag 0, GCC should always optimize the call into
386 vsprintf. */
387 if (size == (__SIZE_TYPE__) -1 && flag == 0)
388 abort ();
389 ++chk_calls;
390 #ifdef __OPTIMIZE__
391 if (vsprintf_disallowed && inside_main)
392 abort();
393 #endif
394 ret = vsprintf (chk_sprintf_buf, fmt, ap);
395 if (ret >= 0)
396 {
397 if (ret >= size)
398 __chk_fail ();
399 memcpy (str, chk_sprintf_buf, ret + 1);
400 }
401 return ret;
402 }
403
404 int
405 __snprintf_chk (char *str, __SIZE_TYPE__ len, int flag, __SIZE_TYPE__ size,
406 const char *fmt, ...)
407 {
408 int ret;
409 va_list ap;
410
411 /* If size is -1 and flag 0, GCC should always optimize the call into
412 snprintf. */
413 if (size == (__SIZE_TYPE__) -1 && flag == 0)
414 abort ();
415 ++chk_calls;
416 if (size < len)
417 __chk_fail ();
418 #ifdef __OPTIMIZE__
419 if (snprintf_disallowed && inside_main)
420 abort();
421 #endif
422 va_start (ap, fmt);
423 ret = vsprintf (chk_sprintf_buf, fmt, ap);
424 va_end (ap);
425 if (ret >= 0)
426 {
427 if (ret < len)
428 memcpy (str, chk_sprintf_buf, ret + 1);
429 else
430 {
431 memcpy (str, chk_sprintf_buf, len - 1);
432 str[len - 1] = '\0';
433 }
434 }
435 return ret;
436 }
437
438 int
439 __vsnprintf_chk (char *str, __SIZE_TYPE__ len, int flag, __SIZE_TYPE__ size,
440 const char *fmt, va_list ap)
441 {
442 int ret;
443
444 /* If size is -1 and flag 0, GCC should always optimize the call into
445 vsnprintf. */
446 if (size == (__SIZE_TYPE__) -1 && flag == 0)
447 abort ();
448 ++chk_calls;
449 if (size < len)
450 __chk_fail ();
451 #ifdef __OPTIMIZE__
452 if (vsnprintf_disallowed && inside_main)
453 abort();
454 #endif
455 ret = vsprintf (chk_sprintf_buf, fmt, ap);
456 if (ret >= 0)
457 {
458 if (ret < len)
459 memcpy (str, chk_sprintf_buf, ret + 1);
460 else
461 {
462 memcpy (str, chk_sprintf_buf, len - 1);
463 str[len - 1] = '\0';
464 }
465 }
466 return ret;
467 }
468
469 int
470 snprintf (char *str, __SIZE_TYPE__ len, const char *fmt, ...)
471 {
472 int ret;
473 va_list ap;
474
475 #ifdef __OPTIMIZE__
476 if (snprintf_disallowed && inside_main)
477 abort();
478 #endif
479 va_start (ap, fmt);
480 ret = vsprintf (chk_sprintf_buf, fmt, ap);
481 va_end (ap);
482 if (ret >= 0)
483 {
484 if (ret < len)
485 memcpy (str, chk_sprintf_buf, ret + 1);
486 else if (len)
487 {
488 memcpy (str, chk_sprintf_buf, len - 1);
489 str[len - 1] = '\0';
490 }
491 }
492 return ret;
493 }
494
495 /* uClibc's vsprintf calls vsnprintf. */
496 #ifndef __UCLIBC__
497 int
498 vsnprintf (char *str, __SIZE_TYPE__ len, const char *fmt, va_list ap)
499 {
500 int ret;
501
502 #ifdef __OPTIMIZE__
503 if (vsnprintf_disallowed && inside_main)
504 abort();
505 #endif
506 ret = vsprintf (chk_sprintf_buf, fmt, ap);
507 if (ret >= 0)
508 {
509 if (ret < len)
510 memcpy (str, chk_sprintf_buf, ret + 1);
511 else if (len)
512 {
513 memcpy (str, chk_sprintf_buf, len - 1);
514 str[len - 1] = '\0';
515 }
516 }
517 return ret;
518 }
519 #endif
520
521 #if defined(__powerpc__) && defined(__LONG_DOUBLE_IEEE128__)
522 __typeof (__sprintf_chk) __sprintf_chkieee128
523 __attribute__((alias ("__sprintf_chk")));
524 __typeof (__vsprintf_chk) __vsprintf_chkieee128
525 __attribute__((alias ("__vsprintf_chk")));
526 __typeof (__snprintf_chk) __snprintf_chkieee128
527 __attribute__((alias ("__snprintf_chk")));
528 __typeof (__vsnprintf_chk) __vsnprintf_chkieee128
529 __attribute__((alias ("__vsnprintf_chk")));
530 #endif