stdio.h (4421B)
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 __fortify_access(write_only, 1, 2) 41 __fortify_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 __fortify_access(write_only, 1) 52 __fortify_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 __fortify_access(read_only, 1) 66 __fortify_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 __fortify__format(printf, 3, 0) 80 __fortify_access(write_only, 1, 2) 81 __fortify_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 __fortify__format(printf, 2, 0) 93 __fortify_access(write_only, 1) 94 __fortify_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, 2); 99 int __r; 100 101 if (__b) { 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 __fortify_has_builtin(__builtin_va_arg_pack) 112 113 /* clang is missing __builtin_va_arg_pack, so we cannot use these impls 114 * outside of gcc; we then have a few options: 115 * 116 * 1) using va_start/end and implementing these functions as static inline, 117 * with inlining never happening; that means extra symbols with internal 118 * linkage, which is not ideal 119 * 2) using macros; this is incompatible with c++ and since musl does not 120 * have the __chk variants, we'd need to implement a body with intermediate 121 * variables within the macro, which means more non-portable mess 122 * 3) not implementing these under clang, which is what we do for now 123 */ 124 125 __fortify__format(printf, 3, 4) 126 _FORTIFY_FN(snprintf) int snprintf(char *__s, size_t __n, 127 const char *__f, ...) 128 { 129 size_t __b = __bos(__s, 0); 130 131 if (__n > __b) 132 __builtin_trap(); 133 return __orig_snprintf(__s, __n, __f, __builtin_va_arg_pack()); 134 } 135 136 __fortify__format(printf, 2, 3) 137 _FORTIFY_FN(sprintf) int sprintf(char *__s, const char *__f, ...) 138 { 139 size_t __b = __bos(__s, 2); 140 int __r; 141 142 if (__b) { 143 __r = __orig_snprintf(__s, __b, __f, __builtin_va_arg_pack()); 144 if (__r != -1 && (size_t)__r >= __b) 145 __builtin_trap(); 146 } else { 147 __r = __orig_sprintf(__s, __f, __builtin_va_arg_pack()); 148 } 149 return __r; 150 } 151 152 #endif /* __fortify_has_builtin(__builtin_va_arg_pack) */ 153 154 #ifdef __cplusplus 155 } 156 #endif 157 158 #endif 159 160 #endif