xref: /third_party/musl/include/fortify/linux/stdio.h (revision 570af302)
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
24extern "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
35size_t __fread_chk(void*, size_t, size_t, FILE*, size_t);
36size_t __fwrite_chk(const void*, size_t, size_t, FILE*, size_t);
37char* __fgets_chk(char*, int, FILE*, size_t);
38
39__DIAGNOSE_FORTIFY_INLINE
40size_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
59size_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
78char* 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
94__DIAGNOSE_FORTIFY_INLINE __DIAGNOSE_PRINTFLIKE(FORMAT_PLACE_3, VALIST_PLACE_0)
95int 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
103__DIAGNOSE_FORTIFY_INLINE __DIAGNOSE_PRINTFLIKE(FORMAT_PLACE_2, VALIST_PLACE_0)
104int 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
110__DIAGNOSE_FORTIFY_VARIADIC __DIAGNOSE_PRINTFLIKE(FORMAT_PLACE_2, VALIST_PLACE_3)
111int 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
121__DIAGNOSE_FORTIFY_VARIADIC __DIAGNOSE_PRINTFLIKE(FORMAT_PLACE_3, VALIST_PLACE_4)
122int 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