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