stdio.h (9099B)
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(read_write, 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) && 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(read_write, 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) && 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) && 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) && USE_NATIVE_CHK 218 return __builtin___vprintf_chk(_FORTIFY_SOURCE, __f, __v); 219 #else 220 return __orig_vprintf(__f, __v); 221 #endif 222 } 223 #endif // __clang__ 224 225 226 #if __has_builtin(__builtin_va_arg_pack) 227 228 /* clang is missing __builtin_va_arg_pack, so we cannot use these impls 229 * outside of gcc; we then have a few options: 230 * 231 * 1) using va_start/end and implementing these functions as static inline, 232 * with inlining never happening; that means extra symbols with internal 233 * linkage, which is not ideal 234 * 2) using macros; this is incompatible with c++ and since musl does not 235 * have the __chk variants, we'd need to implement a body with intermediate 236 * variables within the macro, which means more non-portable mess 237 * 3) not implementing these under clang, which is what we do for now 238 * 239 * TODO: add __diagnose_as_builtin 240 */ 241 242 // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110834 243 #pragma GCC diagnostic push 244 #pragma GCC diagnostic ignored "-Wformat-nonliteral" 245 246 #undef snprintf 247 #undef sprintf 248 #undef printf 249 #undef fprintf 250 251 __fh_access(read_write, 1, 2) 252 __fh_access(read_only, 3) 253 __fh_format(printf, 3, 4) 254 _FORTIFY_FN(snprintf) int snprintf(char *__s, size_t __n, 255 const char *__f, ...) 256 { 257 #if __has_builtin(__builtin___snprintf_chk) && USE_NATIVE_CHK 258 return __builtin___snprintf_chk(__s, __n, _FORTIFY_SOURCE, __fh_bos(__s, 0), __f, __builtin_va_arg_pack()); 259 #else 260 __fh_size_t __b = __fh_bos(__s, 0); 261 262 if (__n > __b) 263 __builtin_trap(); 264 return __orig_snprintf(__s, __n, __f, __builtin_va_arg_pack()); 265 #endif 266 } 267 268 __fh_format(printf, 2, 3) 269 __fh_access(read_write, 1) 270 __fh_access(read_only, 2) 271 _FORTIFY_FN(sprintf) int sprintf(char *__s, const char *__f, ...) 272 { 273 #if __has_builtin(__builtin___sprintf_chk) && USE_NATIVE_CHK 274 return __builtin___sprintf_chk(__s, _FORTIFY_SOURCE, __fh_bos(__s, 0), __f, __builtin_va_arg_pack()); 275 #else 276 __fh_size_t __b = __fh_bos(__s, 0); 277 int __r; 278 279 if (__b != (__fh_size_t)-1) { 280 __r = __orig_snprintf(__s, __b, __f, __builtin_va_arg_pack()); 281 if (__r != -1 && (__fh_size_t)__r >= __b) 282 __builtin_trap(); 283 } else { 284 __r = __orig_sprintf(__s, __f, __builtin_va_arg_pack()); 285 } 286 return __r; 287 #endif 288 } 289 290 __fh_format(printf, 1, 2) 291 __fh_access(read_only, 1) 292 _FORTIFY_FN(printf) int printf(const char *__f, ...) 293 { 294 #if __has_builtin(__builtin___printf_chk) && USE_NATIVE_CHK 295 return __builtin___printf_chk(_FORTIFY_SOURCE, __f, __builtin_va_arg_pack()); 296 #else 297 return __orig_printf(__f, __builtin_va_arg_pack()); 298 #endif 299 } 300 301 __fh_access(read_only, 2) 302 __fh_format(printf, 2, 0) 303 #if __has_builtin(__builtin_fprintf) 304 __diagnose_as_builtin(__builtin_fprintf, 2, 3) 305 #endif 306 _FORTIFY_FN(fprintf) int fprintf(FILE *__s, const char *__f, ...) 307 { 308 #if __has_builtin(__builtin___fprintf_chk) && USE_NATIVE_CHK 309 return __builtin___fprintf_chk(_FORTIFY_SOURCE, __s, __f, __builtin_va_arg_pack()); 310 #else 311 return __orig_fprintf(__s, __f, __builtin_va_arg_pack()); 312 #endif 313 } 314 315 #pragma GCC diagnostic pop 316 #endif /* __has_builtin(__builtin_va_arg_pack) */ 317 318 #ifdef __cplusplus 319 } 320 #endif 321 322 #endif 323 324 #endif