Line data Source code
1 : /*
2 : * Copyright (C) 2015-2016 Dimitris Papastamos <sin@2f30.org>
3 : * Copyright (C) 2022 q66 <q66@chimera-linux.org>
4 : *
5 : * Permission to use, copy, modify, and/or distribute this software for any
6 : * purpose with or without fee is hereby granted.
7 : *
8 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 : */
16 :
17 : #ifndef _FORTIFY_STRING_H
18 : #define _FORTIFY_STRING_H
19 :
20 : #if !defined(__cplusplus) && !defined(__clang__)
21 : __extension__
22 : #endif
23 : #include_next <string.h>
24 :
25 : #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0
26 : #include "fortify-headers.h"
27 :
28 : #ifdef __cplusplus
29 : extern "C" {
30 : #endif
31 :
32 : #undef memcpy
33 : #undef memchr
34 : #undef memmove
35 : #undef memset
36 : #undef strcat
37 : #undef strcpy
38 : #undef strlen
39 : #undef strncat
40 : #undef strncpy
41 :
42 : __fh_access(write_only, 1, 3)
43 : __fh_access(read_only, 2, 3)
44 : #if __has_builtin(__builtin_memcpy)
45 : __diagnose_as_builtin(__builtin_memcpy, 1, 2, 3)
46 : #endif
47 : _FORTIFY_FN(memcpy) void *memcpy(void * _FORTIFY_POS0 __od,
48 : const void * _FORTIFY_POS0 __os, size_t __n)
49 : __error_if((__fh_bos(__od, 0) < __n), "'memcpy' called with `n` bigger than the size of `d`.")
50 : {
51 : #if __has_builtin(__builtin___memcpy_chk) && FORTIFY_USE_NATIVE_CHK
52 : return __builtin___memcpy_chk(__od, __os, __n, __fh_bos(__od, 0));
53 : #else
54 : #if defined FORTIFY_PEDANTIC_CHECKS
55 : if (!__od || !__os)
56 : __builtin_trap();
57 : #endif
58 :
59 : __fh_size_t __bd = __fh_bos(__od, 0);
60 : __fh_size_t __bs = __fh_bos(__os, 0);
61 :
62 6 : if __fh_overlap(__od, __n, __os, __n)
63 1 : __builtin_trap();
64 2 : if (__n > __bd || __n > __bs)
65 3 : __builtin_trap();
66 3 : return __builtin_memcpy(__od, __os, __n);
67 : #endif
68 : }
69 :
70 : __fh_access(write_only, 1, 3)
71 : __fh_access(read_only, 2, 3)
72 : #if __has_builtin(__builtin_memmove)
73 : __diagnose_as_builtin(__builtin_memmove, 1, 2, 3)
74 : #endif
75 : _FORTIFY_FN(memmove) void *memmove(void * _FORTIFY_POS0 __d,
76 : const void * _FORTIFY_POS0 __s, size_t __n)
77 : {
78 : #if __has_builtin(__builtin___memmove_chk) && FORTIFY_USE_NATIVE_CHK
79 : return __builtin___memmove_chk(__d, __s, __n, __fh_bos(__d, 0));
80 : #else
81 : #if defined FORTIFY_PEDANTIC_CHECKS
82 : if (!__d || !__s)
83 : __builtin_trap();
84 : #endif
85 :
86 : __fh_size_t __bd = __fh_bos(__d, 0);
87 : __fh_size_t __bs = __fh_bos(__s, 0);
88 :
89 2 : if (__n > __bd || __n > __bs)
90 4 : __builtin_trap();
91 4 : return __orig_memmove(__d, __s, __n);
92 : #endif
93 : }
94 :
95 : __fh_access(write_only, 1, 3)
96 : #if __has_builtin(__builtin_memset)
97 : __diagnose_as_builtin(__builtin_memset, 1, 2, 3)
98 : #endif
99 : _FORTIFY_FN(memset) void *memset(void * _FORTIFY_POS0 __d, int __c, size_t __n)
100 : __warning_if(__c != 0 && __n == 0, "'memset' will set `0` bytes; did you invert the arguments?")
101 : {
102 : #if __has_builtin(__builtin___memset_chk) && FORTIFY_USE_NATIVE_CHK
103 : return __builtin___memset_chk(__d, __c, __n, __fh_bos(__d, 0));
104 : #else
105 : #if defined FORTIFY_PEDANTIC_CHECKS
106 : if (!__d)
107 : __builtin_trap();
108 : #endif
109 :
110 : __fh_size_t __b = __fh_bos(__d, 0);
111 :
112 1 : if (__n > __b)
113 2 : __builtin_trap();
114 0 : return __builtin_memset(__d, __c, __n);
115 : #endif
116 : }
117 :
118 : __fh_access(read_only, 1, 3)
119 : #if __has_builtin(__builtin_memchr)
120 : __diagnose_as_builtin(__builtin_memchr, 1, 2, 3)
121 : #endif
122 : _FORTIFY_FN(memchr) void *memchr(const void * _FORTIFY_POS0 __d, int __c, size_t __n)
123 : {
124 : #if __has_builtin(__builtin___memchr_chk) && FORTIFY_USE_NATIVE_CHK
125 : return __builtin___memchr_chk(__d, __c, __n, __fh_bos(__d, 0));
126 : #else
127 : #if defined FORTIFY_PEDANTIC_CHECKS
128 : if (!__d)
129 : __builtin_trap();
130 : #if __STDC_VERSION__ < 201112L
131 : __fh_size_t __b = __fh_bos(__d, 0);
132 : if (__n > __b)
133 : __builtin_trap();
134 : #endif
135 : #endif
136 :
137 : return __builtin_memchr(__d, __c, __n);
138 : #endif
139 : }
140 :
141 : #if 0
142 : __fh_access(read_only, 1, 2)
143 : _FORTIFY_FN(strchr) char *strchr(const char * _FORTIFY_POS0 __s, int __c)
144 : {
145 : #if __has_builtin(__builtin___strchr_chk) && FORTIFY_USE_NATIVE_CHK
146 : return __builtin___strchr_chk(__s, __c, __fh_bos(__s, 0));
147 : #else
148 : __fh_size_t __b = __fh_bos(__s, 0);
149 :
150 : char* __r = __builtin_strchr(__s, __c);
151 : if (__r - __s > __b)
152 : __builtin_trap();
153 : return __r;
154 : #endif
155 : }
156 :
157 : __fh_access(read_only, 1, 2)
158 : _FORTIFY_FN(strrchr) char *strrchr(const char * _FORTIFY_POS0 __s, int __c)
159 : {
160 : #if __has_builtin(__builtin___strrchr_chk) && FORTIFY_USE_NATIVE_CHK
161 : return __builtin___strrchr_chk(__s, __c, __fh_bos(__s, 0));
162 : #else
163 : __fh_size_t __b = __fh_bos(__s, 0);
164 :
165 : char* __r = __builtin_strrchr(__s, __c);
166 : if (__r - __s > __b)
167 : __builtin_trap();
168 : return __r;
169 : #endif
170 : }
171 : #endif
172 :
173 : #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
174 : || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
175 : || defined(_BSD_SOURCE)
176 : #undef stpcpy
177 : __fh_access(write_only, 1)
178 : __fh_access(read_only, 2)
179 : #if __has_builtin(__builtin_stpcpy)
180 : __diagnose_as_builtin(__builtin_stpcpy, 1, 2)
181 : #endif
182 : _FORTIFY_FN(stpcpy) char *stpcpy(char * _FORTIFY_POS0 __d, const char *__s)
183 : {
184 : #if __has_builtin(__builtin___stpcpy_chk) && FORTIFY_USE_NATIVE_CHK
185 : return __builtin___stpcpy_chk(__d, __s, __fh_bos(__d, 0));
186 : #else
187 6 : __fh_size_t __n = strlen(__s) + 1;
188 : __fh_size_t __b = __fh_bos(__d, 0);
189 :
190 6 : if (__fh_overlap(__d, __n, __s, __n))
191 2 : __builtin_trap();
192 :
193 2 : if (__n > __b)
194 2 : __builtin_trap();
195 2 : return __orig_stpcpy(__d, __s);
196 : #endif
197 : }
198 :
199 : #undef stpncpy
200 : __fh_access(write_only, 1)
201 : __fh_access(read_only, 2)
202 : #if __has_builtin(__builtin_stpncpy)
203 : __diagnose_as_builtin(__builtin_stpncpy, 1, 2, 3)
204 : #endif
205 : _FORTIFY_FN(stpncpy) char *stpncpy(char * _FORTIFY_POS0 __d, const char *__s,
206 : size_t __n)
207 : {
208 : #if __has_builtin(__builtin___stpncpy_chk) && FORTIFY_USE_NATIVE_CHK
209 : return __builtin___stpncpy_chk(__d, __s, __n, __fh_bos(__d, 0));
210 : #else
211 : // If the length strlen(src) is smaller than n, the remaining
212 : // characters in the array pointed to by dest are filled with null
213 : // bytes ('\0')
214 : __fh_size_t __b = __fh_bos(__d, 0);
215 1 : if (__n > __b)
216 2 : __builtin_trap();
217 :
218 4 : return __orig_stpncpy(__d, __s, __n);
219 : #endif
220 : }
221 : #endif
222 :
223 : __fh_access (read_write, 1)
224 : __fh_access (read_only, 2)
225 : #if __has_builtin(__builtin_strcat)
226 : __diagnose_as_builtin(__builtin_strcat, 1, 2)
227 : #endif
228 : _FORTIFY_FN(strcat) char *strcat(char * _FORTIFY_POS0 __d, const char *__s)
229 : {
230 : #if __has_builtin(__builtin___strcat_chk) && FORTIFY_USE_NATIVE_CHK
231 : return __builtin___strcat_chk(__d, __s, __fh_bos(__d, 0));
232 : #else
233 : __fh_size_t __b = __fh_bos(__d, 0);
234 :
235 2 : if (strlen(__s) + strlen(__d) + 1 > __b)
236 1 : __builtin_trap();
237 1 : return __orig_strcat(__d, __s);
238 : #endif
239 : }
240 :
241 : __fh_access (write_only, 1)
242 : __fh_access (read_only, 2)
243 : #if __has_builtin(__builtin_strcpy)
244 : __diagnose_as_builtin(__builtin_strcpy, 1, 2)
245 : #endif
246 : _FORTIFY_FN(strcpy) char *strcpy(char * _FORTIFY_POS0 __d, const char *__s)
247 : {
248 : #if __has_builtin(__builtin___strcpy_chk) && FORTIFY_USE_NATIVE_CHK
249 : return __builtin___strcpy_chk(__d, __s, __fh_bos(__d, 0));
250 : #else
251 7 : __fh_size_t __n = strlen(__s) + 1;
252 : __fh_size_t __b = __fh_bos(__d, 0);
253 :
254 7 : if (__fh_overlap(__d, __n, __s, __n))
255 2 : __builtin_trap();
256 :
257 2 : if (__n > __b)
258 2 : __builtin_trap();
259 3 : return __orig_strcpy(__d, __s);
260 : #endif
261 : }
262 :
263 : __fh_access (read_only, 1)
264 : #if __has_builtin(__builtin_strlen)
265 : __diagnose_as_builtin(__builtin_strlen, 1)
266 : #endif
267 : _FORTIFY_FN(strlen) size_t strlen(const char * _FORTIFY_POS0 __s)
268 : {
269 : #if __has_builtin(__builtin___strlen_chk) && FORTIFY_USE_NATIVE_CHK
270 : return __builtin___strlen_chk(__s, __fh_bos(__s, 0));
271 : #else
272 19 : __fh_size_t ret = __orig_strlen(__s);
273 19 : if (ret > __fh_bos(__s, 0) - 1)
274 1 : __builtin_trap();
275 : return ret;
276 : #endif
277 : }
278 :
279 : __fh_access (read_write, 1)
280 : __fh_access (read_only, 2, 3)
281 : #if __has_builtin(__builtin_strncat)
282 : __diagnose_as_builtin(__builtin_strncat, 1, 2, 3)
283 : #endif
284 : _FORTIFY_FN(strncat) char *strncat(char * _FORTIFY_POS0 __d, const char *__s,
285 : size_t __n)
286 : {
287 : #if __has_builtin(__builtin___strncat_chk) && FORTIFY_USE_NATIVE_CHK
288 : return __builtin___strncat_chk(__d, __s, __n, __fh_bos(__d, 0));
289 : #else
290 : #if 0 // strlen(__s) isn't guaranteed to be valid.
291 : __fh_size_t __b = __fh_bos(__d, 0);
292 :
293 : if (__n > __b) {
294 : __fh_size_t __sl = strlen(__s);
295 : if (__sl > __n)
296 : __sl = __n;
297 : __fh_size_t __dl = strlen(__d);
298 : if (__sl + __dl + 1 > __b)
299 : __builtin_trap();
300 : }
301 : #endif
302 2 : return __orig_strncat(__d, __s, __n);
303 : #endif
304 : }
305 :
306 : __fh_access (write_only, 1)
307 : __fh_access (read_only, 2)
308 : #if __has_builtin(__builtin_strncpy)
309 : __diagnose_as_builtin(__builtin_strncpy, 1, 2, 3)
310 : #endif
311 : _FORTIFY_FN(strncpy) char *strncpy(char * _FORTIFY_POS0 __d,
312 : const char *__s, size_t __n)
313 : {
314 : #if __has_builtin(__builtin___strncpy_chk) && FORTIFY_USE_NATIVE_CHK
315 : return __builtin___strncpy_chk(__d, __s, __n, __fh_bos(__d, 0));
316 : #else
317 : // If the length of src is less than n, strncpy() writes additional
318 : // null bytes to dest to ensure that a total of n bytes are written.
319 : __fh_size_t __b = __fh_bos(__d, 0);
320 1 : if (__n > __b)
321 2 : __builtin_trap();
322 :
323 4 : return __orig_strncpy(__d, __s, __n);
324 : #endif
325 : }
326 :
327 : #ifdef _GNU_SOURCE
328 : #undef mempcpy
329 : __fh_access(write_only, 1)
330 : __fh_access(read_only, 2, 3)
331 : #if __has_builtin(__builtin_mempcpy)
332 : __diagnose_as_builtin(__builtin_mempcpy, 1, 2, 3)
333 : #endif
334 : _FORTIFY_FN(mempcpy) void *mempcpy(void * _FORTIFY_POS0 __d,
335 : const void * _FORTIFY_POS0 __s, size_t __n)
336 : {
337 : #if __has_builtin(__builtin___mempcpy_chk) && FORTIFY_USE_NATIVE_CHK
338 : return __builtin___mempcpy_chk(__d, __s, __n, __fh_bos(__d, 0));
339 : #else
340 : if (!__d || !__s)
341 : __builtin_trap();
342 :
343 : __fh_size_t __bd = __fh_bos(__d, 0);
344 : __fh_size_t __bs = __fh_bos(__s, 0);
345 :
346 2 : if (__n > __bd || __n > __bs)
347 4 : __builtin_trap();
348 4 : return __orig_mempcpy(__d, __s, __n);
349 : #endif
350 : }
351 : #endif
352 :
353 : #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
354 : #undef strlcat
355 : #undef strlcpy
356 : __fh_access (read_write, 1)
357 : __fh_access (read_only, 2, 3)
358 : #if __has_builtin(__builtin_strlcat)
359 : __diagnose_as_builtin(__builtin_strlcat, 1, 2, 3)
360 : #endif
361 : _FORTIFY_FN(strlcat) size_t strlcat(char * _FORTIFY_POS0 __d,
362 : const char *__s, size_t __n)
363 : {
364 : #if __has_builtin(__builtin___strlcat_chk) && FORTIFY_USE_NATIVE_CHK
365 : return __builtin___strlcat_chk(__d, __s, __n, __fh_bos(__d, 0));
366 : #else
367 : __fh_size_t __b = __fh_bos(__d, 0);
368 :
369 1 : if (__n > __b)
370 2 : __builtin_trap();
371 2 : return __orig_strlcat(__d, __s, __n);
372 : #endif
373 : }
374 :
375 : __fh_access (write_only, 1)
376 : __fh_access (read_only, 2, 3)
377 : #if __has_builtin(__builtin_strlcpy)
378 : __diagnose_as_builtin(__builtin_strlcpy, 1, 2, 3)
379 : #endif
380 : _FORTIFY_FN(strlcpy) size_t strlcpy(char * _FORTIFY_POS0 __d,
381 : const char *__s, size_t __n)
382 : {
383 : #if __has_builtin(__builtin___strlcpy_chk) && FORTIFY_USE_NATIVE_CHK
384 : return __builtin___strlcpy_chk(__d, __s, __n, __fh_bos(__d, 0));
385 : #else
386 : __fh_size_t __b = __fh_bos(__d, 0);
387 :
388 1 : if (__n > __b)
389 2 : __builtin_trap();
390 2 : return __orig_strlcpy(__d, __s, __n);
391 : #endif
392 : }
393 : #endif
394 :
395 : #ifdef __cplusplus
396 : }
397 : #endif
398 :
399 : #endif
400 :
401 : #endif
|