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