1 /*
2 * Copyright (c) 2016-2020 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 #ifndef _SAN_MEMINTRINSICS_H_
29 #define _SAN_MEMINTRINSICS_H_
30
31 #include <sys/cdefs.h>
32
33 /*
34 * Non-sanitized versions of memory intrinsics
35 */
36 static inline void *
__sized_by(sz)37 __sized_by(sz)
38 __nosan_memcpy(void *dst __sized_by(sz), const void *src __sized_by(sz), size_t sz)
39 {
40 return memcpy(dst, src, sz);
41 }
42 static inline void *
__sized_by(sz)43 __sized_by(sz)
44 __nosan_memset(void *dst __sized_by(sz), int c, size_t sz)
45 {
46 return memset(dst, c, sz);
47 }
48 static inline void *
__sized_by(sz)49 __sized_by(sz)
50 __nosan_memmove(void *dst __sized_by(sz), const void *src __sized_by(sz), size_t sz)
51 {
52 return memmove(dst, src, sz);
53 }
54 static inline int
__nosan_bcmp(const void * a __sized_by (sz),const void * b __sized_by (sz),size_t sz)55 __nosan_bcmp(const void *a __sized_by(sz), const void *b __sized_by(sz), size_t sz)
56 {
57 return bcmp(a, b, sz);
58 }
59 static inline void
__nosan_bcopy(const void * src __sized_by (sz),void * dst __sized_by (sz),size_t sz)60 __nosan_bcopy(const void *src __sized_by(sz), void *dst __sized_by(sz), size_t sz)
61 {
62 bcopy(src, dst, sz);
63 }
64 static inline int
__nosan_memcmp(const void * a __sized_by (sz),const void * b __sized_by (sz),size_t sz)65 __nosan_memcmp(const void *a __sized_by(sz), const void *b __sized_by(sz), size_t sz)
66 {
67 return memcmp(a, b, sz);
68 }
69 static inline void
__nosan_bzero(void * dst __sized_by (sz),size_t sz)70 __nosan_bzero(void *dst __sized_by(sz), size_t sz)
71 {
72 bzero(dst, sz);
73 }
74
75 static inline size_t
__nosan_strlcpy(char * __sized_by (sz)dst,const char * __null_terminated src,size_t sz)76 __nosan_strlcpy(char *__sized_by(sz)dst, const char *__null_terminated src, size_t sz)
77 {
78 return strlcpy(dst, src, sz);
79 }
80 static inline size_t
__nosan_strlcat(char * __sized_by (sz)dst,const char * __null_terminated src,size_t sz)81 __nosan_strlcat(char *__sized_by(sz)dst, const char *__null_terminated src, size_t sz)
82 {
83 return strlcat(dst, src, sz);
84 }
85 static inline size_t
__nosan_strnlen(const char * __counted_by (sz)src,size_t sz)86 __nosan_strnlen(const char *__counted_by(sz)src, size_t sz)
87 {
88 return strnlen(src, sz);
89 }
90 static inline size_t
__nosan_strlen(const char * __null_terminated src)91 __nosan_strlen(const char *__null_terminated src)
92 {
93 return strlen(src);
94 }
95 static inline int
__nosan_strcmp(const char * __null_terminated s1,const char * __null_terminated s2)96 __nosan_strcmp(const char *__null_terminated s1, const char *__null_terminated s2)
97 {
98 return strcmp(s1, s2);
99 }
100 static inline int
__nosan_strncmp(const char * __unsafe_indexable s1,const char * __unsafe_indexable s2,size_t n)101 __nosan_strncmp(const char *__unsafe_indexable s1, const char *__unsafe_indexable s2, size_t n)
102 {
103 return strbufcmp(__unsafe_forge_bidi_indexable(const char *, s1, n), n, __unsafe_forge_bidi_indexable(const char *, s2, n), n);
104 }
105 static inline int
__nosan_strlcmp(const char * __counted_by (n)s1,const char * s2,size_t n)106 __nosan_strlcmp(const char *__counted_by(n)s1, const char *s2, size_t n)
107 {
108 return strlcmp(s1, s2, n);
109 }
110 static inline int
__nosan_strbufcmp(const char * __counted_by (s1len)s1,size_t s1len,const char * __counted_by (s2len)s2,size_t s2len)111 __nosan_strbufcmp(const char *__counted_by(s1len)s1, size_t s1len, const char *__counted_by(s2len)s2, size_t s2len)
112 {
113 return strbufcmp(s1, s1len, s2, s2len);
114 }
115 static inline int
__nosan_strcasecmp(const char * __null_terminated s1,const char * __null_terminated s2)116 __nosan_strcasecmp(const char *__null_terminated s1, const char *__null_terminated s2)
117 {
118 return strcasecmp(s1, s2);
119 }
120 static inline int
__nosan_strncasecmp(const char * __unsafe_indexable s1,const char * __unsafe_indexable s2,size_t n)121 __nosan_strncasecmp(const char *__unsafe_indexable s1, const char *__unsafe_indexable s2, size_t n)
122 {
123 return strbufcasecmp(__unsafe_forge_bidi_indexable(const char *, s1, n), n, __unsafe_forge_bidi_indexable(const char *, s2, n), n);
124 }
125 static inline int
__nosan_strlcasecmp(const char * __counted_by (n)s1,const char * s2,size_t n)126 __nosan_strlcasecmp(const char *__counted_by(n)s1, const char *s2, size_t n)
127 {
128 return strlcasecmp(s1, s2, n);
129 }
130 static inline int
__nosan_strbufcasecmp(const char * __counted_by (s1len)s1,size_t s1len,const char * __counted_by (s2len)s2,size_t s2len)131 __nosan_strbufcasecmp(const char *__counted_by(s1len)s1, size_t s1len, const char *__counted_by(s2len)s2, size_t s2len)
132 {
133 return strbufcasecmp(s1, s1len, s2, s2len);
134 }
135 #if !__has_ptrcheck && !__has_include(<__xnu_libcxx_sentinel.h>)
136 static inline char *
__nosan_strncpy(char * dst,const char * src,size_t sz)137 __nosan_strncpy(char *dst, const char *src, size_t sz)
138 {
139 #ifdef __clang__
140 #pragma clang diagnostic push
141 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
142 #endif
143 return strncpy(dst, src, sz);
144 #ifdef __clang__
145 #pragma clang diagnostic pop
146 #endif
147 }
148 static inline char *
__nosan_strncat(char * dst,const char * src,size_t sz)149 __nosan_strncat(char *dst, const char *src, size_t sz)
150 {
151 #ifdef __clang__
152 #pragma clang diagnostic push
153 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
154 #endif
155 return strncat(dst, src, sz);
156 #ifdef __clang__
157 #pragma clang diagnostic pop
158 #endif
159 }
160 #endif /* !__has_ptrcheck && !__has_include(<__xnu_libcxx_sentinel.h>) */
161
162 #if KASAN
163 void *__sized_by(sz) __asan_memcpy(void *dst __sized_by(sz), const void *src __sized_by(sz), size_t sz);
164 void *__sized_by(sz) __asan_memset(void * __sized_by(sz), int c, size_t sz);
165 void *__sized_by(sz) __asan_memmove(void *dst __sized_by(sz), const void *src __sized_by(sz), size_t sz);
166 void __asan_bcopy(const void *src __sized_by(sz), void *dst __sized_by(sz), size_t sz);
167 void __asan_bzero(void *dst __sized_by(sz), size_t sz);
168 int __asan_bcmp(const void *a __sized_by(sz), const void *b __sized_by(sz), size_t sz) __stateful_pure;
169 int __asan_memcmp(const void *a __sized_by(sz), const void *b __sized_by(sz), size_t sz) __stateful_pure;
170
171 size_t __asan_strlcpy(char *__sized_by(sz) dst, const char *__null_terminated src, size_t sz);
172 char *__asan_strncpy(char *dst, const char *src, size_t sz);
173 char *__asan_strncat(char *dst, const char *src, size_t sz);
174 size_t __asan_strlcat(char *__sized_by(sz) dst, const char *__null_terminated src, size_t sz);
175 size_t __asan_strnlen(const char *__counted_by(n)s, size_t n) __stateful_pure;
176 size_t __asan_strlen(const char *__null_terminated src) __stateful_pure;
177 int __asan_strcmp(const char *__null_terminated s1, const char *__null_terminated s2) __stateful_pure;
178 __ptrcheck_unavailable_r("strlcmp or strbufcmp")
179 int __asan_strncmp(const char *__null_terminated s1, const char *__null_terminated s2, size_t n) __stateful_pure;
180 int __asan_strlcmp(const char *__counted_by(n)s1, const char *s2, size_t n) __stateful_pure;
181 int __asan_strbufcmp(const char *__counted_by(s1len)s1, size_t s1len, const char *__counted_by(s2len)s2, size_t s2len) __stateful_pure;
182 int __asan_strcasecmp(const char *__null_terminated s1, const char *__null_terminated s2) __stateful_pure;
183 __ptrcheck_unavailable_r("strlcasecmp or strbufcasecmp")
184 int __asan_strncasecmp(const char *__unsafe_indexable s1, const char *__unsafe_indexable s2, size_t n) __stateful_pure;
185 int __asan_strlcasecmp(const char *__counted_by(n)s1, const char *s2, size_t n) __stateful_pure;
186 int __asan_strbufcasecmp(const char *__counted_by(s1len)s1, size_t s1len, const char *__counted_by(s2len)s2, size_t s2len) __stateful_pure;
187
188 #define memcpy __asan_memcpy
189 #define memmove __asan_memmove
190 #define memset __asan_memset
191 #define bcopy __asan_bcopy
192 #define bzero __asan_bzero
193 #define bcmp __asan_bcmp
194 #define memcmp __asan_memcmp
195
196 #define strlcpy __asan_strlcpy
197 #define strncpy __asan_strncpy
198 #define strlcat __asan_strlcat
199 #define strncat __asan_strncat
200 #define strnlen __asan_strnlen
201 #define strlen __asan_strlen
202 #define strcmp __asan_strcmp
203 #define strncmp __asan_strncmp
204 #define strlcmp __asan_strlcmp
205 #define strcasecmp __asan_strcasecmp
206 #define strncasecmp __asan_strncasecmp
207 #define strlcasecmp __asan_strlcasecmp
208
209 // Previously defined as macros in string.h
210 #undef strbuflen_1
211 #undef strbuflen_2
212 #undef strbuflen
213 #undef strbufcmp_2
214 #undef strbufcmp_4
215 #undef strbufcmp
216 #undef strbufcasecmp_2
217 #undef strbufcasecmp_4
218 #undef strbufcasecmp
219
220 #define strbuflen_1(BUF) ({ \
221 __xnu_assert_is_array(BUF, "argument is not an array"); \
222 __asan_strnlen((BUF), sizeof(BUF)); \
223 })
224 #define strbuflen_2(BUF, LEN) __asan_strnlen(BUF, LEN)
225 #define strbuflen(...) __xnu_argc_overload(strbuflen, __VA_ARGS__)
226
227 #define strbufcmp_2(A, B) ({ \
228 __xnu_assert_is_array(A, "first argument is not an array"); \
229 __xnu_assert_is_array(B, "second argument is not an array"); \
230 (__asan_strbufcmp)((A), sizeof(A), (B), sizeof(B)); \
231 })
232 #define strbufcmp_4 (__asan_strbufcmp)
233 #define strbufcmp(...) __xnu_argc_overload(strbufcmp, __VA_ARGS__)
234
235 #define strbufcasecmp_2(A, B) ({ \
236 __xnu_assert_is_array(A, "first argument is not an array"); \
237 __xnu_assert_is_array(B, "second argument is not an array"); \
238 (__asan_strbufcasecmp)((A), sizeof(A), (B), sizeof(B)); \
239 })
240 #define strbufcasecmp_4 (__asan_strbufcasecmp)
241 #define strbufcasecmp(...) __xnu_argc_overload(strbufcasecmp, __VA_ARGS__)
242
243 #endif
244
245 #endif /* _SAN_MEMINTRINSICS_H_ */
246