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
__ssp_wchar_overlap(const void * leftp,const void * rightp,size_t len)35 __ssp_wchar_overlap(const void *leftp, const void *rightp, size_t len)
36 {
37
38 if (len > __SIZE_T_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
__ssp_wbos(void * ptr)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