1 /*
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 _STRING_H
30 #error "Never include this file directly; instead, include <string.h>"
31 #endif
32
33
34 #if __BIONIC_AVAILABILITY_GUARD(23)
35 void* _Nullable __memchr_chk(const void* _Nonnull, int, size_t, size_t) __INTRODUCED_IN(23);
36 void* _Nullable __memrchr_chk(const void* _Nonnull, int, size_t, size_t) __INTRODUCED_IN(23);
37 #endif /* __BIONIC_AVAILABILITY_GUARD(23) */
38
39 char* _Nonnull __stpncpy_chk2(char* _Nonnull, const char* _Nonnull, size_t, size_t, size_t);
40 char* _Nonnull __strncpy_chk2(char* _Nonnull, const char* _Nonnull, size_t, size_t, size_t);
41 size_t __strlcpy_chk(char* _Nonnull, const char* _Nonnull, size_t, size_t);
42 size_t __strlcat_chk(char* _Nonnull, const char* _Nonnull, size_t, size_t);
43
44 #if defined(__BIONIC_FORTIFY)
45 void* _Nullable __memrchr_real(const void* _Nonnull, int, size_t) __RENAME(memrchr);
46
47 #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
48 /* No diag -- clang diagnoses misuses of this on its own. */
49 __BIONIC_FORTIFY_INLINE
memcpy(void * _Nonnull const dst __pass_object_size0,const void * _Nonnull src,size_t copy_amount)50 void* _Nonnull memcpy(void* _Nonnull const dst __pass_object_size0, const void* _Nonnull src, size_t copy_amount)
51 __diagnose_as_builtin(__builtin_memcpy, 1, 2, 3)
52 __overloadable {
53 return __builtin___memcpy_chk(dst, src, copy_amount, __bos0(dst));
54 }
55
56 /* No diag -- clang diagnoses misuses of this on its own. */
57 __BIONIC_FORTIFY_INLINE
memmove(void * _Nonnull const dst __pass_object_size0,const void * _Nonnull src,size_t len)58 void* _Nonnull memmove(void* _Nonnull const dst __pass_object_size0, const void* _Nonnull src, size_t len)
59 __diagnose_as_builtin(__builtin_memmove, 1, 2, 3)
60 __overloadable {
61 return __builtin___memmove_chk(dst, src, len, __bos0(dst));
62 }
63 #endif
64
65 #if defined(__USE_GNU)
66 #if __ANDROID_API__ >= 30
67 __BIONIC_FORTIFY_INLINE
mempcpy(void * _Nonnull const dst __pass_object_size0,const void * _Nonnull src,size_t copy_amount)68 void* _Nonnull mempcpy(void* _Nonnull const dst __pass_object_size0, const void* _Nonnull src, size_t copy_amount)
69 __diagnose_as_builtin(__builtin_mempcpy, 1, 2, 3)
70 __overloadable
71 __clang_error_if(__bos_unevaluated_lt(__bos0(dst), copy_amount),
72 "'mempcpy' called with size bigger than buffer") {
73 #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
74 size_t bos_dst = __bos0(dst);
75 if (!__bos_trivially_ge(bos_dst, copy_amount)) {
76 return __builtin___mempcpy_chk(dst, src, copy_amount, bos_dst);
77 }
78 #endif
79 return __builtin_mempcpy(dst, src, copy_amount);
80 }
81 #endif /* __ANDROID_API__ >= 30 */
82 #endif /* __USE_GNU */
83
84 __BIONIC_FORTIFY_INLINE
stpcpy(char * _Nonnull const dst __pass_object_size,const char * _Nonnull src)85 char* _Nonnull stpcpy(char* _Nonnull const dst __pass_object_size, const char* _Nonnull src)
86 __overloadable
87 __clang_error_if(__bos_unevaluated_le(__bos(dst), __builtin_strlen(src)),
88 "'stpcpy' called with string bigger than buffer") {
89 #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
90 return __builtin___stpcpy_chk(dst, src, __bos(dst));
91 #else
92 return __builtin_stpcpy(dst, src);
93 #endif
94 }
95
96 __BIONIC_FORTIFY_INLINE
strcpy(char * _Nonnull const dst __pass_object_size,const char * _Nonnull src)97 char* _Nonnull strcpy(char* _Nonnull const dst __pass_object_size, const char* _Nonnull src)
98 __diagnose_as_builtin(__builtin_strcpy, 1, 2)
99 __overloadable
100 __clang_error_if(__bos_unevaluated_le(__bos(dst), __builtin_strlen(src)),
101 "'strcpy' called with string bigger than buffer") {
102 #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
103 return __builtin___strcpy_chk(dst, src, __bos(dst));
104 #else
105 return __builtin_strcpy(dst, src);
106 #endif
107 }
108
109 __BIONIC_FORTIFY_INLINE
strcat(char * _Nonnull const dst __pass_object_size,const char * _Nonnull src)110 char* _Nonnull strcat(char* _Nonnull const dst __pass_object_size, const char* _Nonnull src)
111 __overloadable
112 __clang_error_if(__bos_unevaluated_le(__bos(dst), __builtin_strlen(src)),
113 "'strcat' called with string bigger than buffer") {
114 #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
115 return __builtin___strcat_chk(dst, src, __bos(dst));
116 #else
117 return __builtin_strcat(dst, src);
118 #endif
119 }
120
121 #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
122 /* No diag -- clang diagnoses misuses of this on its own. */
123 __BIONIC_FORTIFY_INLINE
strncat(char * _Nonnull const dst __pass_object_size,const char * _Nonnull src,size_t n)124 char* _Nonnull strncat(char* _Nonnull const dst __pass_object_size, const char* _Nonnull src, size_t n)
125 __diagnose_as_builtin(__builtin_strncat, 1, 2, 3)
126 __overloadable {
127 return __builtin___strncat_chk(dst, src, n, __bos(dst));
128 }
129 #endif
130
131 /* No diag -- clang diagnoses misuses of this on its own. */
132 __BIONIC_FORTIFY_INLINE
memset(void * _Nonnull const s __pass_object_size0,int c,size_t n)133 void* _Nonnull memset(void* _Nonnull const s __pass_object_size0, int c, size_t n) __overloadable
134 __diagnose_as_builtin(__builtin_memset, 1, 2, 3)
135 /* If you're a user who wants this warning to go away: use `(&memset)(foo, bar, baz)`. */
136 __clang_warning_if(c && !n, "'memset' will set 0 bytes; maybe the arguments got flipped?") {
137 #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
138 return __builtin___memset_chk(s, c, n, __bos0(s));
139 #else
140 return __builtin_memset(s, c, n);
141 #endif
142 }
143
144 #if __ANDROID_API__ >= 23 && __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
145 __BIONIC_FORTIFY_INLINE
memchr(const void * _Nonnull const s __pass_object_size,int c,size_t n)146 void* _Nullable memchr(const void* _Nonnull const s __pass_object_size, int c, size_t n) __overloadable {
147 size_t bos = __bos(s);
148
149 if (__bos_trivially_ge(bos, n)) {
150 return __builtin_memchr(s, c, n);
151 }
152
153 return __memchr_chk(s, c, n, bos);
154 }
155
156 __BIONIC_FORTIFY_INLINE
__memrchr_fortify(const void * _Nonnull const __pass_object_size s,int c,size_t n)157 void* _Nullable __memrchr_fortify(const void* _Nonnull const __pass_object_size s, int c, size_t n) __overloadable {
158 size_t bos = __bos(s);
159
160 if (__bos_trivially_ge(bos, n)) {
161 return __memrchr_real(s, c, n);
162 }
163
164 return __memrchr_chk(s, c, n, bos);
165 }
166 #endif
167
168 #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
169 /* No diag -- clang diagnoses misuses of this on its own. */
170 __BIONIC_FORTIFY_INLINE
stpncpy(char * _Nonnull const dst __pass_object_size,const char * _Nonnull const src __pass_object_size,size_t n)171 char* _Nonnull stpncpy(char* _Nonnull const dst __pass_object_size, const char* _Nonnull const src __pass_object_size, size_t n)
172 __diagnose_as_builtin(__builtin_stpncpy, 1, 2, 3)
173 __overloadable {
174 size_t bos_dst = __bos(dst);
175 size_t bos_src = __bos(src);
176
177 /* Ignore dst size checks; they're handled in strncpy_chk */
178 if (bos_src == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
179 return __builtin___stpncpy_chk(dst, src, n, bos_dst);
180 }
181
182 return __stpncpy_chk2(dst, src, n, bos_dst, bos_src);
183 }
184
185 /* No diag -- clang diagnoses misuses of this on its own. */
186 __BIONIC_FORTIFY_INLINE
strncpy(char * _Nonnull const dst __pass_object_size,const char * _Nonnull const src __pass_object_size,size_t n)187 char* _Nonnull strncpy(char* _Nonnull const dst __pass_object_size, const char* _Nonnull const src __pass_object_size, size_t n)
188 __diagnose_as_builtin(__builtin_strncpy, 1, 2, 3)
189 __overloadable {
190 size_t bos_dst = __bos(dst);
191 size_t bos_src = __bos(src);
192
193 /* Ignore dst size checks; they're handled in strncpy_chk */
194 if (bos_src == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
195 return __builtin___strncpy_chk(dst, src, n, bos_dst);
196 }
197
198 return __strncpy_chk2(dst, src, n, bos_dst, bos_src);
199 }
200 #endif
201
202 __BIONIC_FORTIFY_INLINE
strlcpy(char * _Nonnull const dst __pass_object_size,const char * _Nonnull src,size_t size)203 size_t strlcpy(char* _Nonnull const dst __pass_object_size, const char* _Nonnull src, size_t size)
204 __overloadable
205 __clang_error_if(__bos_unevaluated_lt(__bos(dst), size),
206 "'strlcpy' called with size bigger than buffer") {
207 #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
208 return __strlcpy_chk(dst, src, size, __bos(dst));
209 #else
210 return __call_bypassing_fortify(strlcpy)(dst, src, size);
211 #endif
212 }
213
214 __BIONIC_FORTIFY_INLINE
strlcat(char * _Nonnull const dst __pass_object_size,const char * _Nonnull src,size_t size)215 size_t strlcat(char* _Nonnull const dst __pass_object_size, const char* _Nonnull src, size_t size)
216 __overloadable
217 __clang_error_if(__bos_unevaluated_lt(__bos(dst), size),
218 "'strlcat' called with size bigger than buffer") {
219 #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
220 return __strlcat_chk(dst, src, size, __bos(dst));
221 #else
222 return __call_bypassing_fortify(strlcat)(dst, src, size);
223 #endif
224 }
225
226 #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
227 /*
228 * Clang, when parsing C, can fold strlen to a constant without LLVM's help.
229 * This doesn't apply to overloads of strlen, so write this differently. We
230 * can't use `__pass_object_size0` here, but that's fine: it doesn't help much
231 * on __always_inline functions.
232 */
strlen(const char * _Nonnull s)233 extern __always_inline __inline__ __attribute__((gnu_inline)) size_t strlen(const char* _Nonnull s) {
234 return __strlen_chk(s, __bos0(s));
235 }
236 #endif
237
238 __BIONIC_FORTIFY_INLINE
strchr(const char * _Nonnull const s __pass_object_size,int c)239 char* _Nullable strchr(const char* _Nonnull const s __pass_object_size, int c) __overloadable {
240 #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
241 size_t bos = __bos(s);
242
243 if (bos != __BIONIC_FORTIFY_UNKNOWN_SIZE) {
244 return __strchr_chk(s, c, bos);
245 }
246 #endif
247 return __builtin_strchr(s, c);
248 }
249
250 __BIONIC_FORTIFY_INLINE
strrchr(const char * _Nonnull const s __pass_object_size,int c)251 char* _Nullable strrchr(const char* _Nonnull const s __pass_object_size, int c) __overloadable {
252 #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
253 size_t bos = __bos(s);
254
255 if (bos != __BIONIC_FORTIFY_UNKNOWN_SIZE) {
256 return __strrchr_chk(s, c, bos);
257 }
258 #endif
259 return __builtin_strrchr(s, c);
260 }
261
262 #if __ANDROID_API__ >= 23 && __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
263 #if defined(__cplusplus)
264 extern "C++" {
265 __BIONIC_FORTIFY_INLINE
memrchr(void * _Nonnull const __pass_object_size s,int c,size_t n)266 void* _Nullable memrchr(void* _Nonnull const __pass_object_size s, int c, size_t n) {
267 return __memrchr_fortify(s, c, n);
268 }
269
270 __BIONIC_FORTIFY_INLINE
memrchr(const void * _Nonnull const __pass_object_size s,int c,size_t n)271 const void* _Nullable memrchr(const void* _Nonnull const __pass_object_size s, int c, size_t n) {
272 return __memrchr_fortify(s, c, n);
273 }
274 }
275 #else
276 __BIONIC_FORTIFY_INLINE
memrchr(const void * _Nonnull const __pass_object_size s,int c,size_t n)277 void* _Nullable memrchr(const void* _Nonnull const __pass_object_size s, int c, size_t n) __overloadable {
278 return __memrchr_fortify(s, c, n);
279 }
280 #endif
281 #endif /* __ANDROID_API__ >= 23 */
282
283 #endif /* defined(__BIONIC_FORTIFY) */
284