xref: /xnu-8796.101.5/osfmk/device/subrs.c (revision aca3beaa3dfbd42498b42c5e5ce20a938e6554e5)
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 #include <vm/vm_kern.h>
137 #include <kern/misc_protos.h>
138 #include <libsa/stdlib.h>
139 #include <sys/malloc.h>
140 #include <libkern/section_keywords.h>
141 #include <machine/string.h> /* __arch_* defines */
142 
143 /*
144  * Note to implementers, when adding new string/memory functions
145  *
146  * - add a prototype/wrapper to osfmk/libsa/string.h,
147  *   and an impl prototype to osfmk/machine/string.h.
148  *
149  * - if the function has a "chk" variant, add support to osfmk/libsa/string.h
150  *   and the implementation for the checked variant at the end of this file.
151  *
152  * - define the function with the "impl" name and wrap it inside
153  *   an #ifndef __arch_${function} block to allow each architecture
154  *   to provide an optimized version if they so desire.
155  */
156 
157 static_assert(__arch_bcopy, "architecture must provide bcopy");
158 static_assert(__arch_bzero, "architecture must provide bzero");
159 static_assert(__arch_memcpy, "architecture must provide memcpy");
160 static_assert(__arch_memset, "architecture must provide memset");
161 
162 #ifndef __arch_bcmp
163 int
bcmp_impl(const void * pa,const void * pb,size_t len)164 bcmp_impl(const void *pa, const void *pb, size_t len)
165 {
166 	const char *a = (const char *)pa;
167 	const char *b = (const char *)pb;
168 
169 	if (len == 0) {
170 		return 0;
171 	}
172 
173 	do{
174 		if (*a++ != *b++) {
175 			break;
176 		}
177 	} while (--len);
178 
179 	/*
180 	 * Check for the overflow case but continue to handle the non-overflow
181 	 * case the same way just in case someone is using the return value
182 	 * as more than zero/non-zero
183 	 */
184 	if ((len & 0xFFFFFFFF00000000ULL) && !(len & 0x00000000FFFFFFFFULL)) {
185 		return 0xFFFFFFFFL;
186 	} else {
187 		return (int)len;
188 	}
189 }
190 #endif /* __arch_bcmp */
191 
192 #ifndef __arch_memcmp
193 MARK_AS_HIBERNATE_TEXT
194 int
memcmp_impl(const void * s1,const void * s2,size_t n)195 memcmp_impl(const void *s1, const void *s2, size_t n)
196 {
197 	if (n != 0) {
198 		const unsigned char *p1 = s1, *p2 = s2;
199 
200 		do {
201 			if (*p1++ != *p2++) {
202 				return *--p1 - *--p2;
203 			}
204 		} while (--n != 0);
205 	}
206 	return 0;
207 }
208 #endif /* __arch_memcmp */
209 
210 #ifndef __arch_memcmp_zero_ptr_aligned
211 unsigned long
memcmp_zero_ptr_aligned(const void * addr,size_t size)212 memcmp_zero_ptr_aligned(const void *addr, size_t size)
213 {
214 	const uint64_t *p = (const uint64_t *)addr;
215 	uint64_t a = p[0];
216 
217 	static_assert(sizeof(unsigned long) == sizeof(uint64_t));
218 
219 	if (size < 4 * sizeof(uint64_t)) {
220 		if (size > 1 * sizeof(uint64_t)) {
221 			a |= p[1];
222 			if (size > 2 * sizeof(uint64_t)) {
223 				a |= p[2];
224 			}
225 		}
226 	} else {
227 		size_t count = size / sizeof(uint64_t);
228 		uint64_t b = p[1];
229 		uint64_t c = p[2];
230 		uint64_t d = p[3];
231 
232 		/*
233 		 * note: for sizes not a multiple of 32 bytes, this will load
234 		 * the bytes [size % 32 .. 32) twice which is ok
235 		 */
236 		while (count > 4) {
237 			count -= 4;
238 			a |= p[count + 0];
239 			b |= p[count + 1];
240 			c |= p[count + 2];
241 			d |= p[count + 3];
242 		}
243 
244 		a |= b | c | d;
245 	}
246 
247 	return a;
248 }
249 #endif /* __arch_memcmp_zero_ptr_aligned */
250 
251 #ifndef __arch_memmove
252 /* memcpy is provided as a linker alias */
253 void *
memmove_impl(void * dst,const void * src,size_t ulen)254 memmove_impl(void *dst, const void *src, size_t ulen)
255 {
256 	bcopy_impl(src, dst, ulen);
257 	return dst;
258 }
259 #endif /* __arch_memmove */
260 
261 /*
262  * Abstract:
263  * strlen returns the number of characters in "string" preceeding
264  * the terminating null character.
265  */
266 #ifndef __arch_strlen
267 size_t
strlen_impl(const char * string)268 strlen_impl(const char *string)
269 {
270 	const char *ret = string;
271 
272 	while (*string++ != '\0') {
273 		continue;
274 	}
275 	return string - 1 - ret;
276 }
277 #endif /* __arch_strlen */
278 
279 /*
280  * Does the same thing as strlen, except only looks up
281  * to max chars inside the buffer.
282  * Taken from archive/kern-stuff/sbf_machine.c in
283  * seatbelt.
284  * inputs:
285  *      s	string whose length is to be measured
286  *	max	maximum length of string to search for null
287  * outputs:
288  *	length of s or max; whichever is smaller
289  */
290 #ifndef __arch_strnlen
291 size_t
strnlen_impl(const char * s,size_t max)292 strnlen_impl(const char *s, size_t max)
293 {
294 	const char *es = s + max, *p = s;
295 	while (p != es && *p) {
296 		p++;
297 	}
298 
299 	return p - s;
300 }
301 #endif /* __arch_strlen */
302 
303 /*
304  * Abstract:
305  *      strcmp (s1, s2) compares the strings "s1" and "s2".
306  *      It returns 0 if the strings are identical. It returns
307  *      > 0 if the first character that differs in the two strings
308  *      is larger in s1 than in s2 or if s1 is longer than s2 and
309  *      the contents are identical up to the length of s2.
310  *      It returns < 0 if the first differing character is smaller
311  *      in s1 than in s2 or if s1 is shorter than s2 and the
312  *      contents are identical upto the length of s1.
313  * Deprecation Warning:
314  *	strcmp() is being deprecated. Please use strncmp() instead.
315  */
316 #ifndef __arch_strcmp
317 int
strcmp_impl(const char * s1,const char * s2)318 strcmp_impl(const char *s1, const char *s2)
319 {
320 	unsigned int a, b;
321 
322 	do {
323 		a = *s1++;
324 		b = *s2++;
325 		if (a != b) {
326 			return a - b;     /* includes case when
327 			                   *  'a' is zero and 'b' is not zero
328 			                   *  or vice versa */
329 		}
330 	} while (a != '\0');
331 
332 	return 0;       /* both are zero */
333 }
334 #endif /* __arch_strcmp */
335 
336 /*
337  * Abstract:
338  *      strncmp (s1, s2, n) compares the strings "s1" and "s2"
339  *      in exactly the same way as strcmp does.  Except the
340  *      comparison runs for at most "n" characters.
341  */
342 
343 #ifndef __arch_strncmp
344 int
strncmp_impl(const char * s1,const char * s2,size_t n)345 strncmp_impl(const char *s1, const char *s2, size_t n)
346 {
347 	unsigned int a, b;
348 
349 	while (n != 0) {
350 		a = *s1++;
351 		b = *s2++;
352 		if (a != b) {
353 			return a - b;     /* includes case when
354 			                   *  'a' is zero and 'b' is not zero
355 			                   *  or vice versa */
356 		}
357 		if (a == '\0') {
358 			return 0;       /* both are zero */
359 		}
360 		n--;
361 	}
362 
363 	return 0;
364 }
365 #endif /* __arch_strncmp */
366 
367 /*
368  * Return TRUE(1) if string 2 is a prefix of string 1.
369  */
370 int
strprefix(const char * s1,const char * s2)371 strprefix(const char *s1, const char *s2)
372 {
373 	int c;
374 
375 	while ((c = *s2++) != '\0') {
376 		if (c != *s1++) {
377 			return 0;
378 		}
379 	}
380 	return 1;
381 }
382 
383 
384 //
385 // Lame implementation just for use by strcasecmp/strncasecmp
386 //
387 __header_always_inline int
tolower(unsigned char ch)388 tolower(unsigned char ch)
389 {
390 	if (ch >= 'A' && ch <= 'Z') {
391 		ch = 'a' + (ch - 'A');
392 	}
393 
394 	return ch;
395 }
396 
397 #ifndef __arch_strcasecmp
398 int
strcasecmp_impl(const char * s1,const char * s2)399 strcasecmp_impl(const char *s1, const char *s2)
400 {
401 	const unsigned char *us1 = (const u_char *)s1,
402 	    *us2 = (const u_char *)s2;
403 
404 	while (tolower(*us1) == tolower(*us2++)) {
405 		if (*us1++ == '\0') {
406 			return 0;
407 		}
408 	}
409 	return tolower(*us1) - tolower(*--us2);
410 }
411 #endif /* __arch_strcasecmp */
412 
413 #ifndef __arch_strncasecmp
414 int
strncasecmp_impl(const char * s1,const char * s2,size_t n)415 strncasecmp_impl(const char *s1, const char *s2, size_t n)
416 {
417 	if (n != 0) {
418 		const unsigned char *us1 = (const u_char *)s1,
419 		    *us2 = (const u_char *)s2;
420 
421 		do {
422 			if (tolower(*us1) != tolower(*us2++)) {
423 				return tolower(*us1) - tolower(*--us2);
424 			}
425 			if (*us1++ == '\0') {
426 				break;
427 			}
428 		} while (--n != 0);
429 	}
430 	return 0;
431 }
432 #endif /* __arch_strncasecmp */
433 
434 #ifndef __arch_strchr
435 char *
strchr_impl(const char * s,int c)436 strchr_impl(const char *s, int c)
437 {
438 	if (!s) {
439 		return NULL;
440 	}
441 
442 	do {
443 		if (*s == c) {
444 			return __CAST_AWAY_QUALIFIER(s, const, char *);
445 		}
446 	} while (*s++);
447 
448 	return NULL;
449 }
450 #endif /* __arch_strchr */
451 
452 #ifndef __arch_strrchr
453 char *
strrchr_impl(const char * s,int c)454 strrchr_impl(const char *s, int c)
455 {
456 	const char *found = NULL;
457 
458 	if (!s) {
459 		return NULL;
460 	}
461 
462 	do {
463 		if (*s == c) {
464 			found = s;
465 		}
466 	} while (*s++);
467 
468 	return __CAST_AWAY_QUALIFIER(found, const, char *);
469 }
470 #endif /* __arch_strchr */
471 
472 #if CONFIG_VSPRINTF
473 /*
474  * Abstract:
475  *      strcpy copies the contents of the string "from" including
476  *      the null terminator to the string "to". A pointer to "to"
477  *      is returned.
478  * Deprecation Warning:
479  *	strcpy() is being deprecated. Please use strlcpy() instead.
480  */
481 char *
strcpy_impl(char * to,const char * from)482 strcpy_impl(char *to, const char *from)
483 {
484 	char *ret = to;
485 
486 	while ((*to++ = *from++) != '\0') {
487 		continue;
488 	}
489 
490 	return ret;
491 }
492 #endif
493 
494 /*
495  * Abstract:
496  *      strncpy copies "count" characters from the "from" string to
497  *      the "to" string. If "from" contains less than "count" characters
498  *      "to" will be padded with null characters until exactly "count"
499  *      characters have been written. The return value is a pointer
500  *      to the "to" string.
501  */
502 #ifndef __arch_strncpy
503 char *
strncpy_impl(char * dst,const char * src,size_t maxlen)504 strncpy_impl(char * dst, const char * src, size_t maxlen)
505 {
506 	const size_t srclen = strnlen_impl(src, maxlen);
507 	if (srclen < maxlen) {
508 		memcpy_impl(dst, src, srclen);
509 		memset_impl(dst + srclen, 0, maxlen - srclen);
510 	} else {
511 		memcpy_impl(dst, src, maxlen);
512 	}
513 	return dst;
514 }
515 #endif /* __arch_strncpy */
516 
517 /*
518  * atoi:
519  *
520  *      This function converts an ascii string into an integer.
521  *
522  * input        : string
523  * output       : a number
524  */
525 
526 int
atoi(const char * cp)527 atoi(const char *cp)
528 {
529 	int     number;
530 
531 	for (number = 0; ('0' <= *cp) && (*cp <= '9'); cp++) {
532 		number = (number * 10) + (*cp - '0');
533 	}
534 
535 	return number;
536 }
537 
538 /*
539  * convert an integer to an ASCII string.
540  * inputs:
541  *	num	integer to be converted
542  *	str	string pointer.
543  *
544  * outputs:
545  *	pointer to string start.
546  */
547 
548 char *
itoa(int num,char * str)549 itoa(int num, char *str)
550 {
551 	char    digits[11];
552 	char *dp;
553 	char *cp = str;
554 
555 	if (num == 0) {
556 		*cp++ = '0';
557 	} else {
558 		dp = digits;
559 		while (num) {
560 			*dp++ = '0' + num % 10;
561 			num /= 10;
562 		}
563 		while (dp != digits) {
564 			*cp++ = *--dp;
565 		}
566 	}
567 	*cp++ = '\0';
568 
569 	return str;
570 }
571 
572 #if CONFIG_VSPRINTF
573 /*
574  * Deprecation Warning:
575  *	strcat() is being deprecated. Please use strlcat() instead.
576  */
577 char *
strcat_impl(char * dest,const char * src)578 strcat_impl(char *dest, const char *src)
579 {
580 	char *old = dest;
581 
582 	while (*dest) {
583 		++dest;
584 	}
585 	while ((*dest++ = *src++)) {
586 		;
587 	}
588 	return old;
589 }
590 #endif
591 
592 /*
593  * Appends src to string dst of size siz (unlike strncat, siz is the
594  * full size of dst, not space left).  At most siz-1 characters
595  * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
596  * Returns strlen(src) + MIN(siz, strlen(initial dst)).
597  * If retval >= siz, truncation occurred.
598  */
599 #ifndef __arch_strlcat
600 size_t
strlcat_impl(char * dst,const char * src,size_t siz)601 strlcat_impl(char *dst, const char *src, size_t siz)
602 {
603 	char *d = dst;
604 	const char *s = src;
605 	size_t n = siz;
606 	size_t dlen = strlen_impl(dst);
607 
608 	/* Find the end of dst and adjust bytes left but don't go past end */
609 	while (n-- != 0 && *d != '\0') {
610 		d++;
611 	}
612 	dlen = d - dst;
613 	n = siz - dlen;
614 
615 	if (n == 0) {
616 		return dlen + strlen_impl(s);
617 	}
618 	while (*s != '\0') {
619 		if (n != 1) {
620 			*d++ = *s;
621 			n--;
622 		}
623 		s++;
624 	}
625 	*d = '\0';
626 
627 	return dlen + (s - src);       /* count does not include NUL */
628 }
629 #endif /* __arch_strlcat */
630 
631 /*
632  * Copy src to string dst of size siz.  At most siz-1 characters
633  * will be copied.  Always NUL terminates (unless siz == 0).
634  * Returns strlen(src); if retval >= siz, truncation occurred.
635  */
636 #ifndef __arch_strlcpy
637 size_t
strlcpy_impl(char * dst,const char * src,size_t maxlen)638 strlcpy_impl(char * dst, const char * src, size_t maxlen)
639 {
640 	const size_t srclen = strlen_impl(src);
641 	if (srclen + 1 < maxlen) {
642 		memcpy_impl(dst, src, srclen + 1);
643 	} else if (maxlen != 0) {
644 		memcpy_impl(dst, src, maxlen - 1);
645 		dst[maxlen - 1] = '\0';
646 	}
647 	return srclen;
648 }
649 #endif /* __arch_strlcpy */
650 
651 #ifndef __arch_strncat
652 char *
strncat_impl(char * s1,const char * s2,size_t n)653 strncat_impl(char *s1, const char *s2, size_t n)
654 {
655 	if (n != 0) {
656 		char *d = s1;
657 		const char *s = s2;
658 
659 		while (*d != 0) {
660 			d++;
661 		}
662 		do {
663 			if ((*d = *s++) == '\0') {
664 				break;
665 			}
666 			d++;
667 		} while (--n != 0);
668 		*d = '\0';
669 	}
670 
671 	return __CAST_AWAY_QUALIFIER(s1, const, char *);
672 }
673 #endif /* __arch_strncat */
674 
675 #ifndef __arch_strnstr
676 char *
strnstr_impl(const char * s,const char * find,size_t slen)677 strnstr_impl(const char *s, const char *find, size_t slen)
678 {
679 	char c, sc;
680 	size_t len;
681 
682 	if ((c = *find++) != '\0') {
683 		len = strlen_impl(find);
684 		do {
685 			do {
686 				if ((sc = *s++) == '\0' || slen-- < 1) {
687 					return NULL;
688 				}
689 			} while (sc != c);
690 			if (len > slen) {
691 				return NULL;
692 			}
693 		} while (strncmp_impl(s, find, len) != 0);
694 		s--;
695 	}
696 
697 	return __CAST_AWAY_QUALIFIER(s, const, char *);
698 }
699 #endif /* __arch_strnstr */
700 
701 void * __memcpy_chk(void *dst, void const *src, size_t s, size_t chk_size);
702 void * __memmove_chk(void *dst, void const *src, size_t s, size_t chk_size);
703 void * __memset_chk(void *dst, int c, size_t s, size_t chk_size);
704 size_t __strlcpy_chk(char *dst, char const *src, size_t s, size_t chk_size);
705 size_t __strlcat_chk(char *dst, char const *src, size_t s, size_t chk_size);
706 char * __strncpy_chk(char *restrict dst, char *restrict src, size_t len, size_t chk_size);
707 char * __strncat_chk(char *restrict dst, const char *restrict src, size_t len, size_t chk_size);
708 char * __strcpy_chk(char *restrict dst, const char *restrict src, size_t chk_size);
709 char * __strcat_chk(char *restrict dst, const char *restrict src, size_t chk_size);
710 
711 MARK_AS_HIBERNATE_TEXT
712 void *
__memcpy_chk(void * dst,void const * src,size_t s,size_t chk_size)713 __memcpy_chk(void *dst, void const *src, size_t s, size_t chk_size)
714 {
715 	if (__improbable(chk_size < s)) {
716 		panic("__memcpy_chk object size check failed: dst %p, src %p, (%zu < %zu)", dst, src, chk_size, s);
717 	}
718 	return memcpy_impl(dst, src, s);
719 }
720 
721 void *
__memmove_chk(void * dst,void const * src,size_t s,size_t chk_size)722 __memmove_chk(void *dst, void const *src, size_t s, size_t chk_size)
723 {
724 	if (__improbable(chk_size < s)) {
725 		panic("__memmove_chk object size check failed: dst %p, src %p, (%zu < %zu)", dst, src, chk_size, s);
726 	}
727 	return memmove_impl(dst, src, s);
728 }
729 
730 MARK_AS_HIBERNATE_TEXT
731 void *
__memset_chk(void * dst,int c,size_t s,size_t chk_size)732 __memset_chk(void *dst, int c, size_t s, size_t chk_size)
733 {
734 	if (__improbable(chk_size < s)) {
735 		panic("__memset_chk object size check failed: dst %p, c %c, (%zu < %zu)", dst, c, chk_size, s);
736 	}
737 	return memset_impl(dst, c, s);
738 }
739 
740 size_t
__strlcat_chk(char * dst,char const * src,size_t s,size_t chk_size)741 __strlcat_chk(char *dst, char const *src, size_t s, size_t chk_size)
742 {
743 	if (__improbable(chk_size < s)) {
744 		panic("__strlcat_chk object size check failed: dst %p, src %p, (%zu < %zu)", dst, src, chk_size, s);
745 	}
746 	return strlcat_impl(dst, src, s);
747 }
748 
749 size_t
__strlcpy_chk(char * dst,char const * src,size_t s,size_t chk_size)750 __strlcpy_chk(char *dst, char const *src, size_t s, size_t chk_size)
751 {
752 	if (__improbable(chk_size < s)) {
753 		panic("__strlcpy_chk object size check failed: dst %p, src %p, (%zu < %zu)", dst, src, chk_size, s);
754 	}
755 	return strlcpy_impl(dst, src, s);
756 }
757 
758 char *
__strncpy_chk(char * restrict dst,char * restrict src,size_t len,size_t chk_size)759 __strncpy_chk(char *restrict dst, char *restrict src,
760     size_t len, size_t chk_size)
761 {
762 	if (__improbable(chk_size < len)) {
763 		panic("__strncpy_chk object size check failed: dst %p, src %p, (%zu < %zu)", dst, src, chk_size, len);
764 	}
765 	return strncpy_impl(dst, src, len);
766 }
767 
768 char *
__strncat_chk(char * restrict dst,const char * restrict src,size_t len,size_t chk_size)769 __strncat_chk(char *restrict dst, const char *restrict src,
770     size_t len, size_t chk_size)
771 {
772 	size_t len1 = strlen_impl(dst);
773 	size_t len2 = strnlen_impl(src, len);
774 	if (__improbable(chk_size < len1 + len2 + 1)) {
775 		panic("__strncat_chk object size check failed: dst %p, src %p, (%zu < %zu + %zu + 1)", dst, src, chk_size, len1, len2);
776 	}
777 	return strncat_impl(dst, src, len);
778 }
779 
780 char *
__strcpy_chk(char * restrict dst,const char * restrict src,size_t chk_size)781 __strcpy_chk(char *restrict dst, const char *restrict src, size_t chk_size)
782 {
783 	size_t len = strlen_impl(src);
784 	if (__improbable(chk_size < len + 1)) {
785 		panic("__strcpy_chk object size check failed: dst %p, src %p, (%zu < %zu + 1)", dst, src, chk_size, len);
786 	}
787 	memcpy_impl(dst, src, len + 1);
788 	return dst;
789 }
790 
791 char *
__strcat_chk(char * restrict dst,const char * restrict src,size_t chk_size)792 __strcat_chk(char *restrict dst, const char *restrict src, size_t chk_size)
793 {
794 	size_t len1 = strlen_impl(dst);
795 	size_t len2 = strlen_impl(src);
796 	size_t required_len = len1 + len2 + 1;
797 	if (__improbable(chk_size < required_len)) {
798 		panic("__strcat_chk object size check failed: dst %p, src %p, (%zu < %zu + %zu + 1)", dst, src, chk_size, len1, len2);
799 	}
800 	memcpy_impl(dst + len1, src, len2 + 1);
801 	return dst;
802 }
803