fortify-headers.h (5686B)
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_HEADERS_H 18 #define _FORTIFY_HEADERS_H 19 20 #if !defined __has_builtin 21 #error a compiler with __has_builtin support is required 22 #endif 23 24 // https://clang.llvm.org/docs/LanguageExtensions.html#has-builtin 25 // > __has_builtin should not be used to detect support for a builtin macro; use #ifdef instead. 26 #define __fh_has_builtin(x) (__has_builtin(x) || defined(x)) 27 28 #if ! __fh_has_builtin(__builtin_trap) 29 #define __builtin_trap abort 30 #endif 31 32 #if _FORTIFY_SOURCE > 3 33 #warning _FORTIFY_SOURCE > 3 is treated as 3 34 #endif 35 36 #ifdef __clang__ 37 38 #if _FORTIFY_SOURCE > 2 && __fh_has_builtin (__builtin_dynamic_object_size) && __has_attribute(pass_dynamic_object_size) 39 #define _FORTIFY_POSN(n) const __attribute__((pass_dynamic_object_size(n))) 40 #else 41 #define _FORTIFY_POSN(n) const __attribute__((pass_object_size(n))) 42 #endif /* __builtin_dynamic_object_size && pass_dynamic_object_size */ 43 44 /* clang uses overloads; see https://github.com/llvm/llvm-project/issues/53516 */ 45 /* we can't use extern inline with overloads without making them external */ 46 #ifdef __cplusplus 47 #define _FORTIFY_INLINE __inline__ \ 48 __attribute__((__always_inline__,__artificial__,__overloadable__)) 49 #else 50 #define _FORTIFY_INLINE static __inline__ \ 51 __attribute__((__always_inline__,__artificial__,__overloadable__)) 52 #endif 53 54 #else /* !__clang__ */ 55 56 #define _FORTIFY_POSN(n) 57 #define _FORTIFY_INLINE extern __inline__ \ 58 __attribute__((__always_inline__,__gnu_inline__,__artificial__)) 59 60 #endif /* __clang__ */ 61 62 /* https://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html */ 63 #define _FORTIFY_POS0 _FORTIFY_POSN(0) 64 #define _FORTIFY_POS1 _FORTIFY_POSN(1) 65 #define _FORTIFY_POS2 _FORTIFY_POSN(2) 66 67 #define _FORTIFY_STR(s) #s 68 #define _FORTIFY_ORIG(p,fn) __typeof__(fn) __orig_##fn __asm__(_FORTIFY_STR(p) #fn) 69 #define _FORTIFY_FNB(fn) _FORTIFY_ORIG(__USER_LABEL_PREFIX__,fn) 70 #define _FORTIFY_FN(fn) _FORTIFY_FNB(fn); _FORTIFY_INLINE 71 72 /* Use __builtin_dynamic_object_size with _FORTIFY_SOURCE>2, if available. */ 73 #if _FORTIFY_SOURCE > 2 && __fh_has_builtin (__builtin_dynamic_object_size) 74 /* 75 * See: 76 * - https://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html 77 */ 78 #define __fh_bos(ptr, type) __builtin_dynamic_object_size (ptr, type) 79 #else 80 #define __fh_bos(ptr, type) __builtin_object_size (ptr, type) 81 #endif 82 83 #if defined __has_attribute 84 #if __has_attribute (access) 85 #define __fh_access(...) __attribute__ ((access (__VA_ARGS__))) 86 #else 87 #define __fh_access(...) 88 #endif 89 90 #if __has_attribute (format) 91 #define __fh_format(...) __attribute__ ((format (__VA_ARGS__))) 92 #else 93 #define __fh_format(...) 94 #endif 95 96 #if __has_attribute (malloc) 97 #ifdef __clang__ 98 #define __fh_malloc(...) __attribute__ ((malloc)) 99 #else 100 #define __fh_malloc(...) __attribute__ ((malloc, __VA_ARGS__)) 101 #endif /* __clang__ */ 102 #else 103 #define __fh_malloc(...) 104 #endif 105 106 #if __has_attribute (alloc_size) && !defined(__fh_alloc_size) 107 #define __fh_alloc_size(...) __attribute__ ((alloc_size (__VA_ARGS__))) 108 #else 109 #define __fh_alloc_size(...) 110 #endif 111 112 #if __has_attribute (diagnose_as_builtin) 113 #define __diagnose_as_builtin(...) __attribute__ ((diagnose_as_builtin (__VA_ARGS__))) 114 #else 115 #define __diagnose_as_builtin(...) 116 #endif 117 118 #if __has_attribute (diagnose_if) 119 #define __warning_if(cond, msg) __attribute__ ((diagnose_if (cond, msg, "warning"))) 120 #define __error_if(cond, msg) __attribute__ ((diagnose_if (cond, msg, "error"))) 121 #else 122 #define __warning_if(cond, msg) 123 #define __error_if(cond, msg) 124 #endif 125 126 #if __has_attribute (warn_unused_result) 127 #define __warn_unused_result __attribute__ ((warn_unused_result)) 128 #else 129 #define __warn_unused_result 130 #endif 131 132 133 #endif /* __has_attribute */ 134 135 // Since we're not allow to include anything. 136 // https://awesomekling.github.io/How-SerenityOS-declares-ssize_t/ 137 #define __fh_size_t __typeof__(sizeof(char)) 138 139 //TODO(jvoisin) Add a check for overflows 140 /* check if pointers are overlapping but not if dst == src, 141 * since gcc seems to like to generate code that relies on dst == src */ 142 #define __fh_overlap(a, len_a, b, len_b) \ 143 ( \ 144 ((char*)(a) < (char*)(b) && (char*)(b) < ((char*)(a) + (__fh_size_t)(len_a))) \ 145 || ((char*)(b) < (char*)(a) && (char*)(a) < ((char*)(b) + (__fh_size_t)(len_b))) \ 146 ) 147 148 /* 149 * We're not making use of C23's <stdckdint.h> since: 150 * - there is no elegant way to make it ignore the results. 151 * - it's tricky to make it type-agnostic when we don't care about the result. 152 * We're not making use of __builtin_mul_overflow for the same reasons. 153 * 154 * See: 155 * - https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html 156 * - https://clang.llvm.org/docs/LanguageExtensions.html#checked-arithmetic-builtins 157 */ 158 #if __fh_has_builtin (__builtin_mul_overflow_p) 159 #define __bmo(x, y) (x != 0 && __builtin_mul_overflow_p(x, y, (__typeof__ ((x) + (y))) 0)) 160 #else /* !__builtin_mul_overflow_p */ 161 #define __bmo(x, y) (x != 0 && (x * y) / x != y) 162 #endif /* __builtin_mul_overflow_p */ 163 164 #endif /* _FORTIFY_HEADERS_H */