fortify-headers

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

string.h (11015B)


      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) && FORTIFY_USE_NATIVE_CHK
     52 	return __builtin___memcpy_chk(__od, __os, __n, __fh_bos(__od, 0));
     53 #else
     54 #if defined FORTIFY_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) && FORTIFY_USE_NATIVE_CHK
     79 	return __builtin___memmove_chk(__d, __s, __n, __fh_bos(__d, 0));
     80 #else
     81 #if defined FORTIFY_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) && FORTIFY_USE_NATIVE_CHK
    103 	return __builtin___memset_chk(__d, __c, __n, __fh_bos(__d, 0));
    104 #else
    105 #if defined FORTIFY_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) && FORTIFY_USE_NATIVE_CHK
    125 	return __builtin___memchr_chk(__d, __c, __n, __fh_bos(__d, 0));
    126 #else
    127 #if defined FORTIFY_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) && FORTIFY_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) && FORTIFY_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) && FORTIFY_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)
    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) && FORTIFY_USE_NATIVE_CHK
    209 	return __builtin___stpncpy_chk(__d, __s, __n, __fh_bos(__d, 0));
    210 #else
    211 	// If the length strlen(src) is smaller than n, the remaining
    212 	// characters in the array pointed to by dest are filled with null
    213 	// bytes ('\0')
    214 	__fh_size_t __b = __fh_bos(__d, 0);
    215 	if (__n > __b)
    216 		__builtin_trap();
    217 
    218 	return __orig_stpncpy(__d, __s, __n);
    219 #endif
    220 }
    221 #endif
    222 
    223 __fh_access (read_write, 1)
    224 __fh_access (read_only, 2)
    225 #if __has_builtin(__builtin_strcat)
    226 __diagnose_as_builtin(__builtin_strcat, 1, 2)
    227 #endif
    228 _FORTIFY_FN(strcat) char *strcat(char * _FORTIFY_POS0 __d, const char *__s)
    229 {
    230 #if __has_builtin(__builtin___strcat_chk) && FORTIFY_USE_NATIVE_CHK
    231 	return __builtin___strcat_chk(__d, __s, __fh_bos(__d, 0));
    232 #else
    233 	__fh_size_t __b = __fh_bos(__d, 0);
    234 
    235 	if (strlen(__s) + strlen(__d) + 1 > __b)
    236 		__builtin_trap();
    237 	return __orig_strcat(__d, __s);
    238 #endif
    239 }
    240 
    241 __fh_access (write_only, 1)
    242 __fh_access (read_only, 2)
    243 #if __has_builtin(__builtin_strcpy)
    244 __diagnose_as_builtin(__builtin_strcpy, 1, 2)
    245 #endif
    246 _FORTIFY_FN(strcpy) char *strcpy(char * _FORTIFY_POS0 __d, const char *__s)
    247 {
    248 #if __has_builtin(__builtin___strcpy_chk) && FORTIFY_USE_NATIVE_CHK
    249 	return __builtin___strcpy_chk(__d, __s, __fh_bos(__d, 0));
    250 #else
    251 	__fh_size_t __n = strlen(__s) + 1;
    252 	__fh_size_t __b = __fh_bos(__d, 0);
    253 
    254 	if (__fh_overlap(__d, __n, __s, __n))
    255 		__builtin_trap();
    256 
    257 	if (__n > __b)
    258 		__builtin_trap();
    259 	return __orig_strcpy(__d, __s);
    260 #endif
    261 }
    262 
    263 __fh_access (read_only, 1)
    264 #if __has_builtin(__builtin_strlen)
    265 __diagnose_as_builtin(__builtin_strlen, 1)
    266 #endif
    267 _FORTIFY_FN(strlen) size_t strlen(const char * _FORTIFY_POS0 __s)
    268 {
    269 #if __has_builtin(__builtin___strlen_chk) && FORTIFY_USE_NATIVE_CHK
    270 	return __builtin___strlen_chk(__s, __fh_bos(__s, 0));
    271 #else
    272 	__fh_size_t ret = __orig_strlen(__s);
    273 	if (ret > __fh_bos(__s, 0) - 1)
    274 		__builtin_trap();
    275 	return ret;
    276 #endif
    277 }
    278 
    279 __fh_access (read_write, 1)
    280 __fh_access (read_only, 2, 3)
    281 #if __has_builtin(__builtin_strncat)
    282 __diagnose_as_builtin(__builtin_strncat, 1, 2, 3)
    283 #endif
    284 _FORTIFY_FN(strncat) char *strncat(char * _FORTIFY_POS0 __d, const char *__s,
    285                                    size_t __n)
    286 {
    287 #if __has_builtin(__builtin___strncat_chk) && FORTIFY_USE_NATIVE_CHK
    288 	return __builtin___strncat_chk(__d, __s, __n, __fh_bos(__d, 0));
    289 #else
    290 #if 0 // strlen(__s) isn't guaranteed to be valid.
    291 	__fh_size_t __b = __fh_bos(__d, 0);
    292 
    293 	if (__n > __b) {
    294 		__fh_size_t __sl = strlen(__s);
    295 		if (__sl > __n)
    296 			__sl = __n;
    297 		__fh_size_t __dl = strlen(__d);
    298 		if (__sl + __dl + 1 > __b)
    299 			__builtin_trap();
    300 	}
    301 #endif
    302 	return __orig_strncat(__d, __s, __n);
    303 #endif
    304 }
    305 
    306 __fh_access (write_only, 1)
    307 __fh_access (read_only, 2)
    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) && FORTIFY_USE_NATIVE_CHK
    315 	return __builtin___strncpy_chk(__d, __s, __n, __fh_bos(__d, 0));
    316 #else
    317 	// If the length of src is less than n, strncpy() writes additional
    318 	// null bytes to dest to ensure that a total of n bytes are written.
    319 	__fh_size_t __b = __fh_bos(__d, 0);
    320 	if (__n > __b)
    321 		__builtin_trap();
    322 
    323 	return __orig_strncpy(__d, __s, __n);
    324 #endif
    325 }
    326 
    327 #ifdef _GNU_SOURCE
    328 #undef mempcpy
    329 __fh_access(write_only, 1)
    330 __fh_access(read_only, 2, 3)
    331 #if __has_builtin(__builtin_mempcpy)
    332 __diagnose_as_builtin(__builtin_mempcpy, 1, 2, 3)
    333 #endif
    334 _FORTIFY_FN(mempcpy) void *mempcpy(void * _FORTIFY_POS0 __d,
    335                                    const void * _FORTIFY_POS0 __s, size_t __n)
    336 {
    337 #if __has_builtin(__builtin___mempcpy_chk) && FORTIFY_USE_NATIVE_CHK
    338 	return __builtin___mempcpy_chk(__d, __s, __n, __fh_bos(__d, 0));
    339 #else
    340 	if (!__d || !__s)
    341 		__builtin_trap();
    342 
    343 	__fh_size_t __bd = __fh_bos(__d, 0);
    344 	__fh_size_t __bs = __fh_bos(__s, 0);
    345 
    346 	if (__n > __bd || __n > __bs)
    347 		__builtin_trap();
    348 	return __orig_mempcpy(__d, __s, __n);
    349 #endif
    350 }
    351 #endif
    352 
    353 #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
    354 #undef strlcat
    355 #undef strlcpy
    356 __fh_access (read_write, 1)
    357 __fh_access (read_only, 2, 3)
    358 #if __has_builtin(__builtin_strlcat)
    359 __diagnose_as_builtin(__builtin_strlcat, 1, 2, 3)
    360 #endif
    361 _FORTIFY_FN(strlcat) size_t strlcat(char * _FORTIFY_POS0 __d,
    362                                     const char *__s, size_t __n)
    363 {
    364 #if __has_builtin(__builtin___strlcat_chk) && FORTIFY_USE_NATIVE_CHK
    365 	return __builtin___strlcat_chk(__d, __s, __n, __fh_bos(__d, 0));
    366 #else
    367 	__fh_size_t __b = __fh_bos(__d, 0);
    368 
    369 	if (__n > __b)
    370 		__builtin_trap();
    371 	return __orig_strlcat(__d, __s, __n);
    372 #endif
    373 }
    374 
    375 __fh_access (write_only, 1)
    376 __fh_access (read_only, 2, 3)
    377 #if __has_builtin(__builtin_strlcpy)
    378 __diagnose_as_builtin(__builtin_strlcpy, 1, 2, 3)
    379 #endif
    380 _FORTIFY_FN(strlcpy) size_t strlcpy(char * _FORTIFY_POS0 __d,
    381                                     const char *__s, size_t __n)
    382 {
    383 #if __has_builtin(__builtin___strlcpy_chk) && FORTIFY_USE_NATIVE_CHK
    384 	return __builtin___strlcpy_chk(__d, __s, __n, __fh_bos(__d, 0));
    385 #else
    386 	__fh_size_t __b = __fh_bos(__d, 0);
    387 
    388 	if (__n > __b)
    389 		__builtin_trap();
    390 	return __orig_strlcpy(__d, __s, __n);
    391 #endif
    392 }
    393 #endif
    394 
    395 #ifdef __cplusplus
    396 }
    397 #endif
    398 
    399 #endif
    400 
    401 #endif