stdio.h (4380B)
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 fread 34 #undef fwrite 35 #undef vsprintf 36 #undef vsnprintf 37 #undef snprintf 38 #undef sprintf 39 40 __access(read_write, 1, 2) 41 __access(read_only, 3) 42 _FORTIFY_FN(fgets) char *fgets(char * _FORTIFY_POS0 __s, int __n, FILE *__f) 43 { 44 size_t __b = __bos(__s, 0); 45 46 if ((size_t)__n > __b) 47 __builtin_trap(); 48 return __orig_fgets(__s, __n, __f); 49 } 50 51 __access(write_only, 1) 52 __access(read_only, 4) 53 _FORTIFY_FN(fread) size_t fread(void * _FORTIFY_POS0 __d, size_t __n, 54 size_t __m, FILE *__f) 55 { 56 size_t __b = __bos(__d, 0); 57 58 if (__n != 0 && (__n * __m) / __n != __m) 59 __builtin_trap(); 60 if (__n * __m > __b) 61 __builtin_trap(); 62 return __orig_fread(__d, __n, __m, __f); 63 } 64 65 __access(read_only, 1) 66 __access(write_only, 4) 67 _FORTIFY_FN(fwrite) size_t fwrite(const void * _FORTIFY_POS0 __d, size_t __n, 68 size_t __m, FILE *__f) 69 { 70 size_t __b = __bos(__d, 0); 71 72 if (__n != 0 && (__n * __m) / __n != __m) 73 __builtin_trap(); 74 if (__n * __m > __b) 75 __builtin_trap(); 76 return __orig_fwrite(__d, __n, __m, __f); 77 } 78 79 __format(printf, 3, 0) 80 __access(write_only, 1, 2) 81 __access(read_only, 3) 82 _FORTIFY_FN(vsnprintf) int vsnprintf(char * _FORTIFY_POS0 __s, size_t __n, 83 const char *__f, __builtin_va_list __v) 84 { 85 size_t __b = __bos(__s, 0); 86 87 if (__n > __b) 88 __builtin_trap(); 89 return __orig_vsnprintf(__s, __n, __f, __v); 90 } 91 92 __format(printf, 2, 0) 93 __access(write_only, 1) 94 __access(read_only, 2) 95 _FORTIFY_FN(vsprintf) int vsprintf(char * _FORTIFY_POS0 __s, const char *__f, 96 __builtin_va_list __v) 97 { 98 size_t __b = __bos(__s, 0); 99 int __r; 100 101 if (__b != (size_t)-1) { 102 __r = __orig_vsnprintf(__s, __b, __f, __v); 103 if (__r != -1 && (size_t)__r >= __b) 104 __builtin_trap(); 105 } else { 106 __r = __orig_vsprintf(__s, __f, __v); 107 } 108 return __r; 109 } 110 111 #if defined(__has_builtin) 112 #if __has_builtin(__builtin_va_arg_pack) 113 114 /* clang is missing __builtin_va_arg_pack, so we cannot use these impls 115 * outside of gcc; we then have a few options: 116 * 117 * 1) using va_start/end and implementing these functions as static inline, 118 * with inlining never happening; that means extra symbols with internal 119 * linkage, which is not ideal 120 * 2) using macros; this is incompatible with c++ and since musl does not 121 * have the __chk variants, we'd need to implement a body with intermediate 122 * variables within the macro, which means more non-portable mess 123 * 3) not implementing these under clang, which is what we do for now 124 */ 125 126 __format(printf, 3, 4) 127 _FORTIFY_FN(snprintf) int snprintf(char *__s, size_t __n, 128 const char *__f, ...) 129 { 130 size_t __b = __bos(__s, 0); 131 132 if (__n > __b) 133 __builtin_trap(); 134 return __orig_snprintf(__s, __n, __f, __builtin_va_arg_pack()); 135 } 136 137 __format(printf, 2, 3) 138 _FORTIFY_FN(sprintf) int sprintf(char *__s, const char *__f, ...) 139 { 140 size_t __b = __bos(__s, 0); 141 int __r; 142 143 if (__b != (size_t)-1) { 144 __r = __orig_snprintf(__s, __b, __f, __builtin_va_arg_pack()); 145 if (__r != -1 && (size_t)__r >= __b) 146 __builtin_trap(); 147 } else { 148 __r = __orig_sprintf(__s, __f, __builtin_va_arg_pack()); 149 } 150 return __r; 151 } 152 153 #endif /* __has_builtin(__builtin_va_arg_pack) */ 154 #endif /* defined(__has_builtin) */ 155 156 #ifdef __cplusplus 157 } 158 #endif 159 160 #endif 161 162 #endif