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