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