xref: /xnu-11417.140.69/osfmk/libsa/string.h (revision 43a90889846e00bfb5cf1d255cdc0a701a1e05a4)
1 /*
2  * Copyright (c) 2000-2006 Apple Computer, 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 /*
29  * NOTICE: This file was modified by McAfee Research in 2004 to introduce
30  * support for mandatory and extensible security protections.  This notice
31  * is included in support of clause 2.2 (b) of the Apple Public License,
32  * Version 2.0.
33  */
34 /*
35  * HISTORY
36  * @OSF_COPYRIGHT@
37  */
38 
39 #if (defined(__has_include) && __has_include(<__xnu_libcxx_sentinel.h>) && !defined(XNU_LIBCXX_SDKROOT))
40 
41 #if !__has_include_next(<string.h>)
42 #error Do not build with -nostdinc (use GCC_USE_STANDARD_INCLUDE_SEARCHING=NO)
43 #endif /* !__has_include_next(<string.h>) */
44 
45 #include_next <string.h>
46 
47 #else /* (defined(__has_include) && __has_include(<__xnu_libcxx_sentinel.h>) && !defined(XNU_LIBCXX_SDKROOT)) */
48 
49 #ifndef _STRING_H_
50 #define _STRING_H_      1
51 
52 #include <sys/cdefs.h>
53 #ifdef MACH_KERNEL_PRIVATE
54 #include <types.h>
55 #else /* MACH_KERNEL_PRIVATE */
56 #include <sys/types.h>
57 #endif /* MACH_KERNEL_PRIVATE */
58 
59 #ifdef KERNEL
60 #include <machine/trap.h>
61 #endif /* KERNEL */
62 
63 __BEGIN_DECLS
64 
65 #ifndef NULL
66 #if defined (__cplusplus)
67 #if __cplusplus >= 201103L
68 #define NULL nullptr
69 #else
70 #define NULL 0
71 #endif
72 #else
73 #define NULL ((void *)0)
74 #endif
75 #endif
76 
77 /*
78  * Memory functions
79  *
80  *   int bcmp(const void *s1, const void *s2, size_t n);
81  *   int memcmp(const void *s1, const void *s2, size_t n);
82  *   int timingsafe_bcmp(const void *b1, const void *b2, size_t n);
83  *
84  *   void bzero(void *dst, size_t n);
85  *   void *memset(void *s, int c, size_t n);
86  *   int memset_s(void *s, size_t smax, int c, size_t n);
87  *
88  *   void bcopy(const void *src, void *dst, size_t n);
89  *   void *memcpy(void *dst, const void *src, size_t n);
90  *   void *memove(void *dst, const void *src, size_t n);
91  *
92  *
93  * String functions
94  *
95  *   size_t strlen(const char *s);
96  *   size_t strnlen(const char *s, size_t n);
97  *
98  *   int strcmp(const char *s1, const char *s2);
99  *   int strncmp(const char *s1, const char *s2, size_t n);
100  *   int strlcmp(const char *s1, const char *s2, size_t n);
101  *   int strbufcmp(const char *s1, size_t n1, const char *s2, size_t n2);
102  *   int strprefix(const char *s1, const char *s2);
103  *   int strcasecmp(const char *s1, const char *s2);
104  *   int strncasecmp(const char *s1, const char *s2, size_t n);
105  *   int strlcasecmp(const char *s1, const char *s2, size_t n);
106  *   int strbufcasecmp(const char *s1, size_t n1, const char *s2, size_t n2);
107  *
108  *   char *strchr(const char *s, int c);
109  *   char *strrchr(const char *s, int c);
110  *   char *strnstr(const char *s, const char *find, size_t slen);
111  *
112  *   size_t strlcpy(char *dst, const char *src, size_t n);
113  *   const char *strbufcpy(char *dst, size_t dstlen, const char *src, size_t srclen);
114  *   size_t strlcat(char *dst, const char *src, size_t n);
115  *   const char *strbufcat(char *dst, size_t dstlen, const char *src, size_t srclen);
116  *   char * __null_terminated strlcpy_ret(char *dst, const char *src, size_t n);
117  */
118 
119 
120 #pragma mark _FORTIFY_SOURCE helpers
121 
122 /*
123  * If _FORTIFY_SOURCE is undefined, it is assumed to be 1.
124  *
125  * _FORTIFY_SOURCE > 0 will enable checked memory/string functions.
126  *
127  * _FORTIFY_SOURCE_STRICT will enable stricter checking (optional)
128  * for memcpy/memmove/bcopy and will check that copies do not go
129  * past the end of a struct member.
130  */
131 #if KASAN
132 #  define __XNU_FORTIFY_SOURCE          0 /* kasan is a superset */
133 #elif defined (_FORTIFY_SOURCE) && _FORTIFY_SOURCE == 0
134 #  define __XNU_FORTIFY_SOURCE          0 /* forcefully disabled */
135 #elif XNU_KERNEL_PRIVATE || defined(_FORTIFY_SOURCE_STRICT)
136 #  define __XNU_FORTIFY_SOURCE          2
137 #else
138 #  define __XNU_FORTIFY_SOURCE          1
139 #endif
140 
141 /*
142  * The overloadable attribute is load bearing in two major ways:
143  * - __builtin_${function} from ${function} would be infinite recursion and UB,
144  * - we need to still expose the regular prototype for people wanting to take
145  *   its address.
146  */
147 #define __xnu_string_inline \
148 	static inline __attribute__((__always_inline__, __overloadable__))
149 
150 /*
151  * We want to allow certain functions like strlen() to constant fold
152  * at compile time (such as strlen("foo")).
153  *
154  * In order to do so, we need an overload that has a similar looking
155  * signature but is different from the regular function so that it can
156  * call its matching builtin without causing UB due to inifinite recursion.
157  * We abuse that the pass_object_size class of attributes gives us
158  * precisely that semantics.
159  */
160 #define __xnu_force_overload            __xnu_pass_object_size
161 
162 /*
163  * The object_size extension defines two kinds of size: the "struct size" and
164  * the "member size". The "struct size" is the size of the buffer from the
165  * starting address to the end of the largest enclosing object. The "member
166  * size" is the size of the buffer from the starting address to the end of the
167  * immediately enclosing array. For instance, given this:
168  *
169  *  struct foo {
170  *      char a[20];
171  *      char b[20];
172  *  } my_foo;
173  *
174  * The "struct size" for &my_foo.a[10] is 30 (`sizeof(struct foo) -
175  * offsetof(struct foo, a[10])`), and the "member size" for it is 10
176  * (`sizeof(my_foo.a) - 10`).
177  *
178  * In general, you should use the member size for string operations (as it is
179  * always a mistake to go out of bounds of a char buffer with a string
180  * operation) and the struct size for bytewise operations (like bcopy, bzero,
181  * memset, etc). The object_size extension is intended to provide _some_ bounds
182  * safety at a low engineering cost, and various patterns intentionally
183  * overflowing from individual fields with bytewise operations have
184  * historically been tolerated both by engineers and the compiler (despite
185  * probably being undefined).
186  *
187  * As an important side note, -fbounds-safety does not allow naïvely
188  * overflowing from individual fields. -fbounds-safety bounds checks are always
189  * equivalent to checks against the member size.
190  */
191 
192 #if __has_builtin(__builtin_dynamic_object_size)
193 #  define __xnu_pass_struct_size        __attribute__((__pass_dynamic_object_size__(0)))
194 #  define __xnu_pass_member_size        __attribute__((__pass_dynamic_object_size__(1)))
195 #  define __xnu_struct_size(ptr)        __builtin_dynamic_object_size(ptr, 0)
196 #  define __xnu_member_size(ptr)        __builtin_dynamic_object_size(ptr, 1)
197 #else
198 #  define __xnu_pass_struct_size        __attribute__((__pass_object_size__(0)))
199 #  define __xnu_pass_member_size        __attribute__((__pass_object_size__(1)))
200 #  define __xnu_struct_size(ptr)        __builtin_object_size(ptr, 0)
201 #  define __xnu_member_size(ptr)        __builtin_object_size(ptr, 1)
202 #endif
203 
204 #if __XNU_FORTIFY_SOURCE == 0 || !__has_attribute(diagnose_if)
205 #  define __xnu_struct_size_precondition(ptr, size, message)
206 #  define __xnu_member_size_precondition(ptr, size, message)
207 #else
208 #  define __xnu_struct_size_precondition(ptr, size, message) \
209 	__attribute__((__diagnose_if__(__xnu_struct_size(ptr) < (size), message, "error")))
210 #  define __xnu_member_size_precondition(ptr, size, message) \
211 	__attribute__((__diagnose_if__(__xnu_member_size(ptr) < (size), message, "error")))
212 #endif
213 
214 
215 #if __XNU_FORTIFY_SOURCE > 1
216 #  define __xnu_object_size_precondition(...) \
217 	__xnu_member_size_precondition(__VA_ARGS__)
218 #  define __xnu_object_size_check(...) \
219 	__xnu_member_size_check(__VA_ARGS__)
220 #  define __xnu_pass_object_size        __xnu_pass_member_size
221 #else
222 #  define __xnu_object_size_precondition(...) \
223 	__xnu_struct_size_precondition(__VA_ARGS__)
224 #  define __xnu_object_size_check(...) \
225 	__xnu_struct_size_check(__VA_ARGS__)
226 #  define __xnu_pass_object_size        __xnu_pass_struct_size
227 #endif
228 
229 #if __XNU_FORTIFY_SOURCE == 0 || __has_ptrcheck
230 #define __xnu_struct_size_check(ptr, size, how)   ((void)0)
231 #define __xnu_member_size_check(ptr, size, how)   ((void)0)
232 #else
233 __xnu_string_inline __cold __dead2 void
234 __xnu_fortify_trap_write(void)
235 {
236 	ml_fatal_trap(0xbffe); /* XNU_HARD_TRAP_STRING_CHK */
237 }
238 
239 __xnu_string_inline __cold void
240 __xnu_fortify_trap_read(void)
241 {
242 	/* for now do not emit read traps yet */
243 #if 0
244 	ml_recoverable_trap(0xfffe); /* XNU_SOFT_TRAP_STRING_CHK */
245 #endif
246 }
247 
248 #define __xnu_struct_size_check(ptr, size, how)  ({ \
249 	if (__xnu_struct_size(ptr) < (size)) {                                  \
250 	        __xnu_fortify_trap_ ## how();                                   \
251 	}                                                                       \
252 })
253 #define __xnu_member_size_check(ptr, size, how)  ({ \
254 	if (__xnu_member_size(ptr) < (size)) {                                  \
255 	        __xnu_fortify_trap_ ## how();                                   \
256 	}                                                                       \
257 })
258 #endif
259 
260 /*
261  * Verifies at compile-time that an expression is an array (of any type).
262  */
263 #if __has_builtin(__builtin_types_compatible_p)
264 #define __xnu_is_array(A) __builtin_types_compatible_p(typeof((A)[0])[], typeof(A))
265 #else
266 #define __xnu_is_array(A) 1
267 #endif
268 #define __xnu_assert_is_array(A, MSG) _Static_assert(__xnu_is_array(A), MSG)
269 
270 #define __xnu_count_args1(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, N, ...) N
271 #define __xnu_count_args(...) \
272 	__xnu_count_args1(, ##__VA_ARGS__, _9, _8, _7, _6, _5, _4, _3, _2, _1, _0)
273 
274 #define __xnu_argc_overload1(base, N, ...) __CONCAT(base, N)(__VA_ARGS__)
275 #define __xnu_argc_overload(base, ...) \
276 	__xnu_argc_overload1(base, __xnu_count_args(__VA_ARGS__), ##__VA_ARGS__)
277 
278 #pragma mark memory functions
279 
280 
281 extern int bcmp(const void *s1 __sized_by(n), const void *s2 __sized_by(n), size_t n) __stateful_pure;
282 
283 __xnu_string_inline __stateful_pure
284 int
bcmp(const void * const s1 __xnu_pass_struct_size __sized_by (n),const void * const s2 __xnu_pass_struct_size __sized_by (n),size_t n)285 bcmp(
286 	const void *const       s1 __xnu_pass_struct_size __sized_by(n),
287 	const void *const       s2 __xnu_pass_struct_size __sized_by(n),
288 	size_t                  n)
289 __xnu_struct_size_precondition(s1, n, "read overflow (first argument)")
290 __xnu_struct_size_precondition(s2, n, "read overflow (second argument)")
291 {
292 	extern int __xnu_bcmp(
293 		const void * __sized_by(n),
294 		const void * __sized_by(n),
295 		size_t n) __asm("_bcmp");
296 
297 	__xnu_struct_size_check(s1, n, read);
298 	__xnu_struct_size_check(s2, n, read);
299 #if __has_builtin(__builtin_bcmp)
300 	return __builtin_bcmp(s1, s2, n);
301 #else
302 	return __xnu_bcmp(s1, s2, n);
303 #endif
304 }
305 
306 
307 extern int memcmp(const void *s1 __sized_by(n), const void *s2 __sized_by(n), size_t n) __stateful_pure;
308 
309 __xnu_string_inline __stateful_pure
310 int
memcmp(const void * const s1 __xnu_pass_struct_size __sized_by (n),const void * const s2 __xnu_pass_struct_size __sized_by (n),size_t n)311 memcmp(
312 	const void *const       s1 __xnu_pass_struct_size __sized_by(n),
313 	const void *const       s2 __xnu_pass_struct_size __sized_by(n),
314 	size_t                  n)
315 __xnu_struct_size_precondition(s1, n, "read overflow (first argument)")
316 __xnu_struct_size_precondition(s2, n, "read overflow (second argument)")
317 {
318 	extern int __xnu_memcmp(
319 		const void *__sized_by(n),
320 		const void *__sized_by(n),
321 		size_t n) __asm("_memcmp");
322 
323 	__xnu_struct_size_check(s1, n, read);
324 	__xnu_struct_size_check(s2, n, read);
325 #if __has_builtin(__builtin_memcmp)
326 	return __builtin_memcmp(s1, s2, n);
327 #else
328 	return __xnu_memcmp(s1, s2, n);
329 #endif
330 }
331 
332 
333 #ifdef XNU_KERNEL_PRIVATE
334 /*
335  * memcmp_zero_ptr_aligned() checks string s of n bytes contains all zeros.
336  * Address and size of the string s must be pointer-aligned.
337  * Return 0 if true, 1 otherwise. Also return 0 if n is 0.
338  */
339 extern unsigned long memcmp_zero_ptr_aligned(const void *s __sized_by(n), size_t n) __stateful_pure;
340 #endif
341 
342 
343 extern int timingsafe_bcmp(const void *b1 __sized_by(n), const void *b2 __sized_by(n), size_t n);
344 
345 
346 extern void bzero(void *s __sized_by(n), size_t n);
347 
348 __xnu_string_inline
349 void
bzero(void * const s __xnu_pass_struct_size __sized_by (n),size_t n)350 bzero(
351 	void *const             s __xnu_pass_struct_size __sized_by(n),
352 	size_t                  n)
353 __xnu_struct_size_precondition(s, n, "write overflow")
354 {
355 	extern void __xnu_bzero(
356 		const void *__sized_by(n),
357 		size_t n) __asm("_bzero");
358 
359 	__xnu_struct_size_check(s, n, write);
360 #if __has_builtin(__builtin_bzero)
361 	__builtin_bzero(s, n);
362 #else
363 	__xnu_bzero(s, n);
364 #endif
365 }
366 
367 
368 extern void *memset(void *s __sized_by(n), int c, size_t n);
369 
370 __xnu_string_inline
371 void *
__sized_by(n)372 __sized_by(n)
373 memset(
374 	void *const             s __xnu_pass_object_size __sized_by(n),
375 	int                     c,
376 	size_t                  n)
377 __xnu_object_size_precondition(s, n, "write overflow")
378 {
379 	extern void __xnu_memset(
380 		void *__sized_by(n),
381 		int,
382 		size_t n) __asm("_memset");
383 
384 	__xnu_object_size_check(s, n, write);
385 #if __has_builtin(__builtin_memset)
386 	return __builtin_memset(s, c, n);
387 #else
388 	return __xnu_memset(s, c, n);
389 #endif
390 }
391 
392 
393 extern int memset_s(void *s __sized_by(smax), size_t smax, int c, size_t n);
394 
395 
396 extern void *memmove(void *dst __sized_by(n), const void *src __sized_by(n), size_t n);
397 
398 __xnu_string_inline
399 void *
__sized_by(n)400 __sized_by(n)
401 memmove(
402 	void *const             dst __xnu_pass_object_size __sized_by(n),
403 	const void *const       src __xnu_pass_object_size __sized_by(n),
404 	size_t                  n)
405 __xnu_object_size_precondition(dst, n, "write overflow")
406 __xnu_object_size_precondition(src, n, "read overflow")
407 {
408 	extern void *__xnu_memmove(
409 		void *dst __sized_by(n),
410 		const void *src __sized_by(n),
411 		size_t n) __asm("_memmove");
412 
413 	__xnu_object_size_check(dst, n, write);
414 	__xnu_object_size_check(src, n, read);
415 #if __has_builtin(__builtin_memmove)
416 	return __builtin_memmove(dst, src, n);
417 #else
418 	return __xnu_memmove(dst, src, n);
419 #endif
420 }
421 
422 __xnu_string_inline
423 void *
__sized_by(n)424 __sized_by(n)
425 __nochk_memmove(
426 	void *const             dst __xnu_pass_struct_size __sized_by(n),
427 	const void *const       src __xnu_pass_struct_size __sized_by(n),
428 	size_t                  n)
429 __xnu_struct_size_precondition(dst, n, "write overflow")
430 __xnu_struct_size_precondition(src, n, "read overflow")
431 {
432 	extern void *__xnu_memmove(
433 		void *dst __sized_by(n),
434 		const void *src __sized_by(n),
435 		size_t n) __asm("_memmove");
436 
437 	__xnu_struct_size_check(dst, n, write);
438 	__xnu_struct_size_check(src, n, read);
439 #if __has_builtin(__builtin_memmove)
440 	return __builtin_memmove(dst, src, n);
441 #else
442 	return __xnu_memmove(dst, src, n);
443 #endif
444 }
445 
446 
447 extern void bcopy(const void *src __sized_by(n), void *dst __sized_by(n), size_t n);
448 
449 __xnu_string_inline
450 void
bcopy(const void * const src __xnu_pass_object_size __sized_by (n),void * const dst __xnu_pass_object_size __sized_by (n),size_t n)451 bcopy(
452 	const void *const       src __xnu_pass_object_size __sized_by(n),
453 	void *const             dst __xnu_pass_object_size __sized_by(n),
454 	size_t                  n)
455 __xnu_struct_size_precondition(dst, n, "write overflow")
456 __xnu_struct_size_precondition(src, n, "read overflow")
457 {
458 	(void)memmove(dst, src, n);
459 }
460 
461 __xnu_string_inline
462 void
__nochk_bcopy(const void * const src __xnu_pass_struct_size __sized_by (n),void * const dst __xnu_pass_struct_size __sized_by (n),size_t n)463 __nochk_bcopy(
464 	const void *const       src __xnu_pass_struct_size __sized_by(n),
465 	void *const             dst __xnu_pass_struct_size __sized_by(n),
466 	size_t                  n)
467 __xnu_struct_size_precondition(dst, n, "write overflow")
468 __xnu_struct_size_precondition(src, n, "read overflow")
469 {
470 	(void)__nochk_memmove(dst, src, n);
471 }
472 
473 
474 extern void *memcpy(void *dst __sized_by(n), const void *src __sized_by(n), size_t n);
475 
476 __xnu_string_inline
477 void *
__sized_by(n)478 __sized_by(n)
479 memcpy(
480 	void *const             dst __xnu_pass_object_size __sized_by(n),
481 	const void *const       src __xnu_pass_object_size __sized_by(n),
482 	size_t                  n)
483 __xnu_struct_size_precondition(dst, n, "write overflow")
484 __xnu_struct_size_precondition(src, n, "read overflow")
485 {
486 	return memmove(dst, src, n);
487 }
488 
489 __xnu_string_inline
490 void *
__sized_by(n)491 __sized_by(n)
492 __nochk_memcpy(
493 	void *const             dst __xnu_pass_struct_size __sized_by(n),
494 	const void *const       src __xnu_pass_struct_size __sized_by(n),
495 	size_t                  n)
496 __xnu_struct_size_precondition(dst, n, "write overflow")
497 __xnu_struct_size_precondition(src, n, "read overflow")
498 {
499 	return __nochk_memmove(dst, src, n);
500 }
501 
502 
503 #pragma mark string functions
504 
505 extern size_t strlen(const char *__null_terminated s) __stateful_pure;
506 
507 #if __has_builtin(__builtin_strlen)
508 __xnu_string_inline __stateful_pure
509 size_t
strlen(const char * const s __xnu_force_overload)510 strlen(const char * /* __null_terminated */ const s __xnu_force_overload)
511 {
512 	return __builtin_strlen(s);
513 }
514 #endif
515 
516 
517 extern size_t strnlen(const char *__counted_by(n)s, size_t n) __stateful_pure;
518 
519 #if __has_builtin(__builtin_strnlen)
520 __xnu_string_inline __stateful_pure
521 size_t
strnlen(const char * const __counted_by (n)s __xnu_force_overload,size_t n)522 strnlen(const char *const __counted_by(n) s __xnu_force_overload, size_t n)
523 {
524 	return __builtin_strnlen(s, n);
525 }
526 #endif
527 
528 
529 /* strbuflen is the same as strnlen. */
530 #define strbuflen_1(BUF) ({ \
531 	__xnu_assert_is_array(BUF, "argument is not an array"); \
532 	strnlen((BUF), sizeof(BUF)); \
533 })
534 #define strbuflen_2(BUF, LEN) strnlen(BUF, LEN)
535 #define strbuflen(...) __xnu_argc_overload(strbuflen, __VA_ARGS__)
536 
537 
538 extern int strcmp(const char *__null_terminated s1, const char *__null_terminated s2) __stateful_pure;
539 
540 #if __has_builtin(__builtin_strcmp)
541 __xnu_string_inline __stateful_pure
542 int
strcmp(const char * const s1 __xnu_force_overload,const char * const __null_terminated s2)543 strcmp(
544 	const char *const /* __null_terminated */ s1 __xnu_force_overload,
545 	const char *const __null_terminated s2)
546 {
547 	return __builtin_strcmp(s1, s2);
548 }
549 #else
550 #endif
551 
552 
553 __ptrcheck_unavailable_r("strlcmp or strbufcmp")
554 extern int strncmp(const char *__unsafe_indexable s1, const char *__unsafe_indexable s2, size_t n) __stateful_pure;
555 
556 #if __has_builtin(__builtin_strncmp)
557 __ptrcheck_unavailable_r("strlcmp or strbufcmp")
558 __xnu_string_inline __stateful_pure
559 int
strncmp(const char * const __unsafe_indexable s1 __xnu_force_overload,const char * const __unsafe_indexable s2,size_t n)560 strncmp(
561 	const char *const __unsafe_indexable s1 __xnu_force_overload,
562 	const char *const __unsafe_indexable s2, size_t n)
563 {
564 	return __builtin_strncmp(s1, s2, n);
565 }
566 #endif
567 
568 /*
569  * Use strlcmp if you want to compare one string with a known length (with or
570  * without a NUL terminator) and one string with an unknown length (that always
571  * has a NUL terminator).
572  * See docs/primitives/string-handling.md for more information.
573  */
574 extern int strlcmp(const char *__counted_by(n)s1, const char *s2, size_t n) __stateful_pure;
575 
576 #if __has_builtin(__builtin_strncmp)
577 __xnu_string_inline __stateful_pure
578 int
strlcmp(const char * const __counted_by (s1len)s1 __xnu_force_overload,const char * const s2,size_t s1len)579 strlcmp(
580 	const char *const __counted_by(s1len) s1 __xnu_force_overload,
581 	const char *const s2, size_t s1len)
582 __xnu_member_size_precondition(s1, s1len, "read overflow")
583 {
584 	extern int __xnu_strlcmp(
585 		const char * __counted_by(s1len) s1,
586 		const char *__null_terminated s2,
587 		size_t s1len) __asm("_strlcmp");
588 
589 	__xnu_member_size_check(s1, s1len, read);
590 	return __xnu_strlcmp(s1, s2, s1len);
591 }
592 #endif
593 
594 
595 /*
596  * Use strbufcmp if you want to compare two strings and you know both of their
597  * lengths. See docs/primitives/string-handling.md for more information.
598  */
599 extern int strbufcmp(const char *__counted_by(s1len)s1, size_t s1len, const char *__counted_by(s2len)s2, size_t s2len) __stateful_pure;
600 
601 __xnu_string_inline __stateful_pure
602 int
strbufcmp(const char * const __counted_by (s1len)s1 __xnu_pass_member_size,size_t s1len,const char * const __counted_by (s2len)s2 __xnu_pass_member_size,size_t s2len)603 strbufcmp(
604 	const char *const __counted_by(s1len) s1 __xnu_pass_member_size, size_t s1len,
605 	const char *const __counted_by(s2len) s2 __xnu_pass_member_size, size_t s2len)
606 __xnu_member_size_precondition(s1, s1len, "read overflow")
607 __xnu_member_size_precondition(s2, s2len, "read overflow")
608 {
609 	extern int __xnu_strbufcmp(
610 		const char * __counted_by(s1len) s1,
611 		size_t s1len,
612 		const char *__counted_by(s2len) s2,
613 		size_t s2len) __asm("_strbufcmp");
614 
615 	__xnu_member_size_check(s1, s1len, read);
616 	__xnu_member_size_check(s2, s2len, read);
617 	return __xnu_strbufcmp(s1, s1len, s2, s2len);
618 }
619 
620 #define strbufcmp_2(A, B) ({ \
621 	__xnu_assert_is_array(A, "first argument is not an array"); \
622 	__xnu_assert_is_array(B, "second argument is not an array"); \
623 	(strbufcmp)((A), sizeof(A), (B), sizeof(B)); \
624 })
625 #define strbufcmp_4 (strbufcmp)
626 #define strbufcmp(...) __xnu_argc_overload(strbufcmp, __VA_ARGS__)
627 
628 
629 extern int strprefix(const char *__null_terminated s1, const char *__null_terminated s2) __stateful_pure;
630 
631 
632 extern int strcasecmp(const char *__null_terminated s1, const char *__null_terminated s2) __stateful_pure;
633 
634 #if __has_builtin(__builtin_strcasecmp)
635 __xnu_string_inline __stateful_pure
636 int
strcasecmp(const char * const s1 __xnu_force_overload,const char * const __null_terminated s2)637 strcasecmp(
638 	const char *const /* __null_terminated */ s1 __xnu_force_overload,
639 	const char *const __null_terminated s2)
640 {
641 	return __builtin_strcasecmp(s1, s2);
642 }
643 #endif
644 
645 
646 __ptrcheck_unavailable_r("strlcasecmp or strbufcasecmp")
647 extern int strncasecmp(const char *__unsafe_indexable s1, const char *__unsafe_indexable s2, size_t n) __stateful_pure;
648 
649 #if __has_builtin(__builtin_strncasecmp)
650 __ptrcheck_unavailable_r("strlcasecmp or strbufcasecmp")
651 __xnu_string_inline __stateful_pure
652 int
strncasecmp(const char * const __unsafe_indexable s1 __xnu_force_overload,const char * const __unsafe_indexable s2,size_t n)653 strncasecmp(
654 	const char *const __unsafe_indexable s1 __xnu_force_overload,
655 	const char *const __unsafe_indexable s2, size_t n)
656 {
657 	return __builtin_strncasecmp(s1, s2, n);
658 }
659 #endif
660 
661 /*
662  * Use strlcasecmp if you want to compare one string with a known length (with
663  * or without a NUL terminator) and one string with an unknown length (that
664  * always has a NUL terminator).
665  * See docs/primitives/string-handling.md for more information.
666  */
667 extern int strlcasecmp(const char *__counted_by(n)s1, const char *s2, size_t n) __stateful_pure;
668 
669 __xnu_string_inline __stateful_pure
670 int
strlcasecmp(const char * const __counted_by (s1len)s1 __xnu_force_overload,const char * __null_terminated const s2,size_t s1len)671 strlcasecmp(
672 	const char *const __counted_by(s1len) s1 __xnu_force_overload,
673 	const char *__null_terminated const s2, size_t s1len)
674 __xnu_member_size_precondition(s1, s1len, "read overflow")
675 {
676 	extern int __xnu_strlcasecmp(
677 		const char * __counted_by(s1len) s1,
678 		const char *__null_terminated s2,
679 		size_t s1len) __asm("_strlcasecmp");
680 
681 	__xnu_member_size_check(s1, s1len, read);
682 	return __xnu_strlcasecmp(s1, s2, s1len);
683 }
684 
685 
686 /*
687  * Use strbufcmp if you want to compare two strings and you know both of their
688  * lengths. See docs/primitives/string-handling.md for more information.
689  */
690 extern int strbufcasecmp(const char *__counted_by(s1len)s1, size_t s1len, const char *__counted_by(s2len)s2, size_t s2len) __stateful_pure;
691 
692 __xnu_string_inline __stateful_pure
693 int
strbufcasecmp(const char * const __counted_by (s1len)s1 __xnu_pass_member_size,size_t s1len,const char * const __counted_by (s2len)s2 __xnu_pass_member_size,size_t s2len)694 strbufcasecmp(
695 	const char *const __counted_by(s1len) s1 __xnu_pass_member_size, size_t s1len,
696 	const char *const __counted_by(s2len) s2 __xnu_pass_member_size, size_t s2len)
697 __xnu_member_size_precondition(s1, s1len, "read overflow")
698 __xnu_member_size_precondition(s2, s2len, "read overflow")
699 {
700 	extern int __xnu_strbufcasecmp(
701 		const char * __counted_by(s1len) s1,
702 		size_t s1len,
703 		const char *__counted_by(s2len) s2,
704 		size_t s2len) __asm("_strbufcasecmp");
705 
706 	__xnu_member_size_check(s1, s1len, read);
707 	__xnu_member_size_check(s2, s2len, read);
708 	return __xnu_strbufcasecmp(s1, s1len, s2, s2len);
709 }
710 
711 #define strbufcasecmp_2(A, B) ({ \
712 	__xnu_assert_is_array(A, "first argument is not an array"); \
713 	__xnu_assert_is_array(B, "second argument is not an array"); \
714 	(strbufcasecmp)((A), sizeof(A), (B), sizeof(B)); \
715 })
716 #define strbufcasecmp_4 (strbufcasecmp)
717 #define strbufcasecmp(...) __xnu_argc_overload(strbufcasecmp, __VA_ARGS__)
718 
719 
720 #if __has_builtin(__builtin_strchr)
721 __xnu_string_inline
722 char *__null_terminated
strchr(const char * const s __xnu_force_overload,int c)723 strchr(const char *const /* __null_terminated */ s __xnu_force_overload, int c)
724 {
725 	return __unsafe_forge_null_terminated(char *, __builtin_strchr(s, c));
726 }
727 #endif
728 
729 
730 #if XNU_KERNEL_PRIVATE /* rdar://103276672 */
731 extern char *__null_terminated strrchr(const char *__null_terminated s, int c) __stateful_pure;
732 
733 #if __has_builtin(__builtin_strrchr) && !__has_ptrcheck /* rdar://103265304 */
734 __xnu_string_inline
735 char *__null_terminated
strrchr(const char * const __null_terminated s __xnu_force_overload,int c)736 strrchr(const char *const __null_terminated s __xnu_force_overload, int c)
737 {
738 	return __builtin_strrchr(s, c);
739 }
740 #endif
741 #endif
742 
743 
744 extern char *__null_terminated strnstr(const char *__null_terminated s, const char *__null_terminated find, size_t slen) __stateful_pure;
745 
746 
747 extern size_t strlcpy(char *__counted_by(n) dst, const char *__null_terminated src, size_t n);
748 
749 __xnu_string_inline
750 size_t
strlcpy(char * const dst __xnu_pass_member_size __counted_by (n),const char * const src __null_terminated,size_t n)751 strlcpy(
752 	char *const             dst __xnu_pass_member_size __counted_by(n),
753 	const char *const       src __null_terminated,
754 	size_t                  n)
755 __xnu_member_size_precondition(dst, n, "write overflow")
756 {
757 	extern size_t __xnu_strlcpy(
758 		char * __counted_by(n),
759 		const char *__null_terminated,
760 		size_t n) __asm("_strlcpy");
761 
762 	__xnu_member_size_check(dst, n, write);
763 #if __has_builtin(__builtin_strlcpy)
764 	return __builtin_strlcpy(dst, src, n);
765 #else
766 	return __xnu_strlcpy(dst, src, n);
767 #endif
768 }
769 
770 /*
771  * Use strlcpy_ret if all you want is the __null_terminated pointer
772  * to the resulting string.
773  * See docs/primitives/string-handling.md for more information.
774  */
775 __xnu_string_inline
776 char * __null_terminated
strlcpy_ret(char * const dst __xnu_pass_member_size __counted_by (n),const char * const src __null_terminated,size_t n)777 strlcpy_ret(
778 	char *const             dst __xnu_pass_member_size __counted_by(n),
779 	const char *const       src __null_terminated,
780 	size_t                  n)
781 __xnu_member_size_precondition(dst, n, "write overflow")
782 {
783 	size_t cnt = strlcpy(dst, src, n);
784 	/*
785 	 * Like snprintf(3), the strlcpy() returns the total length of the string they tried to create, i.e. length of `src'.
786 	 */
787 	if (cnt >= n) {
788 		/*
789 		 * The output string has been truncated. The terminating NUL is at `dst + (n - 1)'.
790 		 */
791 		return __unsafe_null_terminated_from_indexable(dst, dst + (n - 1));
792 	} else {
793 		/*
794 		 * The output string hasn't been truncated. The terminating NUL is at `dst + cnt';
795 		 */
796 		return __unsafe_null_terminated_from_indexable(dst, dst + cnt);
797 	}
798 }
799 
800 
801 /*
802  * strbufcpy returns its destination as a NUL-terminated string, which makes a
803  * difference when -fbounds-safety is enabled.
804  * See docs/primitives/string-handling.md for more information.
805  */
806 extern const char *__null_terminated
807     strbufcpy(
808 	char *__counted_by(dstsz) dst,
809 	size_t dstsz,
810 	const char *__counted_by(srcsz) src,
811 	size_t srcsz);
812 
813 __xnu_string_inline
814 const char *
strbufcpy(char * const dst __xnu_pass_member_size __counted_by (dstsz),size_t dstsz,const char * const src __xnu_pass_member_size __counted_by (srcsz),size_t srcsz)815 strbufcpy(
816 	char *const             dst __xnu_pass_member_size __counted_by(dstsz),
817 	size_t                  dstsz,
818 	const char *const       src __xnu_pass_member_size __counted_by(srcsz),
819 	size_t                  srcsz)
820 __xnu_member_size_precondition(dst, dstsz, "write overflow")
821 __xnu_member_size_precondition(src, srcsz, "read overflow")
822 {
823 	extern const char *__xnu_strbufcpy(
824 		char *__counted_by(dstsz) dst,
825 		size_t dstsz,
826 		const char *__counted_by(srcsz) src,
827 		size_t srcsz) __asm("_strbufcpy");
828 
829 	__xnu_member_size_check(dst, dstsz, write);
830 	__xnu_member_size_check(src, srcsz, read);
831 	return __xnu_strbufcpy(dst, dstsz, src, srcsz);
832 }
833 
834 #define strbufcpy_2(DST, SRC) ({ \
835 	__xnu_assert_is_array(DST, "dst is not an array"); \
836 	__xnu_assert_is_array(SRC, "src is not an array"); \
837 	(strbufcpy)((DST), sizeof(DST), (SRC), sizeof(SRC)); \
838 })
839 #define strbufcpy_4     (strbufcpy)
840 #define strbufcpy(...)  __xnu_argc_overload(strbufcpy, __VA_ARGS__)
841 
842 extern size_t strlcat(char *__counted_by(n) dst, const char *__null_terminated src, size_t n);
843 
844 __xnu_string_inline
845 size_t
strlcat(char * const dst __xnu_pass_member_size __counted_by (n),const char * const src __null_terminated,size_t n)846 strlcat(
847 	char *const             dst __xnu_pass_member_size __counted_by(n),
848 	const char *const       src __null_terminated,
849 	size_t                  n)
850 __xnu_member_size_precondition(dst, n, "write overflow")
851 {
852 	extern size_t __xnu_strlcat(
853 		char * __sized_by(n),
854 		const char *__null_terminated,
855 		size_t n) __asm("_strlcat");
856 
857 	__xnu_member_size_check(dst, n, write);
858 #if __has_builtin(__builtin_strlcat)
859 	return __builtin_strlcat(dst, src, n);
860 #else
861 	return __xnu_strlcat(dst, src, n);
862 #endif
863 }
864 
865 
866 /*
867  * strbufcat returns its destination as a NUL-terminated string, which makes a
868  * difference when -fbounds-safety is enabled.
869  * See docs/primitives/string-handling.md for more information.
870  */
871 extern const char *__null_terminated
872     strbufcat(
873 	char *__counted_by(dstsz) dst,
874 	size_t dstsz,
875 	const char *__counted_by(srcsz) src,
876 	size_t srcsz);
877 
878 __xnu_string_inline
879 const char *
strbufcat(char * const dst __xnu_pass_member_size __counted_by (dstsz),size_t dstsz,const char * const src __xnu_pass_member_size __counted_by (srcsz),size_t srcsz)880 strbufcat(
881 	char *const             dst __xnu_pass_member_size __counted_by(dstsz),
882 	size_t                  dstsz,
883 	const char *const       src __xnu_pass_member_size __counted_by(srcsz),
884 	size_t                  srcsz)
885 __xnu_member_size_precondition(dst, dstsz, "write overflow")
886 __xnu_member_size_precondition(src, srcsz, "read overflow")
887 {
888 	extern const char *__xnu_strbufcat(
889 		char *__counted_by(dstsz) dst,
890 		size_t dstsz,
891 		const char *__counted_by(srcsz) src,
892 		size_t srcsz) __asm("_strbufcat");
893 
894 	__xnu_member_size_check(dst, dstsz, write);
895 	__xnu_member_size_check(src, srcsz, read);
896 	return __xnu_strbufcat(dst, dstsz, src, srcsz);
897 }
898 
899 #define strbufcat_2(DST, SRC) ({ \
900 	__xnu_assert_is_array(DST, "dst is not an array"); \
901 	__xnu_assert_is_array(SRC, "src is not an array"); \
902 	(strbufcat)((DST), sizeof(DST), (SRC), sizeof(SRC)); \
903 })
904 #define strbufcat_4     (strbufcat)
905 #define strbufcat(...) __xnu_argc_overload(strbufcat, __VA_ARGS__)
906 
907 #pragma mark deprecated functions
908 #if !__has_ptrcheck && !__has_include(<__xnu_libcxx_sentinel.h>)
909 
910 /*
911  * char *strncat(char *dst, const char *src, size_t n);
912  * char *strncpy(char *dst, const char *src, size_t n);
913  *
914  * char *strcat(char *dst, const char *src);
915  * char *strcpy(char *, const char *);
916  *
917  * char *STRDUP(const char *, int);
918  */
919 
920 __deprecated_msg("use strlcat")
921 __kpi_deprecated_arm64_macos_unavailable
922 extern char *strncat(char *dst, const char *src, size_t n);
923 #if __XNU_FORTIFY_SOURCE && __has_builtin(__builtin___strncat_chk)
924 #define strncat(dst, src, n)            __builtin___strncat_chk(dst, src, n, __xnu_member_size(dst))
925 #endif
926 
927 
928 __deprecated_msg("use strlcpy")
929 __kpi_deprecated_arm64_macos_unavailable
930 extern char *strncpy(char *dst, const char *src, size_t n);
931 #if __XNU_FORTIFY_SOURCE && __has_builtin(__builtin___strncpy_chk)
932 #define strncpy(dst, src, n)            __builtin___strncpy_chk(dst, src, n, __xnu_member_size(dst))
933 #endif
934 
935 __deprecated_msg("use strlcpy")
936 __kpi_deprecated_arm64_macos_unavailable
937 extern char *strcpy(char *, const char *);
938 #if __XNU_FORTIFY_SOURCE && __has_builtin(__builtin___strcpy_chk)
939 /* rdar://103287225 */
940 #define strcpy(dst, src, len)           __builtin___strcpy_chk(dst, src, __xnu_member_size(dst))
941 #endif
942 
943 __deprecated_msg("use strlcat")
944 __kpi_deprecated_arm64_macos_unavailable
945 extern char *strcat(char *dst, const char *src);
946 #if __XNU_FORTIFY_SOURCE && __has_builtin(__builtin___strcat_chk)
947 #define strcat(dst, src)                __builtin___strcat_chk(dst, src, __xnu_member_size(dst))
948 #endif
949 
950 #if XNU_PLATFORM_MacOSX
951 #ifndef KERNEL_PRIVATE
952 extern char *STRDUP(const char *, int);
953 #endif
954 #endif /* XNU_PLATFORM_MacOSX */
955 
956 #endif /* !__has_ptrcheck && !__has_include(<__xnu_libcxx_sentinel.h>) */
957 
958 #if __has_include(<san/memintrinsics.h>)
959 #include <san/memintrinsics.h>
960 #endif
961 
962 __END_DECLS
963 
964 #endif  /* _STRING_H_ */
965 
966 #endif
967