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