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