Line data Source code
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 1 : if ((__fh_size_t)__n > __b)
87 2 : __builtin_trap();
88 0 : 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 1 : if (__bmo(__n, __m))
112 1 : __builtin_trap();
113 1 : if (__n * __m > __b)
114 2 : __builtin_trap();
115 0 : 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 1 : if (__bmo(__n, __m))
128 1 : __builtin_trap();
129 1 : if (__n * __m > __b)
130 2 : __builtin_trap();
131 0 : 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 4 : if (__n > __b)
161 2 : __builtin_trap();
162 2 : 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 2 : __r = __orig_vsnprintf(__s, __b, __f, __v);
183 2 : if (__r != -1 && (__fh_size_t)__r >= __b)
184 1 : __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 1 : 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 1 : 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 2 : int ret = __orig_vasprintf(strp, fmt, ap);
235 2 : if (ret < 0)
236 1 : *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
|