commit 474f2887ce756bb5a14defb25e67b89678be0b8c
parent 3effc6dacea8b8ed0edab8ad93a902fa05bafde2
Author: sin <sin@2f30.org>
Date: Thu, 29 Jan 2015 12:42:41 +0000
Add compile-time checks as well
Diffstat:
3 files changed, 63 insertions(+), 1 deletion(-)
diff --git a/include/stdio.h b/include/stdio.h
@@ -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
diff --git a/include/string.h b/include/string.h
@@ -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);
diff --git a/include/strings.h b/include/strings.h
@@ -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);