blob: dce056a3144cd129501ceef6512a3a1c68c371ad [file] [log] [blame]
George Burgess IVb97049c2017-07-24 15:05:05 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#ifndef _STDIO_H_
30#error "Never include this file directly; instead, include <stdio.h>"
31#endif
32
33char* __fgets_chk(char*, int, FILE*, size_t) __INTRODUCED_IN(17);
34size_t __fread_chk(void* __restrict, size_t, size_t, FILE* __restrict, size_t)
35 __INTRODUCED_IN(24);
36size_t __fwrite_chk(const void* __restrict, size_t, size_t, FILE* __restrict, size_t)
37 __INTRODUCED_IN(24);
38
39#if defined(__BIONIC_FORTIFY) && !defined(__BIONIC_NO_STDIO_FORTIFY)
40
41#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
42__BIONIC_FORTIFY_INLINE __printflike(3, 0)
43int vsnprintf(char *const __pass_object_size dest, size_t size,
44 const char *_Nonnull format, __va_list ap) __overloadable {
45 return __builtin___vsnprintf_chk(dest, size, 0, __bos(dest), format, ap);
46}
47
48__BIONIC_FORTIFY_INLINE __printflike(2, 0)
49int vsprintf(char *const __pass_object_size dest, const char *_Nonnull format,
50 __va_list ap) __overloadable {
51 return __builtin___vsprintf_chk(dest, 0, __bos(dest), format, ap);
52}
53#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
54
55#if defined(__clang__)
56#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
57/*
58 * Simple case: `format` can't have format specifiers, so we can just compare
59 * its length to the length of `dest`
60 */
61__BIONIC_ERROR_FUNCTION_VISIBILITY
62int snprintf(char *__restrict dest, size_t size, const char *__restrict format)
63 __overloadable
64 __enable_if(__bos(dest) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
65 __bos(dest) < __builtin_strlen(format),
66 "format string will always overflow destination buffer")
67 __errorattr("format string will always overflow destination buffer");
68
69__BIONIC_FORTIFY_INLINE
70__printflike(3, 4)
71int snprintf(char *__restrict const __pass_object_size dest,
72 size_t size, const char *__restrict format, ...) __overloadable {
73 va_list va;
74 va_start(va, format);
75 int result = __builtin___vsnprintf_chk(dest, size, 0, __bos(dest), format, va);
76 va_end(va);
77 return result;
78}
79
80__BIONIC_ERROR_FUNCTION_VISIBILITY
81int sprintf(char *__restrict dest, const char *__restrict format) __overloadable
82 __enable_if(__bos(dest) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
83 __bos(dest) < __builtin_strlen(format),
84 "format string will always overflow destination buffer")
85 __errorattr("format string will always overflow destination buffer");
86
87__BIONIC_FORTIFY_INLINE
88__printflike(2, 3)
89int sprintf(char *__restrict const __pass_object_size dest,
90 const char *__restrict format, ...) __overloadable {
91 va_list va;
92 va_start(va, format);
93 int result = __builtin___vsprintf_chk(dest, 0, __bos(dest), format, va);
94 va_end(va);
95 return result;
96}
97#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
98
99#if __ANDROID_API__ >= __ANDROID_API_N__
100__BIONIC_FORTIFY_INLINE
101size_t fread(void *__restrict buf, size_t size, size_t count,
102 FILE *__restrict stream) __overloadable
103 __enable_if(__unsafe_check_mul_overflow(size, count), "size * count overflows")
104 __errorattr("size * count overflows");
105
106__BIONIC_FORTIFY_INLINE
107size_t fread(void *__restrict buf, size_t size, size_t count,
108 FILE *__restrict stream) __overloadable
109 __enable_if(!__unsafe_check_mul_overflow(size, count), "no overflow")
110 __enable_if(__bos(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
111 size * count > __bos(buf), "size * count is too large")
112 __errorattr("size * count is too large");
113
114__BIONIC_FORTIFY_INLINE
115size_t fread(void *__restrict const __pass_object_size0 buf, size_t size,
116 size_t count, FILE *__restrict stream) __overloadable {
117 size_t bos = __bos0(buf);
118
119 if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
120 return __call_bypassing_fortify(fread)(buf, size, count, stream);
121 }
122
123 return __fread_chk(buf, size, count, stream, bos);
124}
125
126size_t fwrite(const void * __restrict buf, size_t size,
127 size_t count, FILE * __restrict stream) __overloadable
128 __enable_if(__unsafe_check_mul_overflow(size, count),
129 "size * count overflows")
130 __errorattr("size * count overflows");
131
132size_t fwrite(const void * __restrict buf, size_t size,
133 size_t count, FILE * __restrict stream) __overloadable
134 __enable_if(!__unsafe_check_mul_overflow(size, count), "no overflow")
135 __enable_if(__bos(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
136 size * count > __bos(buf), "size * count is too large")
137 __errorattr("size * count is too large");
138
139__BIONIC_FORTIFY_INLINE
140size_t fwrite(const void * __restrict const __pass_object_size0 buf,
141 size_t size, size_t count, FILE * __restrict stream)
142 __overloadable {
143 size_t bos = __bos0(buf);
144
145 if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
146 return __call_bypassing_fortify(fwrite)(buf, size, count, stream);
147 }
148
149 return __fwrite_chk(buf, size, count, stream, bos);
150}
151#endif /* __ANDROID_API__ >= __ANDROID_API_N__ */
152
153#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
154__BIONIC_ERROR_FUNCTION_VISIBILITY
155char *fgets(char* __restrict dest, int size, FILE* stream) __overloadable
156 __enable_if(size < 0, "size is negative")
157 __errorattr("size is negative");
158
159__BIONIC_ERROR_FUNCTION_VISIBILITY
160char *fgets(char* dest, int size, FILE* stream) __overloadable
161 __enable_if(size >= 0 && size > __bos(dest),
162 "size is larger than the destination buffer")
163 __errorattr("size is larger than the destination buffer");
164
165__BIONIC_FORTIFY_INLINE
166char *fgets(char* __restrict const __pass_object_size dest,
167 int size, FILE* stream) __overloadable {
168 size_t bos = __bos(dest);
169
170 if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
171 return __call_bypassing_fortify(fgets)(dest, size, stream);
172 }
173
174 return __fgets_chk(dest, size, stream, bos);
175}
176#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
177
178#else /* defined(__clang__) */
179
180size_t __fread_real(void * __restrict, size_t, size_t, FILE * __restrict) __RENAME(fread);
181__errordecl(__fread_too_big_error, "fread called with size * count bigger than buffer");
182__errordecl(__fread_overflow, "fread called with overflowing size * count");
183
184char* __fgets_real(char*, int, FILE*) __RENAME(fgets);
185__errordecl(__fgets_too_big_error, "fgets called with size bigger than buffer");
186__errordecl(__fgets_too_small_error, "fgets called with size less than zero");
187
188size_t __fwrite_real(const void * __restrict, size_t, size_t, FILE * __restrict) __RENAME(fwrite);
189__errordecl(__fwrite_too_big_error, "fwrite called with size * count bigger than buffer");
190__errordecl(__fwrite_overflow, "fwrite called with overflowing size * count");
191
192
193#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
194__BIONIC_FORTIFY_INLINE __printflike(3, 4)
195int snprintf(char *__restrict dest, size_t size, const char* _Nonnull format, ...)
196{
197 return __builtin___snprintf_chk(dest, size, 0, __bos(dest), format,
198 __builtin_va_arg_pack());
199}
200
201__BIONIC_FORTIFY_INLINE __printflike(2, 3)
202int sprintf(char *__restrict dest, const char* _Nonnull format, ...) {
203 return __builtin___sprintf_chk(dest, 0, __bos(dest), format,
204 __builtin_va_arg_pack());
205}
206#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
207
208#if __ANDROID_API__ >= __ANDROID_API_N__
209__BIONIC_FORTIFY_INLINE
210size_t fread(void *__restrict buf, size_t size, size_t count, FILE * __restrict stream) {
211 size_t bos = __bos0(buf);
212
213 if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
214 return __fread_real(buf, size, count, stream);
215 }
216
217 if (__builtin_constant_p(size) && __builtin_constant_p(count)) {
218 size_t total;
219 if (__size_mul_overflow(size, count, &total)) {
220 __fread_overflow();
221 }
222
223 if (total > bos) {
224 __fread_too_big_error();
225 }
226
227 return __fread_real(buf, size, count, stream);
228 }
229
230 return __fread_chk(buf, size, count, stream, bos);
231}
232
233__BIONIC_FORTIFY_INLINE
234size_t fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict stream) {
235 size_t bos = __bos0(buf);
236
237 if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
238 return __fwrite_real(buf, size, count, stream);
239 }
240
241 if (__builtin_constant_p(size) && __builtin_constant_p(count)) {
242 size_t total;
243 if (__size_mul_overflow(size, count, &total)) {
244 __fwrite_overflow();
245 }
246
247 if (total > bos) {
248 __fwrite_too_big_error();
249 }
250
251 return __fwrite_real(buf, size, count, stream);
252 }
253
254 return __fwrite_chk(buf, size, count, stream, bos);
255}
256#endif /* __ANDROID_API__ >= __ANDROID_API_N__ */
257
258#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
259__BIONIC_FORTIFY_INLINE
260char *fgets(char* dest, int size, FILE* stream) {
261 size_t bos = __bos(dest);
262
263 // Compiler can prove, at compile time, that the passed in size
264 // is always negative. Force a compiler error.
265 if (__builtin_constant_p(size) && (size < 0)) {
266 __fgets_too_small_error();
267 }
268
269 // Compiler doesn't know destination size. Don't call __fgets_chk
270 if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
271 return __fgets_real(dest, size, stream);
272 }
273
274 // Compiler can prove, at compile time, that the passed in size
275 // is always <= the actual object size. Don't call __fgets_chk
276 if (__builtin_constant_p(size) && (size <= (int) bos)) {
277 return __fgets_real(dest, size, stream);
278 }
279
280 // Compiler can prove, at compile time, that the passed in size
281 // is always > the actual object size. Force a compiler error.
282 if (__builtin_constant_p(size) && (size > (int) bos)) {
283 __fgets_too_big_error();
284 }
285
286 return __fgets_chk(dest, size, stream, bos);
287}
288#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
289
290#endif /* defined(__clang__) */
291#endif /* defined(__BIONIC_FORTIFY) */