diff options
| author | sin | 2015-01-29 12:42:41 +0000 |
|---|---|---|
| committer | sin | 2015-01-29 12:42:41 +0000 |
| commit | 474f2887ce756bb5a14defb25e67b89678be0b8c (patch) | |
| tree | 6f7995df7890c937aeca36ecfc3dd38e06febdd9 /include/string.h | |
| parent | 3effc6dacea8b8ed0edab8ad93a902fa05bafde2 (diff) | |
Add compile-time checks as well
Diffstat (limited to 'include/string.h')
| -rw-r--r-- | include/string.h | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/include/string.h b/include/string.h index 107df9b..e464eab 100644 --- a/include/string.h +++ b/include/string.h | |||
| @@ -6,6 +6,9 @@ | |||
| 6 | 6 | ||
| 7 | #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 | 7 | #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 |
| 8 | 8 | ||
| 9 | #define __errordecl(name, msg) extern void name(void) __attribute__((__error__(msg))) | ||
| 10 | |||
| 11 | __errordecl(__memcpy_error, "memcpy: buffer overflow detected"); | ||
| 9 | static inline __attribute__ ((always_inline)) | 12 | static inline __attribute__ ((always_inline)) |
| 10 | void * | 13 | void * |
| 11 | __fortify_memcpy(void *__restrict dest, const void *__restrict src, size_t n) | 14 | __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) | |||
| 14 | char *d = dest; | 17 | char *d = dest; |
| 15 | const char *s = src; | 18 | const char *s = src; |
| 16 | 19 | ||
| 20 | if (__builtin_constant_p(n) && n > bos) | ||
| 21 | __memcpy_error(); | ||
| 22 | |||
| 17 | /* trap if pointers are overlapping */ | 23 | /* trap if pointers are overlapping */ |
| 18 | if ((d <= s && d + n > s) || | 24 | if ((d <= s && d + n > s) || |
| 19 | (s <= d && s + n > d)) | 25 | (s <= d && s + n > d)) |
| @@ -23,23 +29,31 @@ __fortify_memcpy(void *__restrict dest, const void *__restrict src, size_t n) | |||
| 23 | return memcpy(dest, src, n); | 29 | return memcpy(dest, src, n); |
| 24 | } | 30 | } |
| 25 | 31 | ||
| 32 | __errordecl(__memmove_error, "memmove: buffer overflow detected"); | ||
| 26 | static inline __attribute__ ((always_inline)) | 33 | static inline __attribute__ ((always_inline)) |
| 27 | void * | 34 | void * |
| 28 | __fortify_memmove(void *__restrict dest, const void *__restrict src, size_t n) | 35 | __fortify_memmove(void *__restrict dest, const void *__restrict src, size_t n) |
| 29 | { | 36 | { |
| 30 | size_t bos = __builtin_object_size(dest, 0); | 37 | size_t bos = __builtin_object_size(dest, 0); |
| 31 | 38 | ||
| 39 | if (__builtin_constant_p(n) && n > bos) | ||
| 40 | __memmove_error(); | ||
| 41 | |||
| 32 | if (n > bos) | 42 | if (n > bos) |
| 33 | __builtin_trap(); | 43 | __builtin_trap(); |
| 34 | return memmove(dest, src, n); | 44 | return memmove(dest, src, n); |
| 35 | } | 45 | } |
| 36 | 46 | ||
| 47 | __errordecl(__memset_error, "memset: buffer overflow detected"); | ||
| 37 | static inline __attribute__ ((always_inline)) | 48 | static inline __attribute__ ((always_inline)) |
| 38 | void * | 49 | void * |
| 39 | __fortify_memset(void *dest, int c, size_t n) | 50 | __fortify_memset(void *dest, int c, size_t n) |
| 40 | { | 51 | { |
| 41 | size_t bos = __builtin_object_size(dest, 0); | 52 | size_t bos = __builtin_object_size(dest, 0); |
| 42 | 53 | ||
| 54 | if (__builtin_constant_p(n) && n > bos) | ||
| 55 | __memset_error(); | ||
| 56 | |||
| 43 | if (n > bos) | 57 | if (n > bos) |
| 44 | __builtin_trap(); | 58 | __builtin_trap(); |
| 45 | return memset(dest, c, n); | 59 | return memset(dest, c, n); |
| @@ -56,12 +70,16 @@ __fortify_stpcpy(char *__restrict dest, const char *__restrict src) | |||
| 56 | return stpcpy(dest, src); | 70 | return stpcpy(dest, src); |
| 57 | } | 71 | } |
| 58 | 72 | ||
| 73 | __errordecl(__stpncpy_error, "stpncpy: buffer overflow detected"); | ||
| 59 | static inline __attribute__ ((always_inline)) | 74 | static inline __attribute__ ((always_inline)) |
| 60 | char * | 75 | char * |
| 61 | __fortify_stpncpy(char *__restrict dest, const char *__restrict src, size_t n) | 76 | __fortify_stpncpy(char *__restrict dest, const char *__restrict src, size_t n) |
| 62 | { | 77 | { |
| 63 | size_t bos = __builtin_object_size(dest, 0); | 78 | size_t bos = __builtin_object_size(dest, 0); |
| 64 | 79 | ||
| 80 | if (__builtin_costant_p(n) && n > bos) | ||
| 81 | __stpncpy_error(); | ||
| 82 | |||
| 65 | if (n > bos) | 83 | if (n > bos) |
| 66 | __builtin_trap(); | 84 | __builtin_trap(); |
| 67 | return stpncpy(dest, src, n); | 85 | return stpncpy(dest, src, n); |
| @@ -89,6 +107,7 @@ __fortify_strcpy(char *__restrict dest, const char *__restrict src) | |||
| 89 | return strcpy(dest, src); | 107 | return strcpy(dest, src); |
| 90 | } | 108 | } |
| 91 | 109 | ||
| 110 | __errordecl(__strncat_error, "strncat: buffer overflow detected"); | ||
| 92 | static inline __attribute__ ((always_inline)) | 111 | static inline __attribute__ ((always_inline)) |
| 93 | char * | 112 | char * |
| 94 | __fortify_strncat(char *__restrict dest, const char *__restrict src, size_t n) | 113 | __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) | |||
| 96 | size_t bos = __builtin_object_size(dest, 0); | 115 | size_t bos = __builtin_object_size(dest, 0); |
| 97 | size_t slen, dlen; | 116 | size_t slen, dlen; |
| 98 | 117 | ||
| 118 | if (__builtin_constant_p(n) && n > bos) | ||
| 119 | __strncat_error(); | ||
| 120 | |||
| 99 | if (n > bos) { | 121 | if (n > bos) { |
| 100 | slen = strlen(src); | 122 | slen = strlen(src); |
| 101 | dlen = strlen(dest); | 123 | dlen = strlen(dest); |
| @@ -107,24 +129,32 @@ __fortify_strncat(char *__restrict dest, const char *__restrict src, size_t n) | |||
| 107 | return strncat(dest, src, n); | 129 | return strncat(dest, src, n); |
| 108 | } | 130 | } |
| 109 | 131 | ||
| 132 | __errordecl(__strncpy_error, "strncpy: buffer overflow detected"); | ||
| 110 | static inline __attribute__ ((always_inline)) | 133 | static inline __attribute__ ((always_inline)) |
| 111 | char * | 134 | char * |
| 112 | __fortify_strncpy(char *__restrict dest, const char *__restrict src, size_t n) | 135 | __fortify_strncpy(char *__restrict dest, const char *__restrict src, size_t n) |
| 113 | { | 136 | { |
| 114 | size_t bos = __builtin_object_size(dest, 0); | 137 | size_t bos = __builtin_object_size(dest, 0); |
| 115 | 138 | ||
| 139 | if (__builtin_constant_p(n) && n > bos) | ||
| 140 | __strncpy_error(); | ||
| 141 | |||
| 116 | if (n > bos) | 142 | if (n > bos) |
| 117 | __builtin_trap(); | 143 | __builtin_trap(); |
| 118 | return strncpy(dest, src, n); | 144 | return strncpy(dest, src, n); |
| 119 | } | 145 | } |
| 120 | 146 | ||
| 121 | #ifdef _GNU_SOURCE | 147 | #ifdef _GNU_SOURCE |
| 148 | __errordecl(__mempcpy_error, "mempcpy: buffer overflow detected"); | ||
| 122 | static inline __attribute__ ((always_inline)) | 149 | static inline __attribute__ ((always_inline)) |
| 123 | void * | 150 | void * |
| 124 | __fortify_mempcpy(void *__restrict dest, const void *__restrict src, size_t n) | 151 | __fortify_mempcpy(void *__restrict dest, const void *__restrict src, size_t n) |
| 125 | { | 152 | { |
| 126 | size_t bos = __builtin_object_size(dest, 0); | 153 | size_t bos = __builtin_object_size(dest, 0); |
| 127 | 154 | ||
| 155 | if (__builtin_constant_p(n) && n > bos) | ||
| 156 | __mempcpy_error(); | ||
| 157 | |||
| 128 | if (n > bos) | 158 | if (n > bos) |
| 129 | __builtin_trap(); | 159 | __builtin_trap(); |
| 130 | return mempcpy(dest, src, n); | 160 | return mempcpy(dest, src, n); |
| @@ -132,23 +162,31 @@ __fortify_mempcpy(void *__restrict dest, const void *__restrict src, size_t n) | |||
| 132 | #endif | 162 | #endif |
| 133 | 163 | ||
| 134 | #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) | 164 | #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) |
| 165 | __errordecl(__strlcat_error, "strlcat: buffer overflow detected"); | ||
| 135 | static inline __attribute__ ((always_inline)) | 166 | static inline __attribute__ ((always_inline)) |
| 136 | size_t | 167 | size_t |
| 137 | __fortify_strlcat(char *__restrict dest, const char *__restrict src, size_t n) | 168 | __fortify_strlcat(char *__restrict dest, const char *__restrict src, size_t n) |
| 138 | { | 169 | { |
| 139 | size_t bos = __builtin_object_size(dest, 0); | 170 | size_t bos = __builtin_object_size(dest, 0); |
| 140 | 171 | ||
| 172 | if (__builtin_constant_p(n) && n > bos) | ||
| 173 | __strlcat_error(); | ||
| 174 | |||
| 141 | if (n > bos) | 175 | if (n > bos) |
| 142 | __builtin_trap(); | 176 | __builtin_trap(); |
| 143 | return strlcat(dest, src, n); | 177 | return strlcat(dest, src, n); |
| 144 | } | 178 | } |
| 145 | 179 | ||
| 180 | __errordecl(__strlcpy_error, "strlcpy: buffer overflow detected"); | ||
| 146 | static inline __attribute__ ((always_inline)) | 181 | static inline __attribute__ ((always_inline)) |
| 147 | size_t | 182 | size_t |
| 148 | __fortify_strlcpy(char *__restrict dest, const char *__restrict src, size_t n) | 183 | __fortify_strlcpy(char *__restrict dest, const char *__restrict src, size_t n) |
| 149 | { | 184 | { |
| 150 | size_t bos = __builtin_object_size(dest, 0); | 185 | size_t bos = __builtin_object_size(dest, 0); |
| 151 | 186 | ||
| 187 | if (__builtin_constant_p(n) && n > bos) | ||
| 188 | __strlcpy_error(); | ||
| 189 | |||
| 152 | if (n > bos) | 190 | if (n > bos) |
| 153 | __builtin_trap(); | 191 | __builtin_trap(); |
| 154 | return strlcpy(dest, src, n); | 192 | return strlcpy(dest, src, n); |
