diff options
Diffstat (limited to 'gcc/testsuite/gcc.c-torture/execute/builtins/lib/chk.c')
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/builtins/lib/chk.c | 478 |
1 files changed, 478 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/chk.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/chk.c new file mode 100644 index 000000000..e5197902b --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/chk.c @@ -0,0 +1,478 @@ +#include <stdarg.h> +#ifdef __unix__ +#include <sys/types.h> +#endif + +extern void abort (void); + +extern int inside_main; +void *chk_fail_buf[256] __attribute__((aligned (16))); +volatile int chk_fail_allowed, chk_calls; +volatile int memcpy_disallowed, mempcpy_disallowed, memmove_disallowed; +volatile int memset_disallowed, strcpy_disallowed, stpcpy_disallowed; +volatile int strncpy_disallowed, strcat_disallowed, strncat_disallowed; +volatile int sprintf_disallowed, vsprintf_disallowed; +volatile int snprintf_disallowed, vsnprintf_disallowed; +extern __SIZE_TYPE__ strlen (const char *); +extern int vsprintf (char *, const char *, va_list); + +void __attribute__((noreturn)) +__chk_fail (void) +{ + if (chk_fail_allowed) + __builtin_longjmp (chk_fail_buf, 1); + abort (); +} + +void * +memcpy (void *dst, const void *src, __SIZE_TYPE__ n) +{ + const char *srcp; + char *dstp; + +#ifdef __OPTIMIZE__ + if (memcpy_disallowed && inside_main) + abort (); +#endif + + srcp = src; + dstp = dst; + while (n-- != 0) + *dstp++ = *srcp++; + + return dst; +} + +void * +__memcpy_chk (void *dst, const void *src, __SIZE_TYPE__ n, __SIZE_TYPE__ size) +{ + /* If size is -1, GCC should always optimize the call into memcpy. */ + if (size == (__SIZE_TYPE__) -1) + abort (); + ++chk_calls; + if (n > size) + __chk_fail (); + return memcpy (dst, src, n); +} + +void * +mempcpy (void *dst, const void *src, __SIZE_TYPE__ n) +{ + const char *srcp; + char *dstp; + +#ifdef __OPTIMIZE__ + if (mempcpy_disallowed && inside_main) + abort (); +#endif + + srcp = src; + dstp = dst; + while (n-- != 0) + *dstp++ = *srcp++; + + return dstp; +} + +void * +__mempcpy_chk (void *dst, const void *src, __SIZE_TYPE__ n, __SIZE_TYPE__ size) +{ + /* If size is -1, GCC should always optimize the call into mempcpy. */ + if (size == (__SIZE_TYPE__) -1) + abort (); + ++chk_calls; + if (n > size) + __chk_fail (); + return mempcpy (dst, src, n); +} + +void * +memmove (void *dst, const void *src, __SIZE_TYPE__ n) +{ + const char *srcp; + char *dstp; + +#ifdef __OPTIMIZE__ + if (memmove_disallowed && inside_main) + abort (); +#endif + + srcp = src; + dstp = dst; + if (srcp < dstp) + while (n-- != 0) + dstp[n] = srcp[n]; + else + while (n-- != 0) + *dstp++ = *srcp++; + + return dst; +} + +void * +__memmove_chk (void *dst, const void *src, __SIZE_TYPE__ n, __SIZE_TYPE__ size) +{ + /* If size is -1, GCC should always optimize the call into memmove. */ + if (size == (__SIZE_TYPE__) -1) + abort (); + ++chk_calls; + if (n > size) + __chk_fail (); + return memmove (dst, src, n); +} + +void * +memset (void *dst, int c, __SIZE_TYPE__ n) +{ + /* Single-byte memsets should be done inline when optimisation + is enabled. */ +#ifdef __OPTIMIZE__ + if (memset_disallowed && inside_main && n < 2) + abort (); +#endif + + while (n-- != 0) + n[(char *) dst] = c; + + return dst; +} + +void * +__memset_chk (void *dst, int c, __SIZE_TYPE__ n, __SIZE_TYPE__ size) +{ + /* If size is -1, GCC should always optimize the call into memset. */ + if (size == (__SIZE_TYPE__) -1) + abort (); + ++chk_calls; + if (n > size) + __chk_fail (); + return memset (dst, c, n); +} + +char * +strcpy (char *d, const char *s) +{ + char *r = d; +#ifdef __OPTIMIZE__ + if (strcpy_disallowed && inside_main) + abort (); +#endif + while ((*d++ = *s++)); + return r; +} + +char * +__strcpy_chk (char *d, const char *s, __SIZE_TYPE__ size) +{ + /* If size is -1, GCC should always optimize the call into strcpy. */ + if (size == (__SIZE_TYPE__) -1) + abort (); + ++chk_calls; + if (strlen (s) >= size) + __chk_fail (); + return strcpy (d, s); +} + +char * +stpcpy (char *dst, const char *src) +{ +#ifdef __OPTIMIZE__ + if (stpcpy_disallowed && inside_main) + abort (); +#endif + + while (*src != 0) + *dst++ = *src++; + + *dst = 0; + return dst; +} + +char * +__stpcpy_chk (char *d, const char *s, __SIZE_TYPE__ size) +{ + /* If size is -1, GCC should always optimize the call into stpcpy. */ + if (size == (__SIZE_TYPE__) -1) + abort (); + ++chk_calls; + if (strlen (s) >= size) + __chk_fail (); + return stpcpy (d, s); +} + +char * +strncpy (char *s1, const char *s2, __SIZE_TYPE__ n) +{ + char *dest = s1; +#ifdef __OPTIMIZE__ + if (strncpy_disallowed && inside_main) + abort(); +#endif + for (; *s2 && n; n--) + *s1++ = *s2++; + while (n--) + *s1++ = 0; + return dest; +} + +char * +__strncpy_chk (char *s1, const char *s2, __SIZE_TYPE__ n, __SIZE_TYPE__ size) +{ + /* If size is -1, GCC should always optimize the call into strncpy. */ + if (size == (__SIZE_TYPE__) -1) + abort (); + ++chk_calls; + if (n > size) + __chk_fail (); + return strncpy (s1, s2, n); +} + +char * +strcat (char *dst, const char *src) +{ + char *p = dst; + +#ifdef __OPTIMIZE__ + if (strcat_disallowed && inside_main) + abort (); +#endif + + while (*p) + p++; + while ((*p++ = *src++)) + ; + return dst; +} + +char * +__strcat_chk (char *d, const char *s, __SIZE_TYPE__ size) +{ + /* If size is -1, GCC should always optimize the call into strcat. */ + if (size == (__SIZE_TYPE__) -1) + abort (); + ++chk_calls; + if (strlen (d) + strlen (s) >= size) + __chk_fail (); + return strcat (d, s); +} + +char * +strncat (char *s1, const char *s2, __SIZE_TYPE__ n) +{ + char *dest = s1; + char c; +#ifdef __OPTIMIZE__ + if (strncat_disallowed && inside_main) + abort(); +#endif + while (*s1) s1++; + c = '\0'; + while (n > 0) + { + c = *s2++; + *s1++ = c; + if (c == '\0') + return dest; + n--; + } + if (c != '\0') + *s1 = '\0'; + return dest; +} + +char * +__strncat_chk (char *d, const char *s, __SIZE_TYPE__ n, __SIZE_TYPE__ size) +{ + __SIZE_TYPE__ len = strlen (d), n1 = n; + const char *s1 = s; + + /* If size is -1, GCC should always optimize the call into strncat. */ + if (size == (__SIZE_TYPE__) -1) + abort (); + ++chk_calls; + while (len < size && n1 > 0) + { + if (*s1++ == '\0') + break; + ++len; + --n1; + } + + if (len >= size) + __chk_fail (); + return strncat (d, s, n); +} + +/* No chk test in GCC testsuite needs more bytes than this. + As we can't expect vsnprintf to be available on the target, + assume 4096 bytes is enough. */ +static char chk_sprintf_buf[4096]; + +int +__sprintf_chk (char *str, int flag, __SIZE_TYPE__ size, const char *fmt, ...) +{ + int ret; + va_list ap; + + /* If size is -1 and flag 0, GCC should always optimize the call into + sprintf. */ + if (size == (__SIZE_TYPE__) -1 && flag == 0) + abort (); + ++chk_calls; +#ifdef __OPTIMIZE__ + if (sprintf_disallowed && inside_main) + abort(); +#endif + va_start (ap, fmt); + ret = vsprintf (chk_sprintf_buf, fmt, ap); + va_end (ap); + if (ret >= 0) + { + if (ret >= size) + __chk_fail (); + memcpy (str, chk_sprintf_buf, ret + 1); + } + return ret; +} + +int +__vsprintf_chk (char *str, int flag, __SIZE_TYPE__ size, const char *fmt, + va_list ap) +{ + int ret; + + /* If size is -1 and flag 0, GCC should always optimize the call into + vsprintf. */ + if (size == (__SIZE_TYPE__) -1 && flag == 0) + abort (); + ++chk_calls; +#ifdef __OPTIMIZE__ + if (vsprintf_disallowed && inside_main) + abort(); +#endif + ret = vsprintf (chk_sprintf_buf, fmt, ap); + if (ret >= 0) + { + if (ret >= size) + __chk_fail (); + memcpy (str, chk_sprintf_buf, ret + 1); + } + return ret; +} + +int +__snprintf_chk (char *str, __SIZE_TYPE__ len, int flag, __SIZE_TYPE__ size, + const char *fmt, ...) +{ + int ret; + va_list ap; + + /* If size is -1 and flag 0, GCC should always optimize the call into + snprintf. */ + if (size == (__SIZE_TYPE__) -1 && flag == 0) + abort (); + ++chk_calls; + if (size < len) + __chk_fail (); +#ifdef __OPTIMIZE__ + if (snprintf_disallowed && inside_main) + abort(); +#endif + va_start (ap, fmt); + ret = vsprintf (chk_sprintf_buf, fmt, ap); + va_end (ap); + if (ret >= 0) + { + if (ret < len) + memcpy (str, chk_sprintf_buf, ret + 1); + else + { + memcpy (str, chk_sprintf_buf, len - 1); + str[len - 1] = '\0'; + } + } + return ret; +} + +int +__vsnprintf_chk (char *str, __SIZE_TYPE__ len, int flag, __SIZE_TYPE__ size, + const char *fmt, va_list ap) +{ + int ret; + + /* If size is -1 and flag 0, GCC should always optimize the call into + vsnprintf. */ + if (size == (__SIZE_TYPE__) -1 && flag == 0) + abort (); + ++chk_calls; + if (size < len) + __chk_fail (); +#ifdef __OPTIMIZE__ + if (vsnprintf_disallowed && inside_main) + abort(); +#endif + ret = vsprintf (chk_sprintf_buf, fmt, ap); + if (ret >= 0) + { + if (ret < len) + memcpy (str, chk_sprintf_buf, ret + 1); + else + { + memcpy (str, chk_sprintf_buf, len - 1); + str[len - 1] = '\0'; + } + } + return ret; +} + +int +snprintf (char *str, __SIZE_TYPE__ len, const char *fmt, ...) +{ + int ret; + va_list ap; + +#ifdef __OPTIMIZE__ + if (snprintf_disallowed && inside_main) + abort(); +#endif + va_start (ap, fmt); + ret = vsprintf (chk_sprintf_buf, fmt, ap); + va_end (ap); + if (ret >= 0) + { + if (ret < len) + memcpy (str, chk_sprintf_buf, ret + 1); + else if (len) + { + memcpy (str, chk_sprintf_buf, len - 1); + str[len - 1] = '\0'; + } + } + return ret; +} + +/* uClibc's vsprintf calls vsnprintf. */ +#ifndef __UCLIBC__ +int +vsnprintf (char *str, __SIZE_TYPE__ len, const char *fmt, va_list ap) +{ + int ret; + +#ifdef __OPTIMIZE__ + if (vsnprintf_disallowed && inside_main) + abort(); +#endif + ret = vsprintf (chk_sprintf_buf, fmt, ap); + if (ret >= 0) + { + if (ret < len) + memcpy (str, chk_sprintf_buf, ret + 1); + else if (len) + { + memcpy (str, chk_sprintf_buf, len - 1); + str[len - 1] = '\0'; + } + } + return ret; +} +#endif |