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