fortify-headers

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

string.h (10934B)


      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 	if (!__od || !__os)
     55       		__builtin_trap();
     56 
     57 	__fh_size_t __bd = __fh_bos(__od, 0);
     58 	__fh_size_t __bs = __fh_bos(__os, 0);
     59 	char *__d = (char *)__od;
     60 	const char *__s = (const char *)__os;
     61 
     62 	if __fh_overlap(__d, __bd, __s, __n)
     63 		__builtin_trap();
     64 	if (__n > __bd || __n > __bs)
     65 		__builtin_trap();
     66 	return __builtin_memcpy(__od, __os, __n);
     67 #endif
     68 }
     69 
     70 __fh_access(write_only, 1, 3)
     71 __fh_access(read_only, 2, 3)
     72 #if __has_builtin(__builtin_memmove)
     73 __diagnose_as_builtin(__builtin_memmove, 1, 2, 3)
     74 #endif
     75 _FORTIFY_FN(memmove) void *memmove(void * _FORTIFY_POS0 __d,
     76                                    const void * _FORTIFY_POS0 __s, size_t __n)
     77 {
     78 #if __has_builtin(__builtin___memmove_chk) && USE_NATIVE_CHK
     79 	return __builtin___memmove_chk(__d, __s, __n, __fh_bos(__d, 0));
     80 #else
     81 	if (!__d || !__s)
     82 		__builtin_trap();
     83 
     84 	__fh_size_t __bd = __fh_bos(__d, 0);
     85 	__fh_size_t __bs = __fh_bos(__s, 0);
     86 
     87 	if (__n > __bd || __n > __bs)
     88 		__builtin_trap();
     89 	return __orig_memmove(__d, __s, __n);
     90 #endif
     91 }
     92 
     93 __fh_access(write_only, 1, 3)
     94 #if __has_builtin(__builtin_memset)
     95 __diagnose_as_builtin(__builtin_memset, 1, 2, 3)
     96 #endif
     97 _FORTIFY_FN(memset) void *memset(void * _FORTIFY_POS0 __d, int __c, size_t __n)
     98 __warning_if(__c != 0 && __n == 0, "'memset' will set `0` bytes; did you invert the arguments?")
     99 {
    100 #if __has_builtin(__builtin___memset_chk) && USE_NATIVE_CHK
    101 	return __builtin___memset_chk(__d, __c, __n, __fh_bos(__d, 0));
    102 #else
    103 	if (!__d)
    104 		__builtin_trap();
    105 
    106 	__fh_size_t __b = __fh_bos(__d, 0);
    107 
    108 	if (__n > __b)
    109 		__builtin_trap();
    110 	return __builtin_memset(__d, __c, __n);
    111 #endif
    112 }
    113 
    114 __fh_access(read_only, 1, 3)
    115 #if __has_builtin(__builtin_memchr)
    116 __diagnose_as_builtin(__builtin_memchr, 1, 2, 3)
    117 #endif
    118 _FORTIFY_FN(memchr) void *memchr(const void * _FORTIFY_POS0 __d, int __c, size_t __n)
    119 {
    120 #if __has_builtin(__builtin___memchr_chk) && USE_NATIVE_CHK
    121 	return __builtin___memchr_chk(__d, __c, __n, __fh_bos(__d, 0));
    122 #else
    123 	if (!__d)
    124 		__builtin_trap();
    125 
    126 #if __STDC_VERSION__ < 201112L
    127 	__fh_size_t __b = __fh_bos(__d, 0);
    128 	if (__n > __b)
    129 		__builtin_trap();
    130 #endif
    131 
    132 	return __builtin_memchr(__d, __c, __n);
    133 #endif
    134 }
    135 
    136 #if 0
    137 __fh_access(read_only, 1, 2)
    138 _FORTIFY_FN(strchr) char *strchr(const char * _FORTIFY_POS0 __s, int __c)
    139 {
    140 #if __has_builtin(__builtin___strchr_chk) && USE_NATIVE_CHK
    141 	return __builtin___strchr_chk(__s, __c, __fh_bos(__s, 0));
    142 #else
    143 	__fh_size_t __b = __fh_bos(__s, 0);
    144 
    145 	char* __r = __builtin_strchr(__s, __c);
    146 	if (__r - __s > __b)
    147 		__builtin_trap();
    148 	return __r;
    149 #endif
    150 }
    151 
    152 __fh_access(read_only, 1, 2)
    153 _FORTIFY_FN(strrchr) char *strrchr(const char * _FORTIFY_POS0 __s, int __c)
    154 {
    155 #if __has_builtin(__builtin___strrchr_chk) && USE_NATIVE_CHK
    156 	return __builtin___strrchr_chk(__s, __c, __fh_bos(__s, 0));
    157 #else
    158 	__fh_size_t __b = __fh_bos(__s, 0);
    159 
    160 	char* __r = __builtin_strrchr(__s, __c);
    161 	if (__r - __s > __b)
    162 		__builtin_trap();
    163 	return __r;
    164 #endif
    165 }
    166 #endif
    167 
    168 #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
    169  || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
    170  || defined(_BSD_SOURCE)
    171 #undef stpcpy
    172 __fh_access(write_only, 1)
    173 __fh_access(read_only, 2)
    174 #if __has_builtin(__builtin_stpcpy)
    175 __diagnose_as_builtin(__builtin_stpcpy, 1, 2)
    176 #endif
    177 _FORTIFY_FN(stpcpy) char *stpcpy(char * _FORTIFY_POS0 __d, const char *__s)
    178 {
    179 #if __has_builtin(__builtin___stpcpy_chk) && USE_NATIVE_CHK
    180 	return __builtin___stpcpy_chk(__d, __s, __fh_bos(__d, 0));
    181 #else
    182 	__fh_size_t __n = strlen(__s) + 1;
    183 	__fh_size_t __b = __fh_bos(__d, 0);
    184 
    185 	if (__fh_overlap(__d, __b, __s, __n))
    186 		__builtin_trap();
    187 
    188 	if (__n > __b)
    189 		__builtin_trap();
    190 	return __orig_stpcpy(__d, __s);
    191 #endif
    192 }
    193 
    194 #undef stpncpy
    195 __fh_access(write_only, 1)
    196 __fh_access(read_only, 2, 3)
    197 #if __has_builtin(__builtin_stpncpy)
    198 __diagnose_as_builtin(__builtin_stpncpy, 1, 2, 3)
    199 #endif
    200 _FORTIFY_FN(stpncpy) char *stpncpy(char * _FORTIFY_POS0 __d, const char *__s,
    201                                    size_t __n)
    202 {
    203 #if __has_builtin(__builtin___stpncpy_chk) && USE_NATIVE_CHK
    204 	return __builtin___stpncpy_chk(__d, __s, __n, __fh_bos(__d, 0));
    205 #else
    206 	__fh_size_t max_len_s = strnlen(__s, __n);
    207 	if (__fh_overlap(__d, max_len_s, __s, max_len_s))
    208 		__builtin_trap();
    209 
    210 	// If the length strlen(src) is smaller than n, the remaining
    211 	// characters in the array pointed to by dest are filled with null
    212 	// bytes ('\0')
    213 	__fh_size_t __b = __fh_bos(__d, 0);
    214 	if (__n > __b)
    215 		__builtin_trap();
    216 
    217 	return __orig_stpncpy(__d, __s, __n);
    218 #endif
    219 }
    220 #endif
    221 
    222 __fh_access (read_write, 1)
    223 __fh_access (read_only, 2)
    224 #if __has_builtin(__builtin_strcat)
    225 __diagnose_as_builtin(__builtin_strcat, 1, 2)
    226 #endif
    227 _FORTIFY_FN(strcat) char *strcat(char * _FORTIFY_POS0 __d, const char *__s)
    228 {
    229 #if __has_builtin(__builtin___strcat_chk) && USE_NATIVE_CHK
    230 	return __builtin___strcat_chk(__d, __s, __fh_bos(__d, 0));
    231 #else
    232 	__fh_size_t __b = __fh_bos(__d, 0);
    233 
    234 	if (strlen(__s) + strlen(__d) + 1 > __b)
    235 		__builtin_trap();
    236 	return __orig_strcat(__d, __s);
    237 #endif
    238 }
    239 
    240 __fh_access (write_only, 1)
    241 __fh_access (read_only, 2)
    242 #if __has_builtin(__builtin_strcpy)
    243 __diagnose_as_builtin(__builtin_strcpy, 1, 2)
    244 #endif
    245 _FORTIFY_FN(strcpy) char *strcpy(char * _FORTIFY_POS0 __d, const char *__s)
    246 {
    247 #if __has_builtin(__builtin___strcpy_chk) && USE_NATIVE_CHK
    248 	return __builtin___strcpy_chk(__d, __s, __fh_bos(__d, 0));
    249 #else
    250 	__fh_size_t __n = strlen(__s) + 1;
    251 	__fh_size_t __b = __fh_bos(__d, 0);
    252 
    253 	if (__fh_overlap(__d, __b, __s, __n))
    254 		__builtin_trap();
    255 
    256 	if (__n > __b)
    257 		__builtin_trap();
    258 	return __orig_strcpy(__d, __s);
    259 #endif
    260 }
    261 
    262 __fh_access (read_only, 1)
    263 #if __has_builtin(__builtin_strlen)
    264 __diagnose_as_builtin(__builtin_strlen, 1)
    265 #endif
    266 _FORTIFY_FN(strlen) size_t strlen(const char * _FORTIFY_POS0 __s)
    267 {
    268 #if __has_builtin(__builtin___strlen_chk) && USE_NATIVE_CHK
    269 	return __builtin___strlen_chk(__s, __fh_bos(__s, 0));
    270 #else
    271 	__fh_size_t ret = __orig_strlen(__s);
    272 	if (ret > __fh_bos(__s, 0) - 1)
    273 		__builtin_trap();
    274 	return ret;
    275 #endif
    276 }
    277 
    278 __fh_access (read_write, 1)
    279 __fh_access (read_only, 2, 3)
    280 #if __has_builtin(__builtin_strncat)
    281 __diagnose_as_builtin(__builtin_strncat, 1, 2, 3)
    282 #endif
    283 _FORTIFY_FN(strncat) char *strncat(char * _FORTIFY_POS0 __d, const char *__s,
    284                                    size_t __n)
    285 {
    286 #if __has_builtin(__builtin___strncat_chk) && USE_NATIVE_CHK
    287 	return __builtin___strncat_chk(__d, __s, __n, __fh_bos(__d, 0));
    288 #else
    289 	__fh_size_t __b = __fh_bos(__d, 0);
    290 
    291 	if (__n > __b) {
    292 		__fh_size_t __sl = strnlen(__s, __n);
    293 		__fh_size_t __dl = strlen(__d);
    294 		if (__sl + __dl + 1 > __b)
    295 			__builtin_trap();
    296 	}
    297 	return __orig_strncat(__d, __s, __n);
    298 #endif
    299 }
    300 
    301 __fh_access (write_only, 1)
    302 __fh_access (read_only, 2, 3)
    303 #if __has_builtin(__builtin_strncpy)
    304 __diagnose_as_builtin(__builtin_strncpy, 1, 2, 3)
    305 #endif
    306 _FORTIFY_FN(strncpy) char *strncpy(char * _FORTIFY_POS0 __d,
    307                                    const char *__s, size_t __n)
    308 {
    309 #if __has_builtin(__builtin___strncpy_chk) && USE_NATIVE_CHK
    310 	return __builtin___strncpy_chk(__d, __s, __n, __fh_bos(__d, 0));
    311 #else
    312 	__fh_size_t max_len_s = strnlen(__s, __n);
    313 	if (__fh_overlap(__d, max_len_s, __s, max_len_s))
    314 		__builtin_trap();
    315 
    316 	// If the length of src is less than n, strncpy() writes additional
    317 	// null bytes to dest to ensure that a total of n bytes are written.
    318 	__fh_size_t __b = __fh_bos(__d, 0);
    319 	if (__n > __b)
    320 		__builtin_trap();
    321 
    322 	return __orig_strncpy(__d, __s, __n);
    323 #endif
    324 }
    325 
    326 #ifdef _GNU_SOURCE
    327 #undef mempcpy
    328 __fh_access(write_only, 1)
    329 __fh_access(read_only, 2, 3)
    330 #if __has_builtin(__builtin_mempcpy)
    331 __diagnose_as_builtin(__builtin_mempcpy, 1, 2, 3)
    332 #endif
    333 _FORTIFY_FN(mempcpy) void *mempcpy(void * _FORTIFY_POS0 __d,
    334                                    const void * _FORTIFY_POS0 __s, size_t __n)
    335 {
    336 #if __has_builtin(__builtin___mempcpy_chk) && USE_NATIVE_CHK
    337 	return __builtin___mempcpy_chk(__d, __s, __n, __fh_bos(__d, 0));
    338 #else
    339 	if (!__d || !__s)
    340 		__builtin_trap();
    341 
    342 	__fh_size_t __bd = __fh_bos(__d, 0);
    343 	__fh_size_t __bs = __fh_bos(__s, 0);
    344 
    345 	if (__n > __bd || __n > __bs)
    346 		__builtin_trap();
    347 	return __orig_mempcpy(__d, __s, __n);
    348 #endif
    349 }
    350 #endif
    351 
    352 #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
    353 #undef strlcat
    354 #undef strlcpy
    355 __fh_access (read_write, 1)
    356 __fh_access (read_only, 2, 3)
    357 #if __has_builtin(__builtin_strlcat)
    358 __diagnose_as_builtin(__builtin_strlcat, 1, 2, 3)
    359 #endif
    360 _FORTIFY_FN(strlcat) size_t strlcat(char * _FORTIFY_POS0 __d,
    361                                     const char *__s, size_t __n)
    362 {
    363 #if __has_builtin(__builtin___strlcat_chk) && USE_NATIVE_CHK
    364 	return __builtin___strlcat_chk(__d, __s, __n, __fh_bos(__d, 0));
    365 #else
    366 	__fh_size_t __b = __fh_bos(__d, 0);
    367 
    368 	if (__n > __b)
    369 		__builtin_trap();
    370 	return __orig_strlcat(__d, __s, __n);
    371 #endif
    372 }
    373 
    374 __fh_access (write_only, 1)
    375 __fh_access (read_only, 2, 3)
    376 #if __has_builtin(__builtin_strlcpy)
    377 __diagnose_as_builtin(__builtin_strlcpy, 1, 2, 3)
    378 #endif
    379 _FORTIFY_FN(strlcpy) size_t strlcpy(char * _FORTIFY_POS0 __d,
    380                                     const char *__s, size_t __n)
    381 {
    382 #if __has_builtin(__builtin___strlcpy_chk) && USE_NATIVE_CHK
    383 	return __builtin___strlcpy_chk(__d, __s, __n, __fh_bos(__d, 0));
    384 #else
    385 	__fh_size_t __b = __fh_bos(__d, 0);
    386 
    387 	if (__n > __b)
    388 		__builtin_trap();
    389 	return __orig_strlcpy(__d, __s, __n);
    390 #endif
    391 }
    392 #endif
    393 
    394 #ifdef __cplusplus
    395 }
    396 #endif
    397 
    398 #endif
    399 
    400 #endif