1 /*
2 **  Copyright (c) 1999-2002, Sendmail Inc. and its suppliers.
3 **	All rights reserved.
4 **
5 **  By using this file, you agree to the terms and conditions set
6 **  forth in the LICENSE file which can be found at the top level of
7 **  the sendmail distribution.
8 **
9 **  Copyright (c) 2009, 2012, 2021, The Trusted Domain Project.
10 **    All rights reserved.
11 */
12 
13 /* system includes */
14 #include <sys/types.h>
15 #include <string.h>
16 
17 /*
18 **  XXX the type of the length parameter has been changed
19 **  from size_t to ssize_t to avoid theoretical problems with negative
20 **  numbers passed into these functions.
21 **  The real solution to this problem is to make sure that this doesn't
22 **  happen, but for now we'll use this workaround.
23 */
24 
25 /*
26 **  DMARC_STRLCPY -- size bounded string copy
27 **
28 **	This is a bounds-checking variant of strcpy.
29 **	If size > 0, copy up to size-1 characters from the nul terminated
30 **	string src to dst, nul terminating the result.  If size == 0,
31 **	the dst buffer is not modified.
32 **	Additional note: this function has been "tuned" to run fast and tested
33 **	as such (versus versions in some OS's libc).
34 **
35 **	The result is strlen(src).  You can detect truncation (not all
36 **	of the characters in the source string were copied) using the
37 **	following idiom:
38 **
39 **		char *s, buf[BUFSIZ];
40 **		...
41 **		if (dmarc_strlcpy(buf, s, sizeof(buf)) >= sizeof(buf))
42 **			goto overflow;
43 **
44 **	Parameters:
45 **		dst -- destination buffer
46 **		src -- source string
47 **		size -- size of destination buffer
48 **
49 **	Returns:
50 **		strlen(src)
51 */
52 
53 size_t
dmarc_strlcpy(register char * dst,register const char * src,ssize_t size)54 dmarc_strlcpy(register char *dst, register const char *src, ssize_t size)
55 {
56 	register ssize_t i;
57 
58 	if (size-- <= 0)
59 		return strlen(src);
60 	for (i = 0; i < size && (dst[i] = src[i]) != 0; i++)
61 		continue;
62 	dst[i] = '\0';
63 	if (src[i] == '\0')
64 		return i;
65 	else
66 		return i + strlen(src + i);
67 }
68 
69 /*
70 **  DMARC_STRLCAT -- size bounded string concatenation
71 **
72 **	This is a bounds-checking variant of strcat.
73 **	If strlen(dst) < size, then append at most size - strlen(dst) - 1
74 **	characters from the source string to the destination string,
75 **	nul terminating the result.  Otherwise, dst is not modified.
76 **
77 **	The result is the initial length of dst + the length of src.
78 **	You can detect overflow (not all of the characters in the
79 **	source string were copied) using the following idiom:
80 **
81 **		char *s, buf[BUFSIZ];
82 **		...
83 **		if (dmarc_strlcat(buf, s, sizeof(buf)) >= sizeof(buf))
84 **			goto overflow;
85 **
86 **	Parameters:
87 **		dst -- nul-terminated destination string buffer
88 **		src -- nul-terminated source string
89 **		size -- size of destination buffer
90 **
91 **	Returns:
92 **		total length of the string tried to create
93 **		(= initial length of dst + length of src)
94 */
95 
96 size_t
dmarc_strlcat(register char * dst,register const char * src,ssize_t size)97 dmarc_strlcat(register char *dst, register const char *src, ssize_t size)
98 {
99 	register ssize_t i, j, o;
100 
101 	o = strlen(dst);
102 	if (size < o + 1)
103 		return o + strlen(src);
104 	size -= o + 1;
105 	for (i = 0, j = o; i < size && (dst[j] = src[i]) != 0; i++, j++)
106 		continue;
107 	dst[j] = '\0';
108 	if (src[i] == '\0')
109 		return j;
110 	else
111 		return j + strlen(src + i);
112 }
113