xref: /xnu-11215/osfmk/device/subrs.c (revision 94d3b452)
1 /*
2  * Copyright (c) 2000-2020 Apple 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  * @OSF_COPYRIGHT@
30  */
31 /*
32  *(C)UNIX System Laboratories, Inc. all or some portions of this file are
33  * derived from material licensed to the University of California by
34  * American Telephone and Telegraph Co. or UNIX System Laboratories,
35  * Inc. and are reproduced herein with the permission of UNIX System
36  * Laboratories, Inc.
37  */
38 
39 /*
40  * Mach Operating System
41  * Copyright (c) 1993,1991,1990,1989,1988 Carnegie Mellon University
42  * All Rights Reserved.
43  *
44  * Permission to use, copy, modify and distribute this software and its
45  * documentation is hereby granted, provided that both the copyright
46  * notice and this permission notice appear in all copies of the
47  * software, derivative works or modified versions, and any portions
48  * thereof, and that both notices appear in supporting documentation.
49  *
50  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
51  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
52  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
53  *
54  * Carnegie Mellon requests users of this software to return to
55  *
56  *  Software Distribution Coordinator  or  [email protected]
57  *  School of Computer Science
58  *  Carnegie Mellon University
59  *  Pittsburgh PA 15213-3890
60  *
61  * any improvements or extensions that they make and grant Carnegie Mellon
62  * the rights to redistribute these changes.
63  */
64 /*
65  */
66 /*
67  * Copyright (c) 1988 Regents of the University of California.
68  * All rights reserved.
69  *
70  * Redistribution and use in source and binary forms, with or without
71  * modification, are permitted provided that the following conditions
72  * are met:
73  * 1. Redistributions of source code must retain the above copyright
74  *    notice, this list of conditions and the following disclaimer.
75  * 2. Redistributions in binary form must reproduce the above copyright
76  *    notice, this list of conditions and the following disclaimer in the
77  *    documentation and/or other materials provided with the distribution.
78  * 3. All advertising materials mentioning features or use of this software
79  *    must display the following acknowledgement:
80  *	This product includes software developed by the University of
81  *	California, Berkeley and its contributors.
82  * 4. Neither the name of the University nor the names of its contributors
83  *    may be used to endorse or promote products derived from this software
84  *    without specific prior written permission.
85  *
86  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
87  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
88  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
89  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
90  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
91  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
92  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
93  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
94  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
95  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
96  * SUCH DAMAGE.
97  */
98 
99 /*
100  * Copyright (c) 1998 Todd C. Miller <[email protected]>
101  * All rights reserved.
102  *
103  * Redistribution and use in source and binary forms, with or without
104  * modification, are permitted provided that the following conditions
105  * are met:
106  * 1. Redistributions of source code must retain the above copyright
107  *    notice, this list of conditions and the following disclaimer.
108  * 2. Redistributions in binary form must reproduce the above copyright
109  *    notice, this list of conditions and the following disclaimer in the
110  *    documentation and/or other materials provided with the distribution.
111  * 3. The name of the author may not be used to endorse or promote products
112  *    derived from this software without specific prior written permission.
113  *
114  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
115  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
116  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
117  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
118  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
119  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
120  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
121  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
122  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
123  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
124  */
125 
126 /*
127  * NOTICE: This file was modified by McAfee Research in 2004 to introduce
128  * support for mandatory and extensible security protections.  This notice
129  * is included in support of clause 2.2 (b) of the Apple Public License,
130  * Version 2.0.
131  */
132 /*
133  * Random device subroutines and stubs.
134  */
135 
136 #if KERNEL
137 
138 #if defined (__i386__) || defined (__x86_64__)
139 #include "i386/string.h"
140 #elif defined (__arm__) || defined (__arm64__)
141 #include "arm/string.h"
142 #else
143 #error architecture not supported
144 #endif
145 
146 #include <vm/vm_kern.h>
147 #include <kern/misc_protos.h>
148 #include <kern/telemetry.h>
149 #include <libsa/stdlib.h>
150 #include <sys/malloc.h>
151 #include <libkern/section_keywords.h>
152 #include <machine/string.h> /* __arch_* defines */
153 
154 /*
155  * Note to implementers, when adding new string/memory functions
156  *
157  * - add a prototype/wrapper to osfmk/libsa/string.h,
158  *   and an impl prototype to osfmk/machine/string.h.
159  *
160  * - if the function has a "chk" variant, add support to osfmk/libsa/string.h
161  *   and the implementation for the checked variant at the end of this file.
162  *
163  * - define the function with the "impl" name and wrap it inside
164  *   an #ifndef __arch_${function} block to allow each architecture
165  *   to provide an optimized version if they so desire.
166  */
167 
168 static_assert(__arch_bcopy, "architecture must provide bcopy");
169 static_assert(__arch_bzero, "architecture must provide bzero");
170 static_assert(__arch_memcpy, "architecture must provide memcpy");
171 static_assert(__arch_memmove, "architecture must provide memmove");
172 static_assert(__arch_memset, "architecture must provide memset");
173 
174 #endif /* KERNEL */
175 
176 #ifndef __arch_bcmp
177 int
bcmp_impl(const void * pa,const void * pb,size_t len)178 bcmp_impl(const void *pa, const void *pb, size_t len)
179 {
180 	const char *a = (const char *)pa;
181 	const char *b = (const char *)pb;
182 
183 	if (len == 0) {
184 		return 0;
185 	}
186 
187 	do{
188 		if (*a++ != *b++) {
189 			break;
190 		}
191 	} while (--len);
192 
193 	/*
194 	 * Check for the overflow case but continue to handle the non-overflow
195 	 * case the same way just in case someone is using the return value
196 	 * as more than zero/non-zero
197 	 */
198 	if ((len & 0xFFFFFFFF00000000ULL) && !(len & 0x00000000FFFFFFFFULL)) {
199 		return ~0;
200 	} else {
201 		return (int)len;
202 	}
203 }
204 #endif /* __arch_bcmp */
205 
206 #ifndef __arch_memcmp
207 MARK_AS_HIBERNATE_TEXT
208 int
memcmp_impl(const void * s1,const void * s2,size_t n)209 memcmp_impl(const void *s1, const void *s2, size_t n)
210 {
211 	if (n != 0) {
212 		const unsigned char *p1 = s1, *p2 = s2;
213 
214 		do {
215 			if (*p1++ != *p2++) {
216 				return *--p1 - *--p2;
217 			}
218 		} while (--n != 0);
219 	}
220 	return 0;
221 }
222 #endif /* __arch_memcmp */
223 
224 #ifndef __arch_memcmp_zero_ptr_aligned
225 unsigned long
memcmp_zero_ptr_aligned_impl(const void * addr,size_t size)226 memcmp_zero_ptr_aligned_impl(const void *addr, size_t size)
227 {
228 	const uint64_t *p = (const uint64_t *)addr;
229 	uint64_t a = p[0];
230 
231 	static_assert(sizeof(unsigned long) == sizeof(uint64_t),
232 	    "uint64_t is not the same size as unsigned long");
233 
234 	if (size < 4 * sizeof(uint64_t)) {
235 		if (size > 1 * sizeof(uint64_t)) {
236 			a |= p[1];
237 			if (size > 2 * sizeof(uint64_t)) {
238 				a |= p[2];
239 			}
240 		}
241 	} else {
242 		size_t count = size / sizeof(uint64_t);
243 		uint64_t b = p[1];
244 		uint64_t c = p[2];
245 		uint64_t d = p[3];
246 
247 		/*
248 		 * note: for sizes not a multiple of 32 bytes, this will load
249 		 * the bytes [size % 32 .. 32) twice which is ok
250 		 */
251 		while (count > 4) {
252 			count -= 4;
253 			a |= p[count + 0];
254 			b |= p[count + 1];
255 			c |= p[count + 2];
256 			d |= p[count + 3];
257 		}
258 
259 		a |= b | c | d;
260 	}
261 
262 	return a;
263 }
264 #endif /* __arch_memcmp_zero_ptr_aligned */
265 
266 /*
267  * Abstract:
268  * strlen returns the number of characters in "string" preceeding
269  * the terminating null character.
270  */
271 #ifndef __arch_strlen
272 size_t
strlen_impl(const char * string)273 strlen_impl(const char *string)
274 {
275 	const char *ret = string;
276 
277 	while (*string++ != '\0') {
278 		continue;
279 	}
280 	return (size_t)(string - 1 - ret);
281 }
282 #endif /* __arch_strlen */
283 
284 /*
285  * Does the same thing as strlen, except only looks up
286  * to max chars inside the buffer.
287  * Taken from archive/kern-stuff/sbf_machine.c in
288  * seatbelt.
289  * inputs:
290  *      s	string whose length is to be measured
291  *	max	maximum length of string to search for null
292  * outputs:
293  *	length of s or max; whichever is smaller
294  */
295 #ifndef __arch_strnlen
296 size_t
strnlen_impl(const char * s,size_t max)297 strnlen_impl(const char *s, size_t max)
298 {
299 	const char *es = s + max, *p = s;
300 	while (p != es && *p) {
301 		p++;
302 	}
303 
304 	return (size_t)(p - s);
305 }
306 #endif /* __arch_strlen */
307 
308 /*
309  * Abstract:
310  *      strcmp (s1, s2) compares the strings "s1" and "s2".
311  *      It returns 0 if the strings are identical. It returns
312  *      > 0 if the first character that differs in the two strings
313  *      is larger in s1 than in s2 or if s1 is longer than s2 and
314  *      the contents are identical up to the length of s2.
315  *      It returns < 0 if the first differing character is smaller
316  *      in s1 than in s2 or if s1 is shorter than s2 and the
317  *      contents are identical upto the length of s1.
318  * Deprecation Warning:
319  *	strcmp() is being deprecated. Please use strncmp() instead.
320  */
321 #ifndef __arch_strcmp
322 int
strcmp_impl(const char * s1,const char * s2)323 strcmp_impl(const char *s1, const char *s2)
324 {
325 	int a, b;
326 
327 	do {
328 		a = *s1++;
329 		b = *s2++;
330 		if (a != b) {
331 			return a - b;     /* includes case when
332 			                   *  'a' is zero and 'b' is not zero
333 			                   *  or vice versa */
334 		}
335 	} while (a != '\0');
336 
337 	return 0;       /* both are zero */
338 }
339 #endif /* __arch_strcmp */
340 
341 /*
342  * Abstract:
343  *      strncmp (s1, s2, n) compares the strings "s1" and "s2"
344  *      in exactly the same way as strcmp does.  Except the
345  *      comparison runs for at most "n" characters.
346  */
347 
348 #ifndef __arch_strncmp
349 int
strncmp_impl(const char * s1,const char * s2,size_t n)350 strncmp_impl(const char *s1, const char *s2, size_t n)
351 {
352 	return strbufcmp_impl(s1, n, s2, n);
353 }
354 #endif /* __arch_strncmp */
355 
356 #ifndef __arch_strlcmp
357 int
strlcmp_impl(const char * s1,const char * s2,size_t n)358 strlcmp_impl(const char *s1, const char *s2, size_t n)
359 {
360 	return strbufcmp_impl(s1, n, s2, strlen(s2));
361 }
362 #endif
363 
364 #ifndef __arch_strbufcmp
365 int
strbufcmp_impl(const char * __counted_by (alen)a,size_t alen,const char * __counted_by (blen)b,size_t blen)366 strbufcmp_impl(
367 	const char *__counted_by(alen)a,
368 	size_t alen,
369 	const char *__counted_by(blen)b,
370 	size_t blen)
371 {
372 	int ca, cb;
373 	size_t i, len;
374 
375 	len = alen < blen ? alen : blen;
376 	for (i = 0; i < len; ++i) {
377 		ca = a[i];
378 		cb = b[i];
379 		if (ca != cb) {
380 			return ca - cb;   /* includes case when
381 			                   *  'a' is zero and 'b' is not zero
382 			                   *  or vice versa */
383 		}
384 		if (ca == '\0') {
385 			return 0;       /* both are zero */
386 		}
387 	}
388 
389 	/* if either string is not NUL-terminated, pretend the next character is a
390 	 * NUL */
391 	if (alen < blen) {
392 		return 0 - b[len];
393 	}
394 	if (blen < alen) {
395 		return a[len] - 0;
396 	}
397 	return 0;
398 }
399 #endif /* __arch_strbufcmp */
400 
401 #ifndef __arch_strprefix
402 /*
403  * Return TRUE(1) if string 2 is a prefix of string 1.
404  */
405 int
strprefix_impl(const char * s1,const char * s2)406 strprefix_impl(const char *s1, const char *s2)
407 {
408 	int c;
409 
410 	while ((c = *s2++) != '\0') {
411 		if (c != *s1++) {
412 			return 0;
413 		}
414 	}
415 	return 1;
416 }
417 #endif /* __arch_strprefix */
418 
419 
420 //
421 // Lame implementation just for use by strcasecmp/strncasecmp
422 //
423 __header_always_inline int
tolower(int ch)424 tolower(int ch)
425 {
426 	if (ch >= 'A' && ch <= 'Z') {
427 		ch = 'a' + (ch - 'A');
428 	}
429 
430 	return ch;
431 }
432 
433 #ifndef __arch_strcasecmp
434 int
strcasecmp_impl(const char * s1,const char * s2)435 strcasecmp_impl(const char *s1, const char *s2)
436 {
437 	const unsigned char *us1 = (const u_char *)s1,
438 	    *us2 = (const u_char *)s2;
439 
440 	while (tolower(*us1) == tolower(*us2++)) {
441 		if (*us1++ == '\0') {
442 			return 0;
443 		}
444 	}
445 	return tolower(*us1) - tolower(*--us2);
446 }
447 #endif /* __arch_strcasecmp */
448 
449 #ifndef __arch_strncasecmp
450 int
strncasecmp_impl(const char * s1,const char * s2,size_t n)451 strncasecmp_impl(const char *s1, const char *s2, size_t n)
452 {
453 	return strbufcasecmp_impl(s1, n, s2, n);
454 }
455 #endif /* __arch_strncasecmp */
456 
457 #ifndef __arch_strlcasecmp
458 int
strlcasecmp_impl(const char * s1,const char * s2,size_t n)459 strlcasecmp_impl(const char *s1, const char *s2, size_t n)
460 {
461 	return strbufcasecmp_impl(s1, n, s2, strlen(s2));
462 }
463 #endif
464 
465 #ifndef __arch_strbufcasecmp
466 int
strbufcasecmp_impl(const char * __counted_by (alen)a,size_t alen,const char * __counted_by (blen)b,size_t blen)467 strbufcasecmp_impl(
468 	const char *__counted_by(alen)a,
469 	size_t alen,
470 	const char *__counted_by(blen)b,
471 	size_t blen)
472 {
473 	int ca, cb;
474 	size_t i, len;
475 
476 	len = alen < blen ? alen : blen;
477 	for (i = 0; i < len; ++i) {
478 		ca = tolower(a[i]);
479 		cb = tolower(b[i]);
480 		if (ca != cb) {
481 			return ca - cb; /* includes case when
482 			                 *  'a' is zero and 'b' is not zero
483 			                 *  or vice versa */
484 		}
485 		if (ca == '\0') {
486 			return 0;       /* both are zero */
487 		}
488 	}
489 
490 	/* if either string is not NUL-terminated, pretend the next character is a
491 	 * NUL */
492 	if (alen < blen) {
493 		return 0 - tolower(b[len]);
494 	}
495 	if (blen < alen) {
496 		return tolower(a[len]) - 0;
497 	}
498 	return 0;
499 }
500 #endif /* __arch_strbufcasecmp */
501 
502 #ifndef __arch_strchr
503 char *
strchr_impl(const char * s,int c)504 strchr_impl(const char *s, int c)
505 {
506 	if (!s) {
507 		return NULL;
508 	}
509 
510 	do {
511 		if (*s == c) {
512 			return __CAST_AWAY_QUALIFIER(s, const, char *);
513 		}
514 	} while (*s++);
515 
516 	return NULL;
517 }
518 #endif /* __arch_strchr */
519 
520 #ifndef __arch_strrchr
521 char *
strrchr_impl(const char * s,int c)522 strrchr_impl(const char *s, int c)
523 {
524 	const char *found = NULL;
525 
526 	if (!s) {
527 		return NULL;
528 	}
529 
530 	do {
531 		if (*s == c) {
532 			found = s;
533 		}
534 	} while (*s++);
535 
536 	return __CAST_AWAY_QUALIFIER(found, const, char *);
537 }
538 #endif /* __arch_strchr */
539 
540 #if CONFIG_VSPRINTF
541 /*
542  * Abstract:
543  *      strcpy copies the contents of the string "from" including
544  *      the null terminator to the string "to". A pointer to "to"
545  *      is returned.
546  * Deprecation Warning:
547  *	strcpy() is being deprecated. Please use strlcpy() instead.
548  */
549 char *
strcpy_impl(char * to,const char * from)550 strcpy_impl(char *to, const char *from)
551 {
552 	char *ret = to;
553 
554 	while ((*to++ = *from++) != '\0') {
555 		continue;
556 	}
557 
558 	return ret;
559 }
560 #endif
561 
562 /*
563  * Abstract:
564  *      strncpy copies "count" characters from the "from" string to
565  *      the "to" string. If "from" contains less than "count" characters
566  *      "to" will be padded with null characters until exactly "count"
567  *      characters have been written. The return value is a pointer
568  *      to the "to" string.
569  */
570 #ifndef __arch_strncpy
571 char *
strncpy_impl(char * dst,const char * src,size_t maxlen)572 strncpy_impl(char * dst, const char * src, size_t maxlen)
573 {
574 	const size_t srclen = strnlen_impl(src, maxlen);
575 	if (srclen < maxlen) {
576 		memcpy_impl(dst, src, srclen);
577 		memset_impl(dst + srclen, 0, maxlen - srclen);
578 	} else {
579 		memcpy_impl(dst, src, maxlen);
580 	}
581 	return dst;
582 }
583 #endif /* __arch_strncpy */
584 
585 /*
586  * atoi:
587  *
588  *      This function converts an ascii string into an integer.
589  *
590  * input        : string
591  * output       : a number
592  */
593 
594 int
atoi(const char * cp)595 atoi(const char *cp)
596 {
597 	int     number;
598 
599 	for (number = 0; ('0' <= *cp) && (*cp <= '9'); cp++) {
600 		number = (number * 10) + (*cp - '0');
601 	}
602 
603 	return number;
604 }
605 
606 /*
607  * convert an integer to an ASCII string.
608  * inputs:
609  *	num	integer to be converted
610  *	str	string pointer.
611  *
612  * outputs:
613  *	pointer to string start.
614  */
615 
616 char *
itoa(int num,char * str)617 itoa(int num, char *str)
618 {
619 	char    digits[11];
620 	char *dp;
621 	char *cp = str;
622 
623 	if (num == 0) {
624 		*cp++ = '0';
625 	} else {
626 		dp = digits;
627 		while (num) {
628 			*dp++ = '0' + num % 10;
629 			num /= 10;
630 		}
631 		while (dp != digits) {
632 			*cp++ = *--dp;
633 		}
634 	}
635 	*cp++ = '\0';
636 
637 	return str;
638 }
639 
640 #if CONFIG_VSPRINTF
641 /*
642  * Deprecation Warning:
643  *	strcat() is being deprecated. Please use strlcat() instead.
644  */
645 char *
strcat_impl(char * dest,const char * src)646 strcat_impl(char *dest, const char *src)
647 {
648 	char *old = dest;
649 
650 	while (*dest) {
651 		++dest;
652 	}
653 	while ((*dest++ = *src++)) {
654 		;
655 	}
656 	return old;
657 }
658 #endif
659 
660 /*
661  * Appends src to string dst of size siz (unlike strncat, siz is the
662  * full size of dst, not space left).  At most siz-1 characters
663  * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
664  * Returns strlen(src) + MIN(siz, strlen(initial dst)).
665  * If retval >= siz, truncation occurred.
666  */
667 #ifndef __arch_strlcat
668 size_t
strlcat_impl(char * dst,const char * src,size_t siz)669 strlcat_impl(char *dst, const char *src, size_t siz)
670 {
671 	char *d = dst;
672 	const char *s = src;
673 	size_t n = siz;
674 	size_t dlen;
675 
676 	/* Find the end of dst and adjust bytes left but don't go past end */
677 	while (n-- != 0 && *d != '\0') {
678 		d++;
679 	}
680 	dlen = (size_t)(d - dst);
681 	n = siz - dlen;
682 
683 	if (n == 0) {
684 		return dlen + strlen_impl(s);
685 	}
686 	while (*s != '\0') {
687 		if (n != 1) {
688 			*d++ = *s;
689 			n--;
690 		}
691 		s++;
692 	}
693 	*d = '\0';
694 
695 	return dlen + (size_t)(s - src);       /* count does not include NUL */
696 }
697 #endif /* __arch_strlcat */
698 
699 /*
700  * Append src string to dst. The operation stops once *any* of the following
701  * conditions is met:
702  *  * when `dst` is filled with `dstsz` characters;
703  *  * when `srcsz` characters have been copied;
704  *  * when a NUL character has been copied from `src` to `dst`.
705  * `dst` is always NUL-terminated, truncating `src` as needed.
706  * If `dstsz` is 0, the function returns NULL. Otherwise, it returns `dst`,
707  * regardless of whether there was free space in dst to append any characters.
708  * This function is most useful to concatenate a fixed-size string to another.
709  */
710 #ifndef __arch_strbufcat
711 const char *__null_terminated
strbufcat_impl(char * __counted_by (dstsz)dst,size_t dstsz,const char * __counted_by (srcsz)src,size_t srcsz)712 strbufcat_impl(
713 	char *__counted_by(dstsz)dst,
714 	size_t dstsz,
715 	const char *__counted_by(srcsz)src,
716 	size_t srcsz)
717 {
718 	size_t len;
719 	if (dstsz == 0) {
720 		return NULL;
721 	}
722 
723 	len = strnlen_impl(dst, dstsz);
724 	strbufcpy_impl(dst + len, dstsz - len, src, srcsz);
725 	return dst;
726 }
727 #endif /* __arch_strbufcat */
728 
729 /*
730  * Copy src to string dst of size siz.  At most siz-1 characters
731  * will be copied.  Always NUL terminates (unless siz == 0).
732  * Returns strlen(src); if retval >= siz, truncation occurred.
733  */
734 #ifndef __arch_strlcpy
735 size_t
strlcpy_impl(char * dst,const char * src,size_t maxlen)736 strlcpy_impl(char * dst, const char * src, size_t maxlen)
737 {
738 	const size_t srclen = strlen_impl(src);
739 	if (srclen + 1 < maxlen) {
740 		memcpy_impl(dst, src, srclen + 1);
741 	} else if (maxlen != 0) {
742 		memcpy_impl(dst, src, maxlen - 1);
743 		dst[maxlen - 1] = '\0';
744 	}
745 	return srclen;
746 }
747 #endif /* __arch_strlcpy */
748 
749 /*
750  * Copy src string to dst. The copy stops once *any* of the following conditions
751  * is met:
752  *  * when `dstsz` characters have been copied;
753  *  * when `srcsz` characters have been copied;
754  *  * when a NUL character has been copied from `src` to `dst`.
755  * `dst` is always NUL-terminated, truncating `src` as needed.
756  * If `dstsz` is 0, the function returns NULL. Otherwise, it returns `dst`.
757  * This function is most useful to copy a fixed-size string from one buffer to
758  * another.
759  */
760 #ifndef __arch_strbufcpy
761 const char *__null_terminated
strbufcpy_impl(char * __counted_by (dstsz)dst,size_t dstsz,const char * __counted_by (srcsz)src,size_t srcsz)762 strbufcpy_impl(
763 	char *__counted_by(dstsz)dst,
764 	size_t dstsz,
765 	const char *__counted_by(srcsz)src,
766 	size_t srcsz)
767 {
768 	size_t copymax;
769 
770 	if (dstsz == 0) {
771 		return NULL;
772 	}
773 
774 	copymax = strnlen_impl(src, srcsz);
775 	if (copymax < dstsz) {
776 		memmove_impl(dst, src, copymax);
777 		dst[copymax] = 0;
778 	} else {
779 		memmove_impl(dst, src, dstsz);
780 		dst[dstsz - 1] = 0;
781 	}
782 	return __unsafe_forge_null_terminated(const char *__null_terminated, dst);
783 }
784 #endif /* __arch_strbufcpy */
785 
786 #ifndef __arch_strncat
787 char *
strncat_impl(char * s1,const char * s2,size_t n)788 strncat_impl(char *s1, const char *s2, size_t n)
789 {
790 	if (n != 0) {
791 		char *d = s1;
792 		const char *s = s2;
793 
794 		while (*d != 0) {
795 			d++;
796 		}
797 		do {
798 			if ((*d = *s++) == '\0') {
799 				break;
800 			}
801 			d++;
802 		} while (--n != 0);
803 		*d = '\0';
804 	}
805 
806 	return __CAST_AWAY_QUALIFIER(s1, const, char *);
807 }
808 #endif /* __arch_strncat */
809 
810 #ifndef __arch_strnstr
811 char *
strnstr_impl(const char * s,const char * find,size_t slen)812 strnstr_impl(const char *s, const char *find, size_t slen)
813 {
814 	char c, sc;
815 	size_t len;
816 
817 	if ((c = *find++) != '\0') {
818 		len = strlen_impl(find);
819 		do {
820 			do {
821 				if ((sc = *s++) == '\0' || slen-- < 1) {
822 					return NULL;
823 				}
824 			} while (sc != c);
825 			if (len > slen) {
826 				return NULL;
827 			}
828 		} while (strncmp_impl(s, find, len) != 0);
829 		s--;
830 	}
831 
832 	return __CAST_AWAY_QUALIFIER(s, const, char *);
833 }
834 #endif /* __arch_strnstr */
835 
836 void * __memcpy_chk(void *dst, void const *src, size_t s, size_t chk_size);
837 void * __memmove_chk(void *dst, void const *src, size_t s, size_t chk_size);
838 void * __memset_chk(void *dst, int c, size_t s, size_t chk_size);
839 size_t __strlcpy_chk(char *dst, char const *src, size_t s, size_t chk_size);
840 size_t __strlcat_chk(char *dst, char const *src, size_t s, size_t chk_size);
841 char * __strncpy_chk(char *restrict dst, char *restrict src, size_t len, size_t chk_size);
842 char * __strncat_chk(char *restrict dst, const char *restrict src, size_t len, size_t chk_size);
843 char * __strcpy_chk(char *restrict dst, const char *restrict src, size_t chk_size);
844 char * __strcat_chk(char *restrict dst, const char *restrict src, size_t chk_size);
845 
846 void *
__memcpy_chk(void * dst,void const * src,size_t s,size_t chk_size)847 __memcpy_chk(void *dst, void const *src, size_t s, size_t chk_size)
848 {
849 	if (__improbable(chk_size < s)) {
850 		panic("__memcpy_chk object size check failed: dst %p, src %p, (%zu < %zu)", dst, src, chk_size, s);
851 	}
852 	return memcpy_impl(dst, src, s);
853 }
854 
855 void *
__memmove_chk(void * dst,void const * src,size_t s,size_t chk_size)856 __memmove_chk(void *dst, void const *src, size_t s, size_t chk_size)
857 {
858 	if (__improbable(chk_size < s)) {
859 		panic("__memmove_chk object size check failed: dst %p, src %p, (%zu < %zu)", dst, src, chk_size, s);
860 	}
861 	return memmove_impl(dst, src, s);
862 }
863 
864 void *
__memset_chk(void * dst,int c,size_t s,size_t chk_size)865 __memset_chk(void *dst, int c, size_t s, size_t chk_size)
866 {
867 	if (__improbable(chk_size < s)) {
868 		panic("__memset_chk object size check failed: dst %p, c %c, (%zu < %zu)", dst, c, chk_size, s);
869 	}
870 	return memset_impl(dst, c, s);
871 }
872 
873 size_t
__strlcat_chk(char * dst,char const * src,size_t s,size_t chk_size)874 __strlcat_chk(char *dst, char const *src, size_t s, size_t chk_size)
875 {
876 	if (__improbable(chk_size < s)) {
877 		panic("__strlcat_chk object size check failed: dst %p, src %p, (%zu < %zu)", dst, src, chk_size, s);
878 	}
879 	return strlcat_impl(dst, src, s);
880 }
881 
882 size_t
__strlcpy_chk(char * dst,char const * src,size_t s,size_t chk_size)883 __strlcpy_chk(char *dst, char const *src, size_t s, size_t chk_size)
884 {
885 	if (__improbable(chk_size < s)) {
886 		panic("__strlcpy_chk object size check failed: dst %p, src %p, (%zu < %zu)", dst, src, chk_size, s);
887 	}
888 	return strlcpy_impl(dst, src, s);
889 }
890 
891 char *
__strncpy_chk(char * restrict dst,char * restrict src,size_t len,size_t chk_size)892 __strncpy_chk(char *restrict dst, char *restrict src,
893     size_t len, size_t chk_size)
894 {
895 	if (__improbable(chk_size < len)) {
896 		panic("__strncpy_chk object size check failed: dst %p, src %p, (%zu < %zu)", dst, src, chk_size, len);
897 	}
898 	return strncpy_impl(dst, src, len);
899 }
900 
901 char *
__strncat_chk(char * restrict dst,const char * restrict src,size_t len,size_t chk_size)902 __strncat_chk(char *restrict dst, const char *restrict src,
903     size_t len, size_t chk_size)
904 {
905 	size_t len1 = strlen_impl(dst);
906 	size_t len2 = strnlen_impl(src, len);
907 	if (__improbable(chk_size < len1 + len2 + 1)) {
908 		panic("__strncat_chk object size check failed: dst %p, src %p, (%zu < %zu + %zu + 1)", dst, src, chk_size, len1, len2);
909 	}
910 	return strncat_impl(dst, src, len);
911 }
912 
913 char *
__strcpy_chk(char * restrict dst,const char * restrict src,size_t chk_size)914 __strcpy_chk(char *restrict dst, const char *restrict src, size_t chk_size)
915 {
916 	size_t len = strlen_impl(src);
917 	if (__improbable(chk_size < len + 1)) {
918 		panic("__strcpy_chk object size check failed: dst %p, src %p, (%zu < %zu + 1)", dst, src, chk_size, len);
919 	}
920 	memcpy_impl(dst, src, len + 1);
921 	return dst;
922 }
923 
924 char *
__strcat_chk(char * restrict dst,const char * restrict src,size_t chk_size)925 __strcat_chk(char *restrict dst, const char *restrict src, size_t chk_size)
926 {
927 	size_t len1 = strlen_impl(dst);
928 	size_t len2 = strlen_impl(src);
929 	size_t required_len = len1 + len2 + 1;
930 	if (__improbable(chk_size < required_len)) {
931 		panic("__strcat_chk object size check failed: dst %p, src %p, (%zu < %zu + %zu + 1)", dst, src, chk_size, len1, len2);
932 	}
933 	memcpy_impl(dst + len1, src, len2 + 1);
934 	return dst;
935 }
936