fortify-headers

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

string.h (11008B)


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