string.h (11015B)
1 /* 2 * Copyright (C) 2015-2016 Dimitris Papastamos <[email protected]> 3 * Copyright (C) 2022 q66 <[email protected]> 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