fortify-headers

standalone fortify-source implementation
git clone git://git.2f30.org/fortify-headers
Log | Files | Refs | README | LICENSE

string.h (10704B)


      1 /*
      2  * Copyright (C) 2015-2016 Dimitris Papastamos <sin@2f30.org>
      3  * Copyright (C) 2022 q66 <q66@chimera-linux.org>
      4  *
      5  * Permission to use, copy, modify, and/or distribute this software for any
      6  * purpose with or without fee is hereby granted.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 #ifndef _FORTIFY_STRING_H
     18 #define _FORTIFY_STRING_H
     19 
     20 #if !defined(__cplusplus) && !defined(__clang__)
     21 __extension__
     22 #endif
     23 #include_next <string.h>
     24 
     25 #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0
     26 #include "fortify-headers.h"
     27 
     28 #ifdef __cplusplus
     29 extern "C" {
     30 #endif
     31 
     32 #undef memcpy
     33 #undef memchr
     34 #undef memmove
     35 #undef memset
     36 #undef strcat
     37 #undef strcpy
     38 #undef strlen
     39 #undef strncat
     40 #undef strncpy
     41 
     42 __fh_access(write_only, 1, 3)
     43 __fh_access(read_only, 2, 3)
     44 #if __has_builtin(__builtin_memcpy)
     45 __diagnose_as_builtin(__builtin_memcpy, 1, 2, 3)
     46 #endif
     47 _FORTIFY_FN(memcpy) void *memcpy(void * _FORTIFY_POS0 __od,
     48                                  const void * _FORTIFY_POS0 __os, size_t __n)
     49 __error_if((__fh_bos(__od, 0) < __n), "'memcpy' called with `n` bigger than the size of `d`.")
     50 {
     51 #if __has_builtin(__builtin___memcpy_chk) && USE_NATIVE_CHK
     52 	return __builtin___memcpy_chk(__od, __os, __n, __fh_bos(__od, 0));
     53 #else
     54 	__fh_size_t __bd = __fh_bos(__od, 0);
     55 	__fh_size_t __bs = __fh_bos(__os, 0);
     56 	char *__d = (char *)__od;
     57 	const char *__s = (const char *)__os;
     58 
     59 	if __fh_overlap(__d, __bd, __s, __n)
     60 		__builtin_trap();
     61 	if (__n > __bd || __n > __bs)
     62 		__builtin_trap();
     63 	return __builtin_memcpy(__od, __os, __n);
     64 #endif
     65 }
     66 
     67 __fh_access(write_only, 1, 3)
     68 __fh_access(read_only, 2, 3)
     69 #if __has_builtin(__builtin_memmove)
     70 __diagnose_as_builtin(__builtin_memmove, 1, 2, 3)
     71 #endif
     72 _FORTIFY_FN(memmove) void *memmove(void * _FORTIFY_POS0 __d,
     73                                    const void * _FORTIFY_POS0 __s, size_t __n)
     74 {
     75 #if __has_builtin(__builtin___memmove_chk) && USE_NATIVE_CHK
     76 	return __builtin___memmove_chk(__d, __s, __n, __fh_bos(__d, 0));
     77 #else
     78 	__fh_size_t __bd = __fh_bos(__d, 0);
     79 	__fh_size_t __bs = __fh_bos(__s, 0);
     80 
     81 	if (__n > __bd || __n > __bs)
     82 		__builtin_trap();
     83 	return __orig_memmove(__d, __s, __n);
     84 #endif
     85 }
     86 
     87 __fh_access(write_only, 1, 3)
     88 #if __has_builtin(__builtin_memset)
     89 __diagnose_as_builtin(__builtin_memset, 1, 2, 3)
     90 #endif
     91 _FORTIFY_FN(memset) void *memset(void * _FORTIFY_POS0 __d, int __c, size_t __n)
     92 __warning_if(__c != 0 && __n == 0, "'memset' will set `0` bytes; did you invert the arguments?")
     93 {
     94 #if __has_builtin(__builtin___memset_chk) && USE_NATIVE_CHK
     95 	return __builtin___memset_chk(__d, __c, __n, __fh_bos(__d, 0));
     96 #else
     97 	__fh_size_t __b = __fh_bos(__d, 0);
     98 
     99 	if (__n > __b)
    100 		__builtin_trap();
    101 	return __builtin_memset(__d, __c, __n);
    102 #endif
    103 }
    104 
    105 __fh_access(read_only, 1, 3)
    106 #if __has_builtin(__builtin_memchr)
    107 __diagnose_as_builtin(__builtin_memchr, 1, 2, 3)
    108 #endif
    109 _FORTIFY_FN(memchr) void *memchr(const void * _FORTIFY_POS0 __d, int __c, size_t __n)
    110 {
    111 #if __has_builtin(__builtin___memchr_chk) && USE_NATIVE_CHK
    112 	return __builtin___memchr_chk(__d, __c, __n, __fh_bos(__d, 0));
    113 #else
    114 	__fh_size_t __b = __fh_bos(__d, 0);
    115 
    116 	if (__n > __b)
    117 		__builtin_trap();
    118 	return __builtin_memchr(__d, __c, __n);
    119 #endif
    120 }
    121 
    122 #if 0
    123 __fh_access(read_only, 1, 2)
    124 _FORTIFY_FN(strchr) char *strchr(const char * _FORTIFY_POS0 __s, int __c)
    125 {
    126 #if __has_builtin(__builtin___strchr_chk) && USE_NATIVE_CHK
    127 	return __builtin___strchr_chk(__s, __c, __fh_bos(__s, 0));
    128 #else
    129 	__fh_size_t __b = __fh_bos(__s, 0);
    130 
    131 	char* __r = __builtin_strchr(__s, __c);
    132 	if (__r - __s > __b)
    133 		__builtin_trap();
    134 	return __r;
    135 #endif
    136 }
    137 
    138 __fh_access(read_only, 1, 2)
    139 _FORTIFY_FN(strrchr) char *strrchr(const char * _FORTIFY_POS0 __s, int __c)
    140 {
    141 #if __has_builtin(__builtin___strrchr_chk) && USE_NATIVE_CHK
    142 	return __builtin___strrchr_chk(__s, __c, __fh_bos(__s, 0));
    143 #else
    144 	__fh_size_t __b = __fh_bos(__s, 0);
    145 
    146 	char* __r = __builtin_strrchr(__s, __c);
    147 	if (__r - __s > __b)
    148 		__builtin_trap();
    149 	return __r;
    150 #endif
    151 }
    152 #endif
    153 
    154 #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
    155  || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
    156  || defined(_BSD_SOURCE)
    157 #undef stpcpy
    158 __fh_access(write_only, 1)
    159 __fh_access(read_only, 2)
    160 #if __has_builtin(__builtin_stpcpy)
    161 __diagnose_as_builtin(__builtin_stpcpy, 1, 2)
    162 #endif
    163 _FORTIFY_FN(stpcpy) char *stpcpy(char * _FORTIFY_POS0 __d, const char *__s)
    164 {
    165 #if __has_builtin(__builtin___stpcpy_chk) && USE_NATIVE_CHK
    166 	return __builtin___stpcpy_chk(__d, __s, __fh_bos(__d, 0));
    167 #else
    168 	__fh_size_t __n = strlen(__s) + 1;
    169 	__fh_size_t __b = __fh_bos(__d, 0);
    170 
    171 	if (__fh_overlap(__d, __b, __s, __n))
    172 		__builtin_trap();
    173 
    174 	if (__n > __b)
    175 		__builtin_trap();
    176 	return __orig_stpcpy(__d, __s);
    177 #endif
    178 }
    179 
    180 #undef stpncpy
    181 __fh_access(write_only, 1)
    182 __fh_access(read_only, 2, 3)
    183 #if __has_builtin(__builtin_stpncpy)
    184 __diagnose_as_builtin(__builtin_stpncpy, 1, 2, 3)
    185 #endif
    186 _FORTIFY_FN(stpncpy) char *stpncpy(char * _FORTIFY_POS0 __d, const char *__s,
    187                                    size_t __n)
    188 {
    189 #if __has_builtin(__builtin___stpncpy_chk) && USE_NATIVE_CHK
    190 	return __builtin___stpncpy_chk(__d, __s, __n, __fh_bos(__d, 0));
    191 #else
    192 	__fh_size_t max_len_s = strnlen(__s, __n);
    193 	if (__fh_overlap(__d, max_len_s, __s, max_len_s))
    194 		__builtin_trap();
    195 
    196 	// If the length strlen(src) is smaller than n, the remaining
    197 	// characters in the array pointed to by dest are filled with null
    198 	// bytes ('\0')
    199 	__fh_size_t __b = __fh_bos(__d, 0);
    200 	if (__n > __b)
    201 		__builtin_trap();
    202 
    203 	return __orig_stpncpy(__d, __s, __n);
    204 #endif
    205 }
    206 #endif
    207 
    208 __fh_access (read_write, 1)
    209 __fh_access (read_only, 2)
    210 #if __has_builtin(__builtin_strcat)
    211 __diagnose_as_builtin(__builtin_strcat, 1, 2)
    212 #endif
    213 _FORTIFY_FN(strcat) char *strcat(char * _FORTIFY_POS0 __d, const char *__s)
    214 {
    215 #if __has_builtin(__builtin___strcat_chk) && USE_NATIVE_CHK
    216 	return __builtin___strcat_chk(__d, __s, __fh_bos(__d, 0));
    217 #else
    218 	__fh_size_t __b = __fh_bos(__d, 0);
    219 
    220 	if (strlen(__s) + strlen(__d) + 1 > __b)
    221 		__builtin_trap();
    222 	return __orig_strcat(__d, __s);
    223 #endif
    224 }
    225 
    226 __fh_access (write_only, 1)
    227 __fh_access (read_only, 2)
    228 #if __has_builtin(__builtin_strcpy)
    229 __diagnose_as_builtin(__builtin_strcpy, 1, 2)
    230 #endif
    231 _FORTIFY_FN(strcpy) char *strcpy(char * _FORTIFY_POS0 __d, const char *__s)
    232 {
    233 #if __has_builtin(__builtin___strcpy_chk) && USE_NATIVE_CHK
    234 	return __builtin___strcpy_chk(__d, __s, __fh_bos(__d, 0));
    235 #else
    236 	__fh_size_t __n = strlen(__s) + 1;
    237 	__fh_size_t __b = __fh_bos(__d, 0);
    238 
    239 	if (__fh_overlap(__d, __b, __s, __n))
    240 		__builtin_trap();
    241 
    242 	if (__n > __b)
    243 		__builtin_trap();
    244 	return __orig_strcpy(__d, __s);
    245 #endif
    246 }
    247 
    248 __fh_access (read_only, 1)
    249 #if __has_builtin(__builtin_strlen)
    250 __diagnose_as_builtin(__builtin_strlen, 1)
    251 #endif
    252 _FORTIFY_FN(strlen) size_t strlen(const char * _FORTIFY_POS0 __s)
    253 {
    254 #if __has_builtin(__builtin___strlen_chk) && USE_NATIVE_CHK
    255 	return __builtin___strlen_chk(__s, __fh_bos(__s, 0));
    256 #else
    257 	__fh_size_t ret = __orig_strlen(__s);
    258 	if (ret > __fh_bos(__s, 0) - 1)
    259 		__builtin_trap();
    260 	return ret;
    261 #endif
    262 }
    263 
    264 __fh_access (read_write, 1)
    265 __fh_access (read_only, 2, 3)
    266 #if __has_builtin(__builtin_strncat)
    267 __diagnose_as_builtin(__builtin_strncat, 1, 2, 3)
    268 #endif
    269 _FORTIFY_FN(strncat) char *strncat(char * _FORTIFY_POS0 __d, const char *__s,
    270                                    size_t __n)
    271 {
    272 #if __has_builtin(__builtin___strncat_chk) && USE_NATIVE_CHK
    273 	return __builtin___strncat_chk(__d, __s, __n, __fh_bos(__d, 0));
    274 #else
    275 	__fh_size_t __b = __fh_bos(__d, 0);
    276 
    277 	if (__n > __b) {
    278 		__fh_size_t __sl = strnlen(__s, __n);
    279 		__fh_size_t __dl = strlen(__d);
    280 		if (__sl + __dl + 1 > __b)
    281 			__builtin_trap();
    282 	}
    283 	return __orig_strncat(__d, __s, __n);
    284 #endif
    285 }
    286 
    287 __fh_access (write_only, 1)
    288 __fh_access (read_only, 2, 3)
    289 #if __has_builtin(__builtin_strncpy)
    290 __diagnose_as_builtin(__builtin_strncpy, 1, 2, 3)
    291 #endif
    292 _FORTIFY_FN(strncpy) char *strncpy(char * _FORTIFY_POS0 __d,
    293                                    const char *__s, size_t __n)
    294 {
    295 #if __has_builtin(__builtin___strncpy_chk) && USE_NATIVE_CHK
    296 	return __builtin___strncpy_chk(__d, __s, __n, __fh_bos(__d, 0));
    297 #else
    298 	__fh_size_t max_len_s = strnlen(__s, __n);
    299 	if (__fh_overlap(__d, max_len_s, __s, max_len_s))
    300 		__builtin_trap();
    301 
    302 	// If the length of src is less than n, strncpy() writes additional
    303 	// null bytes to dest to ensure that a total of n bytes are written.
    304 	__fh_size_t __b = __fh_bos(__d, 0);
    305 	if (__n > __b)
    306 		__builtin_trap();
    307 
    308 	return __orig_strncpy(__d, __s, __n);
    309 #endif
    310 }
    311 
    312 #ifdef _GNU_SOURCE
    313 #undef mempcpy
    314 __fh_access(write_only, 1)
    315 __fh_access(read_only, 2, 3)
    316 #if __has_builtin(__builtin_mempcpy)
    317 __diagnose_as_builtin(__builtin_mempcpy, 1, 2, 3)
    318 #endif
    319 _FORTIFY_FN(mempcpy) void *mempcpy(void * _FORTIFY_POS0 __d,
    320                                    const void * _FORTIFY_POS0 __s, size_t __n)
    321 {
    322 #if __has_builtin(__builtin___mempcpy_chk) && USE_NATIVE_CHK
    323 	return __builtin___mempcpy_chk(__d, __s, __n, __fh_bos(__d, 0));
    324 #else
    325 	__fh_size_t __bd = __fh_bos(__d, 0);
    326 	__fh_size_t __bs = __fh_bos(__s, 0);
    327 
    328 	if (__n > __bd || __n > __bs)
    329 		__builtin_trap();
    330 	return __orig_mempcpy(__d, __s, __n);
    331 #endif
    332 }
    333 #endif
    334 
    335 #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
    336 #undef strlcat
    337 #undef strlcpy
    338 __fh_access (read_write, 1)
    339 __fh_access (read_only, 2, 3)
    340 #if __has_builtin(__builtin_strlcat)
    341 __diagnose_as_builtin(__builtin_strlcat, 1, 2, 3)
    342 #endif
    343 _FORTIFY_FN(strlcat) size_t strlcat(char * _FORTIFY_POS0 __d,
    344                                     const char *__s, size_t __n)
    345 {
    346 #if __has_builtin(__builtin___strlcat_chk) && USE_NATIVE_CHK
    347 	return __builtin___strlcat_chk(__d, __s, __n, __fh_bos(__d, 0));
    348 #else
    349 	__fh_size_t __b = __fh_bos(__d, 0);
    350 
    351 	if (__n > __b)
    352 		__builtin_trap();
    353 	return __orig_strlcat(__d, __s, __n);
    354 #endif
    355 }
    356 
    357 __fh_access (write_only, 1)
    358 __fh_access (read_only, 2, 3)
    359 #if __has_builtin(__builtin_strlcpy)
    360 __diagnose_as_builtin(__builtin_strlcpy, 1, 2, 3)
    361 #endif
    362 _FORTIFY_FN(strlcpy) size_t strlcpy(char * _FORTIFY_POS0 __d,
    363                                     const char *__s, size_t __n)
    364 {
    365 #if __has_builtin(__builtin___strlcpy_chk) && USE_NATIVE_CHK
    366 	return __builtin___strlcpy_chk(__d, __s, __n, __fh_bos(__d, 0));
    367 #else
    368 	__fh_size_t __b = __fh_bos(__d, 0);
    369 
    370 	if (__n > __b)
    371 		__builtin_trap();
    372 	return __orig_strlcpy(__d, __s, __n);
    373 #endif
    374 }
    375 #endif
    376 
    377 #ifdef __cplusplus
    378 }
    379 #endif
    380 
    381 #endif
    382 
    383 #endif