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(code: 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
283extern 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
286int
287bcmp(
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
309extern 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
312int
313memcmp(
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 */
341extern unsigned long memcmp_zero_ptr_aligned(const void *s __sized_by(n), size_t n) __stateful_pure;
342#endif
343
344
345extern int timingsafe_bcmp(const void *b1 __sized_by(n), const void *b2 __sized_by(n), size_t n);
346
347
348extern void bzero(void *s __sized_by(n), size_t n);
349
350__xnu_string_inline
351void
352bzero(
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
370extern void *memset(void *s __sized_by(n), int c, size_t n);
371
372__xnu_string_inline
373void *
374__sized_by(n)
375memset(
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
395extern int memset_s(void *s __sized_by(smax), size_t smax, int c, size_t n);
396
397
398extern void *memmove(void *dst __sized_by(n), const void *src __sized_by(n), size_t n);
399
400__xnu_string_inline
401void *
402__sized_by(n)
403memmove(
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
425void *
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
449extern void bcopy(const void *src __sized_by(n), void *dst __sized_by(n), size_t n);
450
451__xnu_string_inline
452void
453bcopy(
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
464void
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
476extern void *memcpy(void *dst __sized_by(n), const void *src __sized_by(n), size_t n);
477
478__xnu_string_inline
479void *
480__sized_by(n)
481memcpy(
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
492void *
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
507extern size_t strlen(const char *__null_terminated s) __stateful_pure;
508
509#if __has_builtin(__builtin_strlen)
510__xnu_string_inline __stateful_pure
511size_t
512strlen(const char * /* __null_terminated */ const s __xnu_force_overload)
513{
514 return __builtin_strlen(s);
515}
516#endif
517
518
519extern 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
523size_t
524strnlen(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
540extern 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
544int
545strcmp(
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")
556extern 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
561int
562strncmp(
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 */
576extern 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
580int
581strlcmp(
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 */
601extern 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
604int
605strbufcmp(
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
631extern int strprefix(const char *__null_terminated s1, const char *__null_terminated s2) __stateful_pure;
632
633
634extern 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
638int
639strcasecmp(
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")
649extern 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
654int
655strncasecmp(
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 */
669extern int strlcasecmp(const char *__counted_by(n)s1, const char *s2, size_t n) __stateful_pure;
670
671__xnu_string_inline __stateful_pure
672int
673strlcasecmp(
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 */
692extern 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
695int
696strbufcasecmp(
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
724char *__null_terminated
725strchr(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 */
733extern 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
737char *__null_terminated
738strrchr(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
746extern char *__null_terminated strnstr(const char *__null_terminated s, const char *__null_terminated find, size_t slen) __stateful_pure;
747
748
749extern size_t strlcpy(char *__counted_by(n) dst, const char *__null_terminated src, size_t n);
750
751__xnu_string_inline
752size_t
753strlcpy(
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 */
778extern 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
786const char *
787strbufcpy(
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
814extern size_t strlcat(char *__counted_by(n) dst, const char *__null_terminated src, size_t n);
815
816__xnu_string_inline
817size_t
818strlcat(
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 */
843extern 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
851const char *
852strbufcat(
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
894extern 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
902extern 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
909extern 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
917extern 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
924extern 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