fortify-headers

standalone fortify-source implementation
git clone git://git.2f30.org/fortify-headers
Log | Files | Refs | README | LICENSE

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