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 | |
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 |
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 |
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 |
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 * |
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 * |
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 * |
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 |
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 |
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 * |
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 * |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 * |
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 |
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 * |
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 | |