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