xref: /freebsd/include/ssp/wchar.h (revision 95eb4b873b6a8b527c5bd78d7191975dfca38998)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2024, Klara, Inc.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 #ifndef _SSP_WCHAR_H_
28 #define _SSP_WCHAR_H_
29 
30 #include <ssp/ssp.h>
31 
32 #if __SSP_FORTIFY_LEVEL > 0
33 
34 __ssp_inline int
35 __ssp_wchar_overlap(const void *leftp, const void *rightp, size_t len)
36 {
37 
38 	if (len > SIZE_MAX / sizeof(wchar_t))
39 		return (1);
40 	return (__ssp_overlap(leftp, rightp, len * sizeof(wchar_t)));
41 }
42 
43 /*
44  * __ssp_wbos for w*() calls where the size parameters are in sizeof(wchar_t)
45  * units, so the result needs to be scaled appropriately.
46  */
47 __ssp_inline size_t
48 __ssp_wbos(void *ptr)
49 {
50 	const size_t ptrsize = __ssp_bos(ptr);
51 
52 	if (ptrsize == (size_t)-1)
53 		return (ptrsize);
54 
55 	return (ptrsize / sizeof(wchar_t));
56 }
57 
58 __BEGIN_DECLS
59 __ssp_redirect_raw_impl(wchar_t *, wmemcpy, wmemcpy,
60     (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len))
61 {
62 	const size_t slen = __ssp_wbos(buf);
63 
64 	if (len > slen)
65 		__chk_fail();
66 	if (__ssp_wchar_overlap(src, buf, len))
67 		__chk_fail();
68 
69 	return (__ssp_real(wmemcpy)(buf, src, len));
70 }
71 
72 __ssp_redirect_raw_impl(wchar_t *, wmempcpy, wmempcpy,
73     (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len))
74 {
75 	const size_t slen = __ssp_wbos(buf);
76 
77 	if (len > slen)
78 		__chk_fail();
79 	if (__ssp_wchar_overlap(src, buf, len))
80 		__chk_fail();
81 
82 	return (__ssp_real(wmempcpy)(buf, src, len));
83 }
84 
85 __ssp_redirect_raw_impl(wchar_t *, wmemmove, wmemmove,
86     (wchar_t *buf, const wchar_t *src, size_t len))
87 {
88 	const size_t slen = __ssp_wbos(buf);
89 
90 	if (len > slen)
91 		__chk_fail();
92 
93 	return (__ssp_real(wmemmove)(buf, src, len));
94 }
95 
96 __ssp_redirect_raw_impl(wchar_t *, wmemset, wmemset,
97     (wchar_t *buf, wchar_t c, size_t len))
98 {
99 	const size_t slen = __ssp_wbos(buf);
100 
101 	if (len > slen)
102 		__chk_fail();
103 	return (__ssp_real(wmemset)(buf, c, len));
104 }
105 
106 __ssp_redirect_raw_impl(wchar_t *, wcpcpy, wcpcpy,
107     (wchar_t *__restrict buf, const wchar_t *__restrict src))
108 {
109 	const size_t slen = __ssp_wbos(buf);
110 	const size_t len = wcslen(src);
111 
112 	if (len >= slen)
113 		__chk_fail();
114 	if (__ssp_wchar_overlap(buf, src, len))
115 		__chk_fail();
116 
117 	(void)__ssp_real(wmemcpy)(buf, src, len + 1);
118 	return (buf + len);
119 }
120 
121 __ssp_redirect_raw_impl(wchar_t *, wcpncpy, wcpncpy,
122     (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len))
123 {
124 	const size_t slen = __ssp_wbos(buf);
125 
126 	if (len > slen)
127 		__chk_fail();
128 	if (__ssp_wchar_overlap(buf, src, len))
129 		__chk_fail();
130 
131 	return (__ssp_real(wcpncpy)(buf, src, len));
132 }
133 
134 __ssp_redirect_raw_impl(wchar_t *, wcscat, wcscat,
135    (wchar_t *__restrict buf, const wchar_t *__restrict src))
136 {
137 	size_t slen = __ssp_wbos(buf);
138 	wchar_t *cp;
139 
140 	cp = buf;
141 	while (*cp != L'\0') {
142 		cp++;
143 		if (slen-- == 0)
144 			__chk_fail();
145 	}
146 
147 	while (*src != L'\0') {
148 		if (slen-- == 0)
149 			__chk_fail();
150 		*cp++ = *src++;
151 	}
152 
153 	if (slen-- == 0)
154 		__chk_fail();
155 	*cp = '\0';
156 	return (buf);
157 }
158 
159 __ssp_redirect_raw_impl(wchar_t *, wcscpy, wcscpy,
160    (wchar_t *__restrict buf, const wchar_t *__restrict src))
161 {
162 	const size_t slen = __ssp_wbos(buf);
163 	size_t len = wcslen(src) + 1;
164 
165 	if (len > slen)
166 		__chk_fail();
167 	if (__ssp_wchar_overlap(buf, src, len))
168 		__chk_fail();
169 
170 	return (__ssp_real(wmemcpy)(buf, src, len));
171 }
172 
173 __ssp_redirect_raw_impl(wchar_t *, wcsncat, wcsncat,
174     (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len))
175 {
176 	const size_t slen = __ssp_wbos(buf);
177 
178 	if (len == 0)
179 		return (buf);
180 	if (len > slen)
181 		__chk_fail();
182 	if (__ssp_wchar_overlap(buf, src, len))
183 		__chk_fail();
184 
185 	return (__ssp_real(wcsncat)(buf, src, len));
186 }
187 
188 __ssp_redirect_raw_impl(size_t, wcslcat, wcslcat,
189     (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len))
190 {
191 	const size_t slen = __ssp_wbos(buf);
192 
193 	if (len > slen)
194 		__chk_fail();
195 	if (__ssp_wchar_overlap(buf, src, len))
196 		__chk_fail();
197 
198 	return (__ssp_real(wcslcat)(buf, src, len));
199 }
200 
201 __ssp_redirect_raw_impl(wchar_t *, wcsncpy, wcsncpy,
202     (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len))
203 {
204 	const size_t slen = __ssp_wbos(buf);
205 
206 	if (len > slen)
207 		__chk_fail();
208 	if (__ssp_wchar_overlap(buf, src, len))
209 		__chk_fail();
210 
211 	return (__ssp_real(wcsncpy)(buf, src, len));
212 }
213 
214 __ssp_redirect_raw_impl(size_t, wcslcpy, wcslcpy,
215     (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len))
216 {
217 	const size_t slen = __ssp_wbos(buf);
218 
219 	if (len > slen)
220 		__chk_fail();
221 	if (__ssp_wchar_overlap(buf, src, len))
222 		__chk_fail();
223 
224 	return (__ssp_real(wcslcpy)(buf, src, len));
225 }
226 __END_DECLS
227 
228 #endif /* __SSP_FORTIFY_LEVEL > 0 */
229 #endif /* _SSP_WCHAR_H_ */
230