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 _STRING_H
17#error "Never include this file directly; instead, include <string.h>"
18#endif
19
20#include "fortify.h"
21
22#ifdef __cplusplus
23extern "C" {
24#endif
25
26void *__memchr_chk(const void* s, int c, size_t n, size_t actual_size);
27void *__memrchr_chk(const void*, int, size_t, size_t);
28size_t __strlcpy_chk(char*, const char*, size_t, size_t);
29size_t __strlcat_chk(char*, const char*, size_t, size_t);
30char *__strchr_chk(const char* p, int ch, size_t s_len);
31char *__strrchr_chk(const char *p, int ch, size_t s_len);
32size_t __strlen_chk(const char* s, size_t s_len);
33
34#ifdef __FORTIFY_COMPILATION
35__DIAGNOSE_FORTIFY_INLINE
36char *strcpy(char *const dest __DIAGNOSE_PASS_OBJECT_SIZE, const char *src)
37__DIAGNOSE_OVERLOAD
38__DIAGNOSE_ERROR_IF(__DIAGNOSE_UNEVALUATED_LE(__DIAGNOSE_BOS(dest), __builtin_strlen(src)),
39    "'strcpy' " CALLED_WITH_STRING_BIGGER_BUFFER)
40{
41#ifdef __FORTIFY_RUNTIME
42    return __builtin___strcpy_chk(dest, src, __DIAGNOSE_BOS(dest));
43#else
44    return __builtin_strcpy(dest, src);
45#endif
46}
47
48__DIAGNOSE_FORTIFY_INLINE
49char *stpcpy(char *const dest __DIAGNOSE_PASS_OBJECT_SIZE, const char *src)
50__DIAGNOSE_OVERLOAD
51__DIAGNOSE_ERROR_IF(__DIAGNOSE_UNEVALUATED_LE(__DIAGNOSE_BOS(dest), __builtin_strlen(src)),
52    "'stpcpy' " CALLED_WITH_STRING_BIGGER_BUFFER)
53{
54#ifdef __FORTIFY_RUNTIME
55    return __builtin___stpcpy_chk(dest, src, __DIAGNOSE_BOS(dest));
56#else
57    return __builtin_stpcpy(dest, src);
58#endif
59}
60
61__DIAGNOSE_FORTIFY_INLINE
62void *memmove(void *const dest __DIAGNOSE_PASS_OBJECT_SIZE0, const void *src, size_t len)
63__DIAGNOSE_OVERLOAD
64{
65#ifdef __FORTIFY_RUNTIME
66    return __builtin___memmove_chk(dest, src, len, __DIAGNOSE_BOS(dest));
67#else
68    return __builtin_memmove(dest, src, len);
69#endif
70}
71
72__DIAGNOSE_FORTIFY_INLINE
73void *mempcpy(void *const dest __DIAGNOSE_PASS_OBJECT_SIZE, const void *src, size_t copy_amount)
74__DIAGNOSE_OVERLOAD
75__DIAGNOSE_ERROR_IF(__DIAGNOSE_UNEVALUATED_LT(__DIAGNOSE_BOS0(dest), copy_amount),
76    "'mempcpy' " CALLED_WITH_STRING_BIGGER_BUFFER)
77{
78#ifdef __FORTIFY_RUNTIME
79    return __builtin___mempcpy_chk(dest, src, copy_amount, __DIAGNOSE_BOS0(dest));
80#else
81    return __builtin_mempcpy(dest, src, copy_amount);
82#endif
83}
84
85__DIAGNOSE_FORTIFY_INLINE
86char *strcat(char *const dest __DIAGNOSE_PASS_OBJECT_SIZE, const char *src)
87__DIAGNOSE_OVERLOAD
88__DIAGNOSE_ERROR_IF(__DIAGNOSE_UNEVALUATED_LE(__DIAGNOSE_BOS(dest), __builtin_strlen(src)),
89    "'strcat' " CALLED_WITH_STRING_BIGGER_BUFFER)
90{
91#ifdef __FORTIFY_RUNTIME
92    return __builtin___strcat_chk(dest, src, __DIAGNOSE_BOS(dest));
93#else
94    return __builtin_strcat(dest, src);
95#endif
96}
97
98#ifdef __FORTIFY_RUNTIME
99__DIAGNOSE_FORTIFY_INLINE
100char *strncat(char* const dest __DIAGNOSE_PASS_OBJECT_SIZE, const char* src, size_t n)
101__DIAGNOSE_OVERLOAD
102{
103    return __builtin___strncat_chk(dest, src, n, __DIAGNOSE_BOS(dest));
104}
105#endif
106
107#ifdef __FORTIFY_RUNTIME
108__DIAGNOSE_FORTIFY_INLINE
109char *stpncpy(char *const dest __DIAGNOSE_PASS_OBJECT_SIZE,
110    const char *const src __DIAGNOSE_PASS_OBJECT_SIZE, size_t n)
111__DIAGNOSE_OVERLOAD
112{
113    size_t bos_dest = __DIAGNOSE_BOS(dest);
114    return __builtin___stpncpy_chk(dest, src, n, bos_dest);
115}
116#endif
117
118#ifdef __FORTIFY_RUNTIME
119__DIAGNOSE_FORTIFY_INLINE
120char *strncpy(char *const dest __DIAGNOSE_PASS_OBJECT_SIZE,
121    const char *const src __DIAGNOSE_PASS_OBJECT_SIZE, size_t n)
122__DIAGNOSE_OVERLOAD
123{
124    size_t bos_dest = __DIAGNOSE_BOS(dest);
125    return __builtin___strncpy_chk(dest, src, n, bos_dest);
126}
127#endif
128
129#ifdef __FORTIFY_RUNTIME
130__DIAGNOSE_FORTIFY_INLINE
131void *memcpy(void *const dest __DIAGNOSE_PASS_OBJECT_SIZE0, const void *src, size_t copy_amount)
132__DIAGNOSE_OVERLOAD
133{
134    return __builtin___memcpy_chk(dest, src, copy_amount, __DIAGNOSE_BOS0(dest));
135}
136#endif
137
138#if defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
139__DIAGNOSE_FORTIFY_INLINE
140size_t strlcpy(char *const dest __DIAGNOSE_PASS_OBJECT_SIZE, const char *src, size_t size)
141__DIAGNOSE_OVERLOAD
142__DIAGNOSE_ERROR_IF(__DIAGNOSE_UNEVALUATED_LT(__DIAGNOSE_BOS(dest), size),
143    "'strlcpy' called with size bigger than buffer")
144{
145#ifdef __FORTIFY_RUNTIME
146    return __strlcpy_chk(dest, src, size, __DIAGNOSE_BOS(dest));
147#else
148    return __DIAGNOSE_CALL_BYPASSING_FORTIFY(strlcpy)(dest, src, size);
149#endif
150}
151
152__DIAGNOSE_FORTIFY_INLINE
153size_t strlcat(char* const dest __DIAGNOSE_PASS_OBJECT_SIZE, const char* src, size_t size)
154__DIAGNOSE_OVERLOAD
155__DIAGNOSE_ERROR_IF(__DIAGNOSE_UNEVALUATED_LT(__DIAGNOSE_BOS(dest), size),
156    "'strlcat' called with size bigger than buffer")
157{
158#ifdef __FORTIFY_RUNTIME
159    return __strlcat_chk(dest, src, size, __DIAGNOSE_BOS(dest));
160#else
161    return __DIAGNOSE_CALL_BYPASSING_FORTIFY(strlcat)(dest, src, size);
162#endif
163}
164#endif // defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
165
166__DIAGNOSE_FORTIFY_INLINE
167void *memset(void *const s __DIAGNOSE_PASS_OBJECT_SIZE0, int c, size_t n)
168__DIAGNOSE_OVERLOAD
169__DIAGNOSE_WARNING_IF(c && !n, "'memset' will set 0 bytes; maybe the arguments got flipped?")
170{
171#ifdef __FORTIFY_RUNTIME
172    return __builtin___memset_chk(s, c, n, __DIAGNOSE_BOS0(s));
173#else
174    return __builtin_memset(s, c, n);
175#endif
176}
177
178#ifdef __FORTIFY_RUNTIME
179__DIAGNOSE_FORTIFY_INLINE
180void *memchr(const void *const s __DIAGNOSE_PASS_OBJECT_SIZE, int c, size_t n)
181__DIAGNOSE_OVERLOAD
182{
183    size_t bos = __DIAGNOSE_BOS(s);
184    if (__DIAGNOSE_BOS_TRIVIALLY_GE(bos, n)) {
185        return __builtin_memchr(s, c, n);
186    }
187    return __memchr_chk(s, c, n, bos);
188}
189#endif // memchr __FORTIFY_RUNTIME
190
191extern void* __memrchr_real(const void*, int, size_t) __DIAGNOSE_RENAME(memrchr);
192
193#ifdef __FORTIFY_RUNTIME
194__DIAGNOSE_FORTIFY_INLINE
195void *memrchr(const void *const __DIAGNOSE_PASS_OBJECT_SIZE s, int c, size_t n)
196__DIAGNOSE_OVERLOAD
197{
198    size_t bos = __DIAGNOSE_BOS(s);
199    if (__DIAGNOSE_BOS_TRIVIALLY_GE(bos, n)) {
200        return __memrchr_real(s, c, n);
201    }
202    return __memrchr_chk(s, c, n, bos);
203}
204#endif
205
206__DIAGNOSE_FORTIFY_INLINE
207char* strchr(const char* const s __DIAGNOSE_PASS_OBJECT_SIZE, int c)
208__DIAGNOSE_OVERLOAD
209{
210#ifdef __FORTIFY_RUNTIME
211    size_t bos = __DIAGNOSE_BOS(s);
212
213    if (bos != __DIAGNOSE_FORTIFY_UNKNOWN_SIZE) {
214        return __strchr_chk(s, c, bos);
215    }
216#endif
217    return __builtin_strchr(s, c);
218}
219
220__DIAGNOSE_FORTIFY_INLINE
221char* strrchr(const char* const s __DIAGNOSE_PASS_OBJECT_SIZE, int c)
222__DIAGNOSE_OVERLOAD
223{
224#ifdef __FORTIFY_RUNTIME
225    size_t bos = __DIAGNOSE_BOS(s);
226
227    if (bos != __DIAGNOSE_FORTIFY_UNKNOWN_SIZE) {
228        return __strrchr_chk(s, c, bos);
229    }
230#endif
231    return __builtin_strrchr(s, c);
232}
233
234#ifdef __FORTIFY_RUNTIME
235__DIAGNOSE_FORTIFY_INLINE
236size_t strlen(const char* const s __DIAGNOSE_PASS_OBJECT_SIZE0)
237__DIAGNOSE_OVERLOAD
238{
239    return __strlen_chk(s, __DIAGNOSE_BOS0(s));
240}
241#endif
242
243#endif // __FORTIFY_COMPILATION
244#ifdef __cplusplus
245}
246#endif