fortify-headers

standalone fortify-source implementation
git clone git://git.2f30.org/fortify-headers
Log | Files | Refs | README | LICENSE

string.h (5478B)


      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 memmove
     34 #undef memset
     35 #undef strcat
     36 #undef strcpy
     37 #undef strncat
     38 #undef strncpy
     39 
     40 __access(write_only, 1, 3)
     41 __access(read_only, 2, 3)
     42 _FORTIFY_FN(memcpy) void *memcpy(void * _FORTIFY_POS0 __od,
     43                                  const void * _FORTIFY_POS0 __os, size_t __n)
     44 {
     45 	size_t __bd = __bos(__od, 0);
     46 	size_t __bs = __bos(__os, 0);
     47 	char *__d = (char *)__od;
     48 	const char *__s = (const char *)__os;
     49 
     50 	/* trap if pointers are overlapping but not if dst == src.
     51 	 * gcc seems to like to generate code that relies on dst == src */
     52 	if ((__d < __s && __d + __n > __s) ||
     53 	    (__s < __d && __s + __n > __d))
     54 		__builtin_trap();
     55 	if (__n > __bd || __n > __bs)
     56 		__builtin_trap();
     57 	return __builtin_memcpy(__od, __os, __n);
     58 }
     59 
     60 __access(write_only, 1, 3)
     61 __access(read_only, 2, 3)
     62 _FORTIFY_FN(memmove) void *memmove(void * _FORTIFY_POS0 __d,
     63                                    const void * _FORTIFY_POS0 __s, size_t __n)
     64 {
     65 	size_t __bd = __bos(__d, 0);
     66 	size_t __bs = __bos(__s, 0);
     67 
     68 	if (__n > __bd || __n > __bs)
     69 		__builtin_trap();
     70 	return __orig_memmove(__d, __s, __n);
     71 }
     72 
     73 __access(write_only, 1, 3)
     74 __warning_if(__c != 0 && __n == 0, "'memset' will set `0` bytes; did you invert the arguments?")
     75 _FORTIFY_FN(memset) void *memset(void * _FORTIFY_POS0 __d, int __c, size_t __n)
     76 {
     77 	size_t __b = __bos(__d, 0);
     78 
     79 	if (__n > __b)
     80 		__builtin_trap();
     81 	return __builtin_memset(__d, __c, __n);
     82 }
     83 
     84 #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
     85  || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
     86  || defined(_BSD_SOURCE)
     87 #undef stpcpy
     88 __access(write_only, 1)
     89 __access(read_only, 2)
     90 _FORTIFY_FN(stpcpy) char *stpcpy(char * _FORTIFY_POS0 __d, const char *__s)
     91 {
     92 	size_t __b = __bos(__d, 0);
     93 
     94 	if (strlen(__s) + 1 > __b)
     95 		__builtin_trap();
     96 	return __orig_stpcpy(__d, __s);
     97 }
     98 
     99 #undef stpncpy
    100 __access(write_only, 1)
    101 __access(read_only, 2)
    102 _FORTIFY_FN(stpncpy) char *stpncpy(char * _FORTIFY_POS0 __d, const char *__s,
    103                                    size_t __n)
    104 {
    105 	size_t __b = __bos(__d, 0);
    106 
    107 	if (__n > __b && strlen(__s) + 1 > __b)
    108 		__builtin_trap();
    109 	return __orig_stpncpy(__d, __s, __n);
    110 }
    111 #endif
    112 
    113 __access(read_write, 1)
    114 __access(read_only, 2)
    115 _FORTIFY_FN(strcat) char *strcat(char * _FORTIFY_POS0 __d, const char *__s)
    116 {
    117 	size_t __b = __bos(__d, 0);
    118 
    119 	if (strlen(__s) + strlen(__d) + 1 > __b)
    120 		__builtin_trap();
    121 	return __orig_strcat(__d, __s);
    122 }
    123 
    124 __access(write_only, 1)
    125 __access(read_only, 2)
    126 _FORTIFY_FN(strcpy) char *strcpy(char * _FORTIFY_POS0 __d, const char *__s)
    127 {
    128 	size_t __b = __bos(__d, 0);
    129 
    130 	if (strlen(__s) + 1 > __b)
    131 		__builtin_trap();
    132 	return __orig_strcpy(__d, __s);
    133 }
    134 
    135 __access(read_write, 1)
    136 __access(read_only, 2)
    137 _FORTIFY_FN(strncat) char *strncat(char * _FORTIFY_POS0 __d, const char *__s,
    138                                    size_t __n)
    139 {
    140 	size_t __b = __bos(__d, 0);
    141 	size_t __sl, __dl;
    142 
    143 	if (__n > __b) {
    144 		__sl = strlen(__s);
    145 		__dl = strlen(__d);
    146 		if (__sl > __n)
    147 			__sl = __n;
    148 		if (__sl + __dl + 1 > __b)
    149 			__builtin_trap();
    150 	}
    151 	return __orig_strncat(__d, __s, __n);
    152 }
    153 
    154 __access(write_only, 1)
    155 __access(read_only, 2)
    156 _FORTIFY_FN(strncpy) char *strncpy(char * _FORTIFY_POS0 __d,
    157                                    const char *__s, size_t __n)
    158 {
    159 	size_t __b = __bos(__d, 0);
    160 
    161 	if (__n > __b)
    162 		__builtin_trap();
    163 	return __orig_strncpy(__d, __s, __n);
    164 }
    165 
    166 #ifdef _GNU_SOURCE
    167 #undef mempcpy
    168 __access(write_only, 1, 3)
    169 __access(read_only, 2, 3)
    170 _FORTIFY_FN(mempcpy) void *mempcpy(void * _FORTIFY_POS0 __d,
    171                                    const void * _FORTIFY_POS0 __s, size_t __n)
    172 {
    173 	size_t __bd = __bos(__d, 0);
    174 	size_t __bs = __bos(__s, 0);
    175 
    176 	if (__n > __bd || __n > __bs)
    177 		__builtin_trap();
    178 	return __orig_mempcpy(__d, __s, __n);
    179 }
    180 #endif
    181 
    182 #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
    183 #undef strlcat
    184 #undef strlcpy
    185 __access(read_write, 1)
    186 __access(read_only, 2)
    187 _FORTIFY_FN(strlcat) size_t strlcat(char * _FORTIFY_POS0 __d,
    188                                     const char *__s, size_t __n)
    189 {
    190 	size_t __b = __bos(__d, 0);
    191 
    192 	if (__n > __b)
    193 		__builtin_trap();
    194 	return __orig_strlcat(__d, __s, __n);
    195 }
    196 
    197 __access(write_only, 1)
    198 __access(read_only, 2)
    199 _FORTIFY_FN(strlcpy) size_t strlcpy(char * _FORTIFY_POS0 __d,
    200                                     const char *__s, size_t __n)
    201 {
    202 	size_t __b = __bos(__d, 0);
    203 
    204 	if (__n > __b)
    205 		__builtin_trap();
    206 	return __orig_strlcpy(__d, __s, __n);
    207 }
    208 #endif
    209 
    210 #ifdef __cplusplus
    211 }
    212 #endif
    213 
    214 #endif
    215 
    216 #endif