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