1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef _STDIO_H
17 #error "Never include this file directly; instead, include <stdio.h>"
18 #endif
19
20 #include <stdarg.h>
21 #include "fortify.h"
22
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26
27 #if defined(__FORTIFY_COMPILATION)
28
29 #define FORMAT_PLACE_2 (2)
30 #define FORMAT_PLACE_3 (3)
31 #define VALIST_PLACE_0 (0)
32 #define VALIST_PLACE_3 (3)
33 #define VALIST_PLACE_4 (4)
34
35 size_t __fread_chk(void*, size_t, size_t, FILE*, size_t);
36 size_t __fwrite_chk(const void*, size_t, size_t, FILE*, size_t);
37 char* __fgets_chk(char*, int, FILE*, size_t);
38
39 __DIAGNOSE_FORTIFY_INLINE
fread(void * const __DIAGNOSE_PASS_OBJECT_SIZE0 buf,size_t size,size_t count,FILE * stream)40 size_t fread(void* const __DIAGNOSE_PASS_OBJECT_SIZE0 buf,
41 size_t size, size_t count, FILE* stream)
42 __DIAGNOSE_OVERLOAD
43 __DIAGNOSE_ERROR_IF(__DIAGNOSE_UNSAFE_CHK_MUL_OVERFLOW(size, count),
44 "in call to 'fread', size * count overflows")
45 __DIAGNOSE_ERROR_IF(__DIAGNOSE_UNEVALUATED_LT(__DIAGNOSE_BOS0(buf), size * count),
46 "in call to 'fread', size * count is too large for the given buffer")
47 {
48 #ifdef __FORTIFY_RUNTIME
49 size_t bos = __DIAGNOSE_BOS0(buf);
50
51 if (!__DIAGNOSE_BOS_TRIVIALLY_GE_MUL(bos, size, count)) {
52 return __fread_chk(buf, size, count, stream, bos);
53 }
54 #endif
55 return __DIAGNOSE_CALL_BYPASSING_FORTIFY(fread)(buf, size, count, stream);
56 }
57
58 __DIAGNOSE_FORTIFY_INLINE
fwrite(const void * const __DIAGNOSE_PASS_OBJECT_SIZE0 buf,size_t size,size_t count,FILE * stream)59 size_t fwrite(const void* const __DIAGNOSE_PASS_OBJECT_SIZE0 buf,
60 size_t size, size_t count, FILE* stream)
61 __DIAGNOSE_OVERLOAD
62 __DIAGNOSE_ERROR_IF(__DIAGNOSE_UNSAFE_CHK_MUL_OVERFLOW(size, count),
63 "in call to 'fwrite', size * count overflows")
64 __DIAGNOSE_ERROR_IF(__DIAGNOSE_UNEVALUATED_LT(__DIAGNOSE_BOS0(buf), size * count),
65 "in call to 'fwrite', size * count is too large for the given buffer")
66 {
67 #ifdef __FORTIFY_RUNTIME
68 size_t bos = __DIAGNOSE_BOS0(buf);
69
70 if (!__DIAGNOSE_BOS_TRIVIALLY_GE_MUL(bos, size, count)) {
71 return __fwrite_chk(buf, size, count, stream, bos);
72 }
73 #endif
74 return __DIAGNOSE_CALL_BYPASSING_FORTIFY(fwrite)(buf, size, count, stream);
75 }
76
77 __DIAGNOSE_FORTIFY_INLINE
fgets(char * const __DIAGNOSE_PASS_OBJECT_SIZE dest,int size,FILE * stream)78 char* fgets(char* const __DIAGNOSE_PASS_OBJECT_SIZE dest, int size, FILE* stream)
79 __DIAGNOSE_OVERLOAD
80 __DIAGNOSE_ERROR_IF(size < 0, "in call to 'fgets', size should not be less than 0")
81 __DIAGNOSE_ERROR_IF(__DIAGNOSE_UNEVALUATED_LT(__DIAGNOSE_BOS(dest), size),
82 "in call to 'fgets', " SIZE_LARGER_THEN_DESTINATION_BUFFER)
83 {
84 #ifdef __FORTIFY_RUNTIME
85 size_t bos = __DIAGNOSE_BOS(dest);
86
87 if (!__DIAGNOSE_BOS_DYNAMIC_CHECK_IMPL_AND(bos, >=, (size_t)size, size >= 0)) {
88 return __fgets_chk(dest, size, stream, bos);
89 }
90 #endif
91 return __DIAGNOSE_CALL_BYPASSING_FORTIFY(fgets)(dest, size, stream);
92 }
93
__DIAGNOSE_PRINTFLIKE(FORMAT_PLACE_3,VALIST_PLACE_0)94 __DIAGNOSE_FORTIFY_INLINE __DIAGNOSE_PRINTFLIKE(FORMAT_PLACE_3, VALIST_PLACE_0)
95 int vsnprintf(char* const __DIAGNOSE_PASS_OBJECT_SIZE dest,
96 size_t size, const char* format, va_list ap)
97 __DIAGNOSE_OVERLOAD
98 {
99 size_t bos = __DIAGNOSE_BOS(dest);
100 return __builtin___vsnprintf_chk(dest, size, 0, bos, format, ap);
101 }
102
__DIAGNOSE_PRINTFLIKE(FORMAT_PLACE_2,VALIST_PLACE_0)103 __DIAGNOSE_FORTIFY_INLINE __DIAGNOSE_PRINTFLIKE(FORMAT_PLACE_2, VALIST_PLACE_0)
104 int vsprintf(char* const __DIAGNOSE_PASS_OBJECT_SIZE dest, const char* format, va_list ap)
105 __DIAGNOSE_OVERLOAD
106 {
107 return __builtin___vsprintf_chk(dest, 0, __DIAGNOSE_BOS(dest), format, ap);
108 }
109
__DIAGNOSE_PRINTFLIKE(FORMAT_PLACE_2,VALIST_PLACE_3)110 __DIAGNOSE_FORTIFY_VARIADIC __DIAGNOSE_PRINTFLIKE(FORMAT_PLACE_2, VALIST_PLACE_3)
111 int sprintf(char* const __DIAGNOSE_PASS_OBJECT_SIZE dest, const char* format, ...)
112 __DIAGNOSE_OVERLOAD
113 {
114 va_list va_l;
115 va_start(va_l, format);
116 int result = __builtin___vsprintf_chk(dest, 0, __DIAGNOSE_BOS(dest), format, va_l);
117 va_end(va_l);
118 return result;
119 }
120
__DIAGNOSE_PRINTFLIKE(FORMAT_PLACE_3,VALIST_PLACE_4)121 __DIAGNOSE_FORTIFY_VARIADIC __DIAGNOSE_PRINTFLIKE(FORMAT_PLACE_3, VALIST_PLACE_4)
122 int snprintf(char* const __DIAGNOSE_PASS_OBJECT_SIZE dest, size_t size, const char* format, ...)
123 __DIAGNOSE_OVERLOAD
124 {
125 va_list va_l;
126 va_start(va_l, format);
127 int result = __builtin___vsnprintf_chk(dest, size, 0, __DIAGNOSE_BOS(dest), format, va_l);
128 va_end(va_l);
129 return result;
130 }
131
132 #endif // defined(__FORTIFY_COMPILATION)
133
134 #ifdef __cplusplus
135 }
136 #endif