xref: /xnu-12377.41.6/san/memory/memintrinsics.h (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
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