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