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