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
28// zig patch: ssp/wchar.h header was added in FreeBSD 15
29#if __FreeBSD_version < 1500500
30 #error "ssp/wchar.h did not exist before FreeBSD 15"
31#endif /* error for FreeBSD before 15 */
32
33#ifndef _SSP_WCHAR_H_
34#define _SSP_WCHAR_H_
35
36#include <ssp/ssp.h>
37
38#if __SSP_FORTIFY_LEVEL > 0
39
40__ssp_inline int
41__ssp_wchar_overlap(const void *leftp, const void *rightp, size_t len)
42{
43
44 if (len > __SIZE_T_MAX / sizeof(wchar_t))
45 return (1);
46 return (__ssp_overlap(leftp, rightp, len * sizeof(wchar_t)));
47}
48
49/*
50 * __ssp_wbos for w*() calls where the size parameters are in sizeof(wchar_t)
51 * units, so the result needs to be scaled appropriately.
52 */
53__ssp_inline size_t
54__ssp_wbos(void *ptr)
55{
56 const size_t ptrsize = __ssp_bos(ptr);
57
58 if (ptrsize == (size_t)-1)
59 return (ptrsize);
60
61 return (ptrsize / sizeof(wchar_t));
62}
63
64__BEGIN_DECLS
65__ssp_redirect_raw_impl(wchar_t *, wmemcpy, wmemcpy,
66 (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len))
67{
68 const size_t slen = __ssp_wbos(buf);
69
70 if (len > slen)
71 __chk_fail();
72 if (__ssp_wchar_overlap(src, buf, len))
73 __chk_fail();
74
75 return (__ssp_real(wmemcpy)(buf, src, len));
76}
77
78__ssp_redirect_raw_impl(wchar_t *, wmempcpy, wmempcpy,
79 (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len))
80{
81 const size_t slen = __ssp_wbos(buf);
82
83 if (len > slen)
84 __chk_fail();
85 if (__ssp_wchar_overlap(src, buf, len))
86 __chk_fail();
87
88 return (__ssp_real(wmempcpy)(buf, src, len));
89}
90
91__ssp_redirect_raw_impl(wchar_t *, wmemmove, wmemmove,
92 (wchar_t *buf, const wchar_t *src, size_t len))
93{
94 const size_t slen = __ssp_wbos(buf);
95
96 if (len > slen)
97 __chk_fail();
98
99 return (__ssp_real(wmemmove)(buf, src, len));
100}
101
102__ssp_redirect_raw_impl(wchar_t *, wmemset, wmemset,
103 (wchar_t *buf, wchar_t c, size_t len))
104{
105 const size_t slen = __ssp_wbos(buf);
106
107 if (len > slen)
108 __chk_fail();
109 return (__ssp_real(wmemset)(buf, c, len));
110}
111
112__ssp_redirect_raw_impl(wchar_t *, wcpcpy, wcpcpy,
113 (wchar_t *__restrict buf, const wchar_t *__restrict src))
114{
115 const size_t slen = __ssp_wbos(buf);
116 const size_t len = wcslen(src);
117
118 if (len >= slen)
119 __chk_fail();
120 if (__ssp_wchar_overlap(buf, src, len))
121 __chk_fail();
122
123 (void)__ssp_real(wmemcpy)(buf, src, len + 1);
124 return (buf + len);
125}
126
127__ssp_redirect_raw_impl(wchar_t *, wcpncpy, wcpncpy,
128 (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len))
129{
130 const size_t slen = __ssp_wbos(buf);
131
132 if (len > slen)
133 __chk_fail();
134 if (__ssp_wchar_overlap(buf, src, len))
135 __chk_fail();
136
137 return (__ssp_real(wcpncpy)(buf, src, len));
138}
139
140__ssp_redirect_raw_impl(wchar_t *, wcscat, wcscat,
141 (wchar_t *__restrict buf, const wchar_t *__restrict src))
142{
143 size_t slen = __ssp_wbos(buf);
144 wchar_t *cp;
145
146 cp = buf;
147 while (*cp != L'\0') {
148 cp++;
149 if (slen-- == 0)
150 __chk_fail();
151 }
152
153 while (*src != L'\0') {
154 if (slen-- == 0)
155 __chk_fail();
156 *cp++ = *src++;
157 }
158
159 if (slen-- == 0)
160 __chk_fail();
161 *cp = '\0';
162 return (buf);
163}
164
165__ssp_redirect_raw_impl(wchar_t *, wcscpy, wcscpy,
166 (wchar_t *__restrict buf, const wchar_t *__restrict src))
167{
168 const size_t slen = __ssp_wbos(buf);
169 size_t len = wcslen(src) + 1;
170
171 if (len > slen)
172 __chk_fail();
173 if (__ssp_wchar_overlap(buf, src, len))
174 __chk_fail();
175
176 return (__ssp_real(wmemcpy)(buf, src, len));
177}
178
179__ssp_redirect_raw_impl(wchar_t *, wcsncat, wcsncat,
180 (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len))
181{
182 const size_t slen = __ssp_wbos(buf);
183
184 if (len == 0)
185 return (buf);
186 if (len > slen)
187 __chk_fail();
188 if (__ssp_wchar_overlap(buf, src, len))
189 __chk_fail();
190
191 return (__ssp_real(wcsncat)(buf, src, len));
192}
193
194__ssp_redirect_raw_impl(size_t, wcslcat, wcslcat,
195 (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len))
196{
197 const size_t slen = __ssp_wbos(buf);
198
199 if (len > slen)
200 __chk_fail();
201 if (__ssp_wchar_overlap(buf, src, len))
202 __chk_fail();
203
204 return (__ssp_real(wcslcat)(buf, src, len));
205}
206
207__ssp_redirect_raw_impl(wchar_t *, wcsncpy, wcsncpy,
208 (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len))
209{
210 const size_t slen = __ssp_wbos(buf);
211
212 if (len > slen)
213 __chk_fail();
214 if (__ssp_wchar_overlap(buf, src, len))
215 __chk_fail();
216
217 return (__ssp_real(wcsncpy)(buf, src, len));
218}
219
220__ssp_redirect_raw_impl(size_t, wcslcpy, wcslcpy,
221 (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len))
222{
223 const size_t slen = __ssp_wbos(buf);
224
225 if (len > slen)
226 __chk_fail();
227 if (__ssp_wchar_overlap(buf, src, len))
228 __chk_fail();
229
230 return (__ssp_real(wcslcpy)(buf, src, len));
231}
232__END_DECLS
233
234#endif /* __SSP_FORTIFY_LEVEL > 0 */
235#endif /* _SSP_WCHAR_H_ */