stdio.h (10325B)
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_STDIO_H 18 #define _FORTIFY_STDIO_H 19 20 #if !defined(__cplusplus) && !defined(__clang__) 21 __extension__ 22 #endif 23 #include_next <stdio.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 fgets 33 #undef fopen 34 #undef fread 35 #undef fwrite 36 #undef vsnprintf 37 #undef vsprintf 38 39 #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ 40 || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ 41 || defined(_BSD_SOURCE) 42 43 #undef fdopen 44 #undef fmemopen 45 #undef popen 46 47 __fh_access(read_only, 2) 48 #if __has_builtin(__builtin_fdopen) 49 __diagnose_as_builtin(__builtin_fdopen, 1, 2) 50 #endif 51 _FORTIFY_FN(fdopen) FILE *fdopen(int __f, const char* _FORTIFY_POS0 __m) 52 { 53 return __orig_fdopen(__f, __m); 54 } 55 56 __fh_malloc(malloc (fclose, 1)) 57 #if __has_builtin(__builtin_fmemopen) 58 __diagnose_as_builtin(__builtin_fmemopen, 1, 2, 3) 59 #endif 60 _FORTIFY_FN(fmemopen) FILE *fmemopen(void* _FORTIFY_POS0 __b, size_t __s, const char* _FORTIFY_POS0 __m) 61 { 62 return __orig_fmemopen(__b, __s, __m); 63 } 64 65 __fh_access(read_only, 1) 66 __fh_access(read_only, 2) 67 __fh_malloc(malloc (pclose, 1)) 68 #if __has_builtin(__builtin_popen) 69 __diagnose_as_builtin(__builtin_popen, 1, 2) 70 #endif 71 _FORTIFY_FN(popen) FILE *popen(const char* _FORTIFY_POS0 __c, const char* _FORTIFY_POS0 __t) 72 { 73 return __orig_popen(__c, __t); 74 } 75 76 #endif /* _POSIX_SOURCE || _POSIX_C_SOURCE || _XOPEN_SOURCE || _GNU_SOURCE || _BSD_SOURCE */ 77 78 __fh_access(write_only, 1, 2) 79 #if __has_builtin(__builtin_fgets) 80 __diagnose_as_builtin(__builtin_fgets, 1, 2, 3) 81 #endif 82 _FORTIFY_FN(fgets) char *fgets(char * _FORTIFY_POS0 __s, int __n, FILE *__f) 83 { 84 __fh_size_t __b = __fh_bos(__s, 0); 85 86 if ((__fh_size_t)__n > __b) 87 __builtin_trap(); 88 return __orig_fgets(__s, __n, __f); 89 } 90 91 __fh_access(read_only, 1) 92 __fh_access(read_only, 2) 93 __fh_malloc(malloc (fclose, 1)) 94 #if __has_builtin(__builtin_fopen) 95 __diagnose_as_builtin(__builtin_fopen, 1, 2) 96 #endif 97 _FORTIFY_FN(fopen) FILE *fopen(const char* _FORTIFY_POS0 __p, const char* _FORTIFY_POS0 __m) 98 { 99 return __orig_fopen(__p, __m); 100 } 101 102 __fh_access(write_only, 1) 103 #if __has_builtin(__builtin_fread) 104 __diagnose_as_builtin(__builtin_fread, 1, 2, 3, 4) 105 #endif 106 _FORTIFY_FN(fread) size_t fread(void * _FORTIFY_POS0 __d, size_t __n, 107 size_t __m, FILE *__f) 108 { 109 __fh_size_t __b = __fh_bos(__d, 0); 110 111 if (__bmo(__n, __m)) 112 __builtin_trap(); 113 if (__n * __m > __b) 114 __builtin_trap(); 115 return __orig_fread(__d, __n, __m, __f); 116 } 117 118 __fh_access(read_only, 1) 119 #if __has_builtin(__builtin_fwrite) 120 __diagnose_as_builtin(__builtin_fwrite, 1, 2, 3, 4) 121 #endif 122 _FORTIFY_FN(fwrite) size_t fwrite(const void * _FORTIFY_POS0 __d, size_t __n, 123 size_t __m, FILE *__f) 124 { 125 __fh_size_t __b = __fh_bos(__d, 0); 126 127 if (__bmo(__n, __m)) 128 __builtin_trap(); 129 if (__n * __m > __b) 130 __builtin_trap(); 131 return __orig_fwrite(__d, __n, __m, __f); 132 } 133 134 #ifndef __clang__ /* FIXME */ 135 #undef tmpfile 136 __fh_malloc(malloc (fclose, 1)) 137 #if __has_builtin(__builtin_tmpfile) 138 __diagnose_as_builtin(__builtin_tmpfile) 139 #endif 140 _FORTIFY_FN(tmpfile) FILE *tmpfile(void) 141 { 142 return __orig_tmpfile(); 143 } 144 #endif 145 146 __fh_access(write_only, 1, 2) 147 __fh_access(read_only, 3) 148 __fh_format(printf, 3, 0) 149 #if __has_builtin(__builtin_vsnprintf) 150 __diagnose_as_builtin(__builtin_vsnprintf, 1, 2, 3, 4) 151 #endif 152 _FORTIFY_FN(vsnprintf) int vsnprintf(char * _FORTIFY_POS0 __s, size_t __n, 153 const char *__f, __builtin_va_list __v) 154 { 155 #if __has_builtin(__builtin___vsnprintf_chk) && FORTIFY_USE_NATIVE_CHK 156 return __builtin___vsnprintf_chk(__s, __n, _FORTIFY_SOURCE, __fh_bos(__s, 0), __f, __v); 157 #else 158 __fh_size_t __b = __fh_bos(__s, 0); 159 160 if (__n > __b) 161 __builtin_trap(); 162 return __orig_vsnprintf(__s, __n, __f, __v); 163 #endif 164 } 165 166 __fh_format(printf, 2, 0) 167 __fh_access(write_only, 1) 168 __fh_access(read_only, 2) 169 #if __has_builtin(__builtin_vsprintf) 170 __diagnose_as_builtin(__builtin_vsprintf, 1, 2, 3) 171 #endif 172 _FORTIFY_FN(vsprintf) int vsprintf(char * _FORTIFY_POS0 __s, const char *__f, 173 __builtin_va_list __v) 174 { 175 #if __has_builtin(__builtin___vsprintf_chk) && FORTIFY_USE_NATIVE_CHK 176 return __builtin___vsprintf_chk(__s, _FORTIFY_SOURCE, __fh_bos(__s, 0), __f, __v); 177 #else 178 __fh_size_t __b = __fh_bos(__s, 0); 179 int __r; 180 181 if (__b != (__fh_size_t)-1) { 182 __r = __orig_vsnprintf(__s, __b, __f, __v); 183 if (__r != -1 && (__fh_size_t)__r >= __b) 184 __builtin_trap(); 185 } else { 186 __r = __orig_vsprintf(__s, __f, __v); 187 } 188 return __r; 189 #endif 190 } 191 192 #ifndef __clang__ /* FIXME */ 193 #undef vfprintf 194 #undef vprintf 195 196 __fh_access(read_only, 2) 197 __fh_format(printf, 2, 0) 198 #if __has_builtin(__builtin_vfprintf) 199 __diagnose_as_builtin(__builtin_vfprintf, 2, 3) 200 #endif 201 _FORTIFY_FN(vfprintf) int vfprintf(FILE * __s, const char *__f, __builtin_va_list __v) 202 { 203 #if __has_builtin(__builtin___vfprintf_chk) && FORTIFY_USE_NATIVE_CHK 204 return __builtin___vfprintf_chk(__s, _FORTIFY_SOURCE, __f, __v); 205 #else 206 return __orig_vfprintf(__s, __f, __v); 207 #endif 208 } 209 210 __fh_access(read_only, 1) 211 __fh_format(printf, 1, 0) 212 #if __has_builtin(__builtin_vprintf) 213 __diagnose_as_builtin(__builtin_vprintf, 1, 2) 214 #endif 215 _FORTIFY_FN(vprintf) int vprintf(const char *__f, __builtin_va_list __v) 216 { 217 #if __has_builtin(__builtin___vprintf_chk) && FORTIFY_USE_NATIVE_CHK 218 return __builtin___vprintf_chk(_FORTIFY_SOURCE, __f, __v); 219 #else 220 return __orig_vprintf(__f, __v); 221 #endif 222 } 223 224 #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) 225 #undef vasprintf 226 #if __has_builtin(__builtin_vasprintf) 227 __diagnose_as_builtin(__builtin_vasprintf, 1, 2, 3) 228 #endif 229 _FORTIFY_FN(vasprintf) int vasprintf(char **strp, const char *fmt, __builtin_va_list ap) 230 { 231 #if __has_builtin(__builtin___vasprintf_chk) && FORTIFY_USE_NATIVE_CHK 232 return __builtin___vasprintf_chk(_FORTIFY_SOURCE, strp, fmt, ap); 233 #else 234 int ret = __orig_vasprintf(strp, fmt, ap); 235 if (ret < 0) 236 *strp = NULL; 237 return ret; 238 #endif 239 } 240 241 242 #endif // defined(_GNU_SOURCE) || defined(_BSD_SOURCE) 243 #endif // __clang__ 244 245 246 #if 0 247 #if __has_builtin(__builtin_va_arg_pack) 248 249 /* clang is missing __builtin_va_arg_pack, so we cannot use these impls 250 * outside of gcc; we then have a few options: 251 * 252 * 1) using va_start/end and implementing these functions as static inline, 253 * with inlining never happening; that means extra symbols with internal 254 * linkage, which is not ideal 255 * 2) using macros; this is incompatible with c++ and since musl does not 256 * have the __chk variants, we'd need to implement a body with intermediate 257 * variables within the macro, which means more non-portable mess 258 * 3) not implementing these under clang, which is what we do for now 259 * 260 * TODO: add __diagnose_as_builtin 261 */ 262 263 // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110834 264 #pragma GCC diagnostic push 265 #pragma GCC diagnostic ignored "-Wformat-nonliteral" 266 267 #undef snprintf 268 #undef sprintf 269 #undef printf 270 #undef fprintf 271 272 __fh_access(write_only, 1, 2) 273 __fh_access(read_only, 3) 274 __fh_format(printf, 3, 4) 275 _FORTIFY_FN(snprintf) int snprintf(char *__s, size_t __n, 276 const char *__f, ...) 277 { 278 #if __has_builtin(__builtin___snprintf_chk) && FORTIFY_USE_NATIVE_CHK 279 return __builtin___snprintf_chk(__s, __n, _FORTIFY_SOURCE, __fh_bos(__s, 0), __f, __builtin_va_arg_pack()); 280 #else 281 __fh_size_t __b = __fh_bos(__s, 0); 282 283 if (__n > __b) 284 __builtin_trap(); 285 return __orig_snprintf(__s, __n, __f, __builtin_va_arg_pack()); 286 #endif 287 } 288 289 __fh_format(printf, 2, 3) 290 //__fh_access(write_only, 1) 291 __fh_access(read_only, 2) 292 _FORTIFY_FN(sprintf) int sprintf(char *__s, const char *__f, ...) 293 { 294 #if __has_builtin(__builtin___sprintf_chk) && FORTIFY_USE_NATIVE_CHK 295 return __builtin___sprintf_chk(__s, _FORTIFY_SOURCE, __fh_bos(__s, 0), __f, __builtin_va_arg_pack()); 296 #else 297 __fh_size_t __b = __fh_bos(__s, 0); 298 int __r; 299 300 if (__b == (__fh_size_t)-1) { 301 return __orig_sprintf(__s, __f, __builtin_va_arg_pack()); 302 } 303 304 __r = __orig_snprintf(__s, __b, __f, __builtin_va_arg_pack()); 305 if (__r != -1 && (__fh_size_t)__r >= __b) 306 __builtin_trap(); 307 return __r; 308 #endif 309 } 310 311 __fh_format(printf, 1, 2) 312 __fh_access(read_only, 1) 313 _FORTIFY_FN(printf) int printf(const char *__f, ...) 314 { 315 #if __has_builtin(__builtin___printf_chk) && FORTIFY_USE_NATIVE_CHK 316 return __builtin___printf_chk(_FORTIFY_SOURCE, __f, __builtin_va_arg_pack()); 317 #else 318 return __orig_printf(__f, __builtin_va_arg_pack()); 319 #endif 320 } 321 322 __fh_access(read_only, 2) 323 __fh_format(printf, 2, 0) 324 #if __has_builtin(__builtin_fprintf) 325 __diagnose_as_builtin(__builtin_fprintf, 2, 3) 326 #endif 327 _FORTIFY_FN(fprintf) int fprintf(FILE *__s, const char *__f, ...) 328 { 329 #if __has_builtin(__builtin___fprintf_chk) && FORTIFY_USE_NATIVE_CHK 330 return __builtin___fprintf_chk(_FORTIFY_SOURCE, __s, __f, __builtin_va_arg_pack()); 331 #else 332 return __orig_fprintf(__s, __f, __builtin_va_arg_pack()); 333 #endif 334 } 335 336 #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) 337 #ifndef __clang__ 338 #undef asprintf 339 __fh_access(read_only, 2) 340 __fh_format(printf, 2, 0) 341 #if __has_builtin(__builtin_asprintf) 342 __diagnose_as_builtin(__builtin_asprintf, 2, 3) 343 #endif 344 _FORTIFY_FN(asprintf) int asprintf(char **strp, const char *fmt, ...) 345 { 346 #if __has_builtin(__builtin___asprintf_chk) && FORTIFY_USE_NATIVE_CHK 347 return __builtin___asprintf_chk(_FORTIFY_SOURCE, strp, fmt, __builtin_va_arg_pack()); 348 #else 349 int ret = __orig_asprintf(strp, fmt, __builtin_va_arg_pack()); 350 if (ret<0) 351 *strp = NULL; 352 return ret; 353 #endif 354 } 355 #endif // __clang__ 356 #endif 357 358 #pragma GCC diagnostic pop 359 #endif /* __has_builtin(__builtin_va_arg_pack) */ 360 #endif 361 362 #ifdef __cplusplus 363 } 364 #endif 365 366 #endif 367 368 #endif