Add compile-time checks as well

This commit is contained in:
sin 2015-01-29 12:42:41 +00:00
parent 3effc6dace
commit 474f2887ce
3 changed files with 63 additions and 1 deletions

View File

@ -6,17 +6,24 @@
#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0
#define __errordecl(name, msg) extern void name(void) __attribute__((__error__(msg)))
__errordecl(__fgets_error, "fgets: buffer overflow detected");
static inline __attribute__ ((always_inline))
char *
__fortify_fgets(char *s, int n, FILE *fp)
{
size_t bos = __builtin_object_size(s, 0);
if (__builtin_constant_p(n) && (size_t)n > bos)
__fgets_error();
if ((size_t)n > bos)
__builtin_trap();
return fgets(s, n, fp);
}
__errordecl(__vsnprintf_error, "vsnprintf: buffer overflow detected");
static inline
__attribute__ ((always_inline))
__attribute__ ((__format__ (printf, 3, 0)))
@ -27,6 +34,9 @@ __fortify_vsnprintf(char *__restrict s, size_t n, const char *__restrict fmt,
{
size_t bos = __builtin_object_size(s, 0);
if (__builtin_constant_p(n) && n > bos)
__vsnprintf_error();
if (n > bos)
__builtin_trap();
return vsnprintf(s, n, fmt, ap);
@ -36,13 +46,17 @@ __fortify_vsnprintf(char *__restrict s, size_t n, const char *__restrict fmt,
#define fgets(s, n, fp) __fortify_fgets(s, n, fp)
#undef vsnprintf
#define vsnprintf(s, n, fmt, ap) __fortify_vsnprintf(s, n, fmt, ap)
__errordecl(__snprintf_error, "snprintf: buffer overflow detected");
#undef snprintf
#define snprintf(s, n, fmt, ...) ({ \
size_t _n = (n); \
size_t bos = __builtin_object_size(s, 0); \
if (__builtin_constant_p(_n) && _n > bos) \
__snprintf_error(); \
if (_n > bos) \
__builtin_trap(); \
snprintf(s, _n, fmt, __VA_ARGS__); \
snprintf(s, _n, fmt, ## __VA_ARGS__); \
})
#endif

View File

@ -6,6 +6,9 @@
#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0
#define __errordecl(name, msg) extern void name(void) __attribute__((__error__(msg)))
__errordecl(__memcpy_error, "memcpy: buffer overflow detected");
static inline __attribute__ ((always_inline))
void *
__fortify_memcpy(void *__restrict dest, const void *__restrict src, size_t n)
@ -14,6 +17,9 @@ __fortify_memcpy(void *__restrict dest, const void *__restrict src, size_t n)
char *d = dest;
const char *s = src;
if (__builtin_constant_p(n) && n > bos)
__memcpy_error();
/* trap if pointers are overlapping */
if ((d <= s && d + n > s) ||
(s <= d && s + n > d))
@ -23,23 +29,31 @@ __fortify_memcpy(void *__restrict dest, const void *__restrict src, size_t n)
return memcpy(dest, src, n);
}
__errordecl(__memmove_error, "memmove: buffer overflow detected");
static inline __attribute__ ((always_inline))
void *
__fortify_memmove(void *__restrict dest, const void *__restrict src, size_t n)
{
size_t bos = __builtin_object_size(dest, 0);
if (__builtin_constant_p(n) && n > bos)
__memmove_error();
if (n > bos)
__builtin_trap();
return memmove(dest, src, n);
}
__errordecl(__memset_error, "memset: buffer overflow detected");
static inline __attribute__ ((always_inline))
void *
__fortify_memset(void *dest, int c, size_t n)
{
size_t bos = __builtin_object_size(dest, 0);
if (__builtin_constant_p(n) && n > bos)
__memset_error();
if (n > bos)
__builtin_trap();
return memset(dest, c, n);
@ -56,12 +70,16 @@ __fortify_stpcpy(char *__restrict dest, const char *__restrict src)
return stpcpy(dest, src);
}
__errordecl(__stpncpy_error, "stpncpy: buffer overflow detected");
static inline __attribute__ ((always_inline))
char *
__fortify_stpncpy(char *__restrict dest, const char *__restrict src, size_t n)
{
size_t bos = __builtin_object_size(dest, 0);
if (__builtin_costant_p(n) && n > bos)
__stpncpy_error();
if (n > bos)
__builtin_trap();
return stpncpy(dest, src, n);
@ -89,6 +107,7 @@ __fortify_strcpy(char *__restrict dest, const char *__restrict src)
return strcpy(dest, src);
}
__errordecl(__strncat_error, "strncat: buffer overflow detected");
static inline __attribute__ ((always_inline))
char *
__fortify_strncat(char *__restrict dest, const char *__restrict src, size_t n)
@ -96,6 +115,9 @@ __fortify_strncat(char *__restrict dest, const char *__restrict src, size_t n)
size_t bos = __builtin_object_size(dest, 0);
size_t slen, dlen;
if (__builtin_constant_p(n) && n > bos)
__strncat_error();
if (n > bos) {
slen = strlen(src);
dlen = strlen(dest);
@ -107,24 +129,32 @@ __fortify_strncat(char *__restrict dest, const char *__restrict src, size_t n)
return strncat(dest, src, n);
}
__errordecl(__strncpy_error, "strncpy: buffer overflow detected");
static inline __attribute__ ((always_inline))
char *
__fortify_strncpy(char *__restrict dest, const char *__restrict src, size_t n)
{
size_t bos = __builtin_object_size(dest, 0);
if (__builtin_constant_p(n) && n > bos)
__strncpy_error();
if (n > bos)
__builtin_trap();
return strncpy(dest, src, n);
}
#ifdef _GNU_SOURCE
__errordecl(__mempcpy_error, "mempcpy: buffer overflow detected");
static inline __attribute__ ((always_inline))
void *
__fortify_mempcpy(void *__restrict dest, const void *__restrict src, size_t n)
{
size_t bos = __builtin_object_size(dest, 0);
if (__builtin_constant_p(n) && n > bos)
__mempcpy_error();
if (n > bos)
__builtin_trap();
return mempcpy(dest, src, n);
@ -132,23 +162,31 @@ __fortify_mempcpy(void *__restrict dest, const void *__restrict src, size_t n)
#endif
#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
__errordecl(__strlcat_error, "strlcat: buffer overflow detected");
static inline __attribute__ ((always_inline))
size_t
__fortify_strlcat(char *__restrict dest, const char *__restrict src, size_t n)
{
size_t bos = __builtin_object_size(dest, 0);
if (__builtin_constant_p(n) && n > bos)
__strlcat_error();
if (n > bos)
__builtin_trap();
return strlcat(dest, src, n);
}
__errordecl(__strlcpy_error, "strlcpy: buffer overflow detected");
static inline __attribute__ ((always_inline))
size_t
__fortify_strlcpy(char *__restrict dest, const char *__restrict src, size_t n)
{
size_t bos = __builtin_object_size(dest, 0);
if (__builtin_constant_p(n) && n > bos)
__strlcpy_error();
if (n > bos)
__builtin_trap();
return strlcpy(dest, src, n);

View File

@ -6,26 +6,36 @@
#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0
#define __errordecl(name, msg) extern void name(void) __attribute__((__error__(msg)))
#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_POSIX_SOURCE) \
|| (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE+0 < 200809L) \
|| (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700)
__errordecl(__bcopy_error, "bcopy: buffer overflow detected");
static inline __attribute__ ((always_inline))
void
__fortify_bcopy(const void *__restrict src, void *__restrict dest, size_t n)
{
size_t bos = __builtin_object_size(dest, 0);
if (__builtin_constant_p(n) && n > bos)
__bcopy_error();
if (n > bos)
__builtin_trap();
return bcopy(src, dest, n);
}
__errordecl(__bzero_error, "bzero: buffer overflow detected");
static inline __attribute__ ((always_inline))
void
__fortify_bzero(void *src, size_t n)
{
size_t bos = __builtin_object_size(src, 0);
if (__builtin_constant_p(n) && n > bos)
__bzero_error();
if (n > bos)
__builtin_trap();
return bzero(src, n);