| 1 | /*===---- ptrcheck.h - Pointer bounds hints & specifications ----------------=== |
| 2 | * |
| 3 | * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | * See https://llvm.org/LICENSE.txt for license information. |
| 5 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | * |
| 7 | *===-----------------------------------------------------------------------=== |
| 8 | */ |
| 9 | |
| 10 | #ifndef __PTRCHECK_H |
| 11 | #define __PTRCHECK_H |
| 12 | |
| 13 | /* __has_ptrcheck can be used in preprocessor macros (and other parts of the |
| 14 | language expecting constant expressions) to test if bounds attributes |
| 15 | exist. */ |
| 16 | #if defined(__has_feature) && __has_feature(bounds_attributes) |
| 17 | #define __has_ptrcheck 1 |
| 18 | #else |
| 19 | #define __has_ptrcheck 0 |
| 20 | #endif |
| 21 | |
| 22 | #if __has_ptrcheck |
| 23 | |
| 24 | /* An attribute that modifies a pointer type such that its ABI is three pointer |
| 25 | components: the pointer value itself (the pointer value); one-past-the-end of |
| 26 | the object it is derived from (the upper bound); and the base address of the |
| 27 | object it is derived from (the lower bound). The pointer value is allowed to |
| 28 | lie outside the [lower bound, upper bound) interval, and it supports the |
| 29 | entire range of arithmetic operations that are usually applicable to |
| 30 | pointers. Bounds are implicitly checked only when the pointer is dereferenced |
| 31 | or converted to a different representation. */ |
| 32 | #define __bidi_indexable __attribute__((__bidi_indexable__)) |
| 33 | |
| 34 | /* An attribute that modifies a pointer type such that its ABI is two pointer |
| 35 | components: the pointer value itself (the lower bound); and one-past-the-end |
| 36 | of the object it is derived from (the upper bound). Indexable pointers do not |
| 37 | support negative arithmetic operations: it is a compile-time error to use a |
| 38 | subtraction or add a negative quantity to them, and it is a runtime error if |
| 39 | the same happens at runtime while it can't be detected at compile-time. Same |
| 40 | as __bidi_indexable pointers, __indexable pointers are bounds-checked when |
| 41 | dereferenced or converted to another representation. */ |
| 42 | #define __indexable __attribute__((__indexable__)) |
| 43 | |
| 44 | /* An attribute that modifies a pointer type such than it has the ABI of a |
| 45 | regular C pointer, without allowing pointer arithmetic. Pointer arithmetic is |
| 46 | a compile-time error. A __single pointer is expected to be either NULL or |
| 47 | point to exactly one valid value. */ |
| 48 | #define __single __attribute__((__single__)) |
| 49 | |
| 50 | /* An attribute that modifies a pointer type such than it can be used exactly |
| 51 | like a regular C pointer, with unchecked arithmetic and dereferencing. An |
| 52 | __unsafe_indexable pointer cannot convert implicitly to another type of |
| 53 | pointer since that would require information that is not available to the |
| 54 | program. You must use __unsafe_forge_bidi_indexable or __unsafe_forge_single |
| 55 | to convert __unsafe_indexable pointers to so-called safe pointers. */ |
| 56 | #define __unsafe_indexable __attribute__((__unsafe_indexable__)) |
| 57 | |
| 58 | /* An attribute that modifies a pointer type such that it has the ABI of a |
| 59 | regular C pointer, but it implicitly converts to a __bidi_indexable pointer |
| 60 | with bounds that assume there are N valid elements starting at its address. |
| 61 | The conversion happens at the same point the object converts to an rvalue, or |
| 62 | immediately for values which cannot be lvalues (such as function calls). */ |
| 63 | |
| 64 | /* Assignments to the pointer object must be accompanied with an assignment to |
| 65 | N if it is assignable. */ |
| 66 | |
| 67 | /* N must either be an expression that evaluates to a constant, or an integer |
| 68 | declaration from the same scope, or (for structure fields) a declaration |
| 69 | contained in basic arithmetic. */ |
| 70 | #define __counted_by(N) __attribute__((__counted_by__(N))) |
| 71 | |
| 72 | /* Identical to __counted_by(N), aside that N is a byte count instead of an |
| 73 | object count. */ |
| 74 | #define __sized_by(N) __attribute__((__sized_by__(N))) |
| 75 | |
| 76 | /* An attribute that modifies a pointer type such that it has the ABI of a |
| 77 | regular C pointer, but it implicitly converts to a __bidi_indexable pointer |
| 78 | with bounds that assume that E is one-past-the-end of the original object. |
| 79 | Implicitly, referencing E in the same scope will create a pointer that |
| 80 | converts to a __bidi_indexable pointer one-past-the-end of the original |
| 81 | object, but with a lower bound set to the value of the pointer that is |
| 82 | attributed. */ |
| 83 | |
| 84 | /* Assignments to the pointer object must be accompanied with an assignment to |
| 85 | E if it is assignable. */ |
| 86 | #define __ended_by(E) __attribute__((__ended_by__(E))) |
| 87 | |
| 88 | /* The __terminated_by(T) attribute can be applied to arrays and pointers. The |
| 89 | argument T specifies the terminator and must be an integer constant |
| 90 | expression. Even though T has to be an integer constant, __terminated_by(T) |
| 91 | can be applied to pointer arrays as well. For convenience, the |
| 92 | __null_terminated macro is provided, which is equivalent to |
| 93 | __terminated_by(0). |
| 94 | |
| 95 | The __terminated_by(T) attribute can be applied only to __single pointers. If |
| 96 | the pointer attribute is not specified, it is automatically set to __single. |
| 97 | A __terminated_by(T) pointer points to the first element of an array that is |
| 98 | terminated with T. |
| 99 | |
| 100 | Arithmetic on __terminated_by(T) pointers is restricted to only incrementing |
| 101 | the pointer by one, and must be able to be evaluated at compile-time. |
| 102 | Pointer arithmetic generates a runtime check to ensure that the pointer |
| 103 | doesn't point pass the terminator. |
| 104 | |
| 105 | A __terminated_by(T) pointer has the ABI of a regular C pointer. |
| 106 | |
| 107 | When __terminated_by(T) is applied to an array, the compiler checks if the |
| 108 | array is terminated with the given terminator T during the initialization. |
| 109 | Moreover, a __terminated_by(T) array decays to a __terminated_by(T) __single |
| 110 | pointer, instead of decaying to a __bidi_indexable pointer. */ |
| 111 | #define __terminated_by(T) __attribute__((__terminated_by__(T))) |
| 112 | #define __null_terminated __terminated_by(0) |
| 113 | |
| 114 | /* Directives that tells the compiler to assume that subsequent pointer types |
| 115 | have the ABI specified by the ABI parameter, which may be one of single, |
| 116 | indexable, bidi_indexable or unsafe_indexable. */ |
| 117 | |
| 118 | /* In project files, the ABI is assumed to be single by default. In headers |
| 119 | included from libraries or the SDK, the ABI is assumed to be unsafe_indexable |
| 120 | by default. */ |
| 121 | #define __ptrcheck_abi_assume_single() \ |
| 122 | _Pragma("clang abi_ptr_attr set(single)") |
| 123 | |
| 124 | #define __ptrcheck_abi_assume_indexable() \ |
| 125 | _Pragma("clang abi_ptr_attr set(indexable)") |
| 126 | |
| 127 | #define __ptrcheck_abi_assume_bidi_indexable() \ |
| 128 | _Pragma("clang abi_ptr_attr set(bidi_indexable)") |
| 129 | |
| 130 | #define __ptrcheck_abi_assume_unsafe_indexable() \ |
| 131 | _Pragma("clang abi_ptr_attr set(unsafe_indexable)") |
| 132 | |
| 133 | /* Create a __bidi_indexable pointer of a given pointer type (T), starting at |
| 134 | address P, pointing to S bytes of valid memory. T must be a pointer type. */ |
| 135 | #define __unsafe_forge_bidi_indexable(T, P, S) \ |
| 136 | ((T __bidi_indexable)__builtin_unsafe_forge_bidi_indexable((P), (S))) |
| 137 | |
| 138 | /* Create a __single pointer of a given type (T), starting at address P. T must |
| 139 | be a pointer type. */ |
| 140 | #define __unsafe_forge_single(T, P) \ |
| 141 | ((T __single)__builtin_unsafe_forge_single((P))) |
| 142 | |
| 143 | /* Create a __terminated_by pointer of a given pointer type (T), starting at |
| 144 | address P, terminated by E. T must be a pointer type. */ |
| 145 | #define __unsafe_forge_terminated_by(T, P, E) \ |
| 146 | ((T __terminated_by(E))__builtin_unsafe_forge_terminated_by((P), (E))) |
| 147 | |
| 148 | /* Create a __terminated_by pointer of a given pointer type (T), starting at |
| 149 | address P, terminated by 0. T must be a pointer type. */ |
| 150 | #define __unsafe_forge_null_terminated(T, P) __unsafe_forge_terminated_by(T, P, 0) |
| 151 | |
| 152 | /* Create a wide pointer with the same lower bound and upper bounds as X, but |
| 153 | with a pointer component also equal to the lower bound. */ |
| 154 | #define __ptr_lower_bound(X) __builtin_get_pointer_lower_bound(X) |
| 155 | |
| 156 | /* Create a wide pointer with the same lower bound and upper bounds as X, but |
| 157 | with a pointer component also equal to the upper bound. */ |
| 158 | #define __ptr_upper_bound(X) __builtin_get_pointer_upper_bound(X) |
| 159 | |
| 160 | /* Convert a __terminated_by(T) pointer to an __indexable pointer. These |
| 161 | operations will calculate the upper bound by iterating over the memory |
| 162 | pointed to by P in order to find the terminator. |
| 163 | |
| 164 | The __terminated_by_to_indexable(P) does NOT include the terminator within |
| 165 | bounds of the __indexable pointer. Consequently, the terminator cannot be |
| 166 | erased (or even accessed) through the __indexable pointer. The address one |
| 167 | past the end of the array (pointing to the terminator) can be found with |
| 168 | __ptr_upper_bound(). |
| 169 | |
| 170 | The __unsafe_terminated_by_to_indexable(P) does include the terminator within |
| 171 | the bounds of the __indexable pointer. This makes the operation unsafe, since |
| 172 | the terminator can be erased, and thus using P might result in out-of-bounds |
| 173 | access. */ |
| 174 | #define __terminated_by_to_indexable(P) \ |
| 175 | __builtin_terminated_by_to_indexable(P) |
| 176 | #define __unsafe_terminated_by_to_indexable(P) \ |
| 177 | __builtin_unsafe_terminated_by_to_indexable(P) |
| 178 | |
| 179 | #define __null_terminated_to_indexable(P) \ |
| 180 | ({ \ |
| 181 | __typeof__(*(P)) *__null_terminated __ptr = (P); \ |
| 182 | __terminated_by_to_indexable(__ptr); \ |
| 183 | }) |
| 184 | |
| 185 | #define __unsafe_null_terminated_to_indexable(P) \ |
| 186 | ({ \ |
| 187 | __typeof__(*(P)) *__null_terminated __ptr = (P); \ |
| 188 | __unsafe_terminated_by_to_indexable(__ptr); \ |
| 189 | }) |
| 190 | |
| 191 | /* __unsafe_terminated_by_from_indexable(T, PTR [, PTR_TO_TERM]) converts an |
| 192 | __indexable pointer to a __terminated_by(T) pointer. The operation will |
| 193 | check if the given terminator T occurs in the memory pointed to by PTR. |
| 194 | If so, the operation evaluates to __terminated_by(T) pointer. Otherwise, it |
| 195 | traps. |
| 196 | |
| 197 | The operation has an optional parameter PTR_TO_TERM, which changes the way |
| 198 | how the check for the terminator existence is generated. PTR_TO_TERM must |
| 199 | point to the terminator element and be within the bounds of PTR. |
| 200 | If PTR_TO_TERM is provided, the runtime will check if it is in fact within |
| 201 | the bounds and points to an element that equals to T. If PTR_TO_TERM is not |
| 202 | provided, the runtime will iterate over the memory pointed to by PTR to find |
| 203 | the terminator. |
| 204 | |
| 205 | The operation is unsafe, since the terminator can be erased through PTR after |
| 206 | the conversion. This can result in out-of-bounds access through the newly |
| 207 | created __terminated_by(T) pointer. |
| 208 | |
| 209 | For convenience, the |
| 210 | __unsafe_null_terminated_from_indexable(PTR [, PTR_TO_TERM]) macro is |
| 211 | provided, which assumes that the terminator is 0. */ |
| 212 | #define __unsafe_terminated_by_from_indexable(T, ...) \ |
| 213 | __builtin_unsafe_terminated_by_from_indexable((T), __VA_ARGS__) |
| 214 | #define __unsafe_null_terminated_from_indexable(...) \ |
| 215 | __builtin_unsafe_terminated_by_from_indexable(0, __VA_ARGS__) |
| 216 | |
| 217 | /* Instruct the compiler to disregard the bounds of an array used in a function |
| 218 | prototype and allow the decayed pointer to use __counted_by. This is a niche |
| 219 | capability that is only useful in limited patterns (the way that `mig` uses |
| 220 | arrays being one of them). */ |
| 221 | #define __array_decay_dicards_count_in_parameters \ |
| 222 | __attribute__((__decay_discards_count_in_parameters__)) |
| 223 | |
| 224 | /* An attribute to indicate a variable to be effectively constant (or data const) |
| 225 | that it is allocated in a const section so cannot be modified after an early |
| 226 | stage of bootup, for example. Adding this attribute allows a global variable |
| 227 | to be used in __counted_by attribute of struct fields, function parameter, or |
| 228 | local variable just like actual constants. |
| 229 | Note that ensuring the value never changes once it is used is the user's |
| 230 | responsibility. One way to achieve this is the xnu model, in which certain |
| 231 | variables are placed in a segment that is remapped as read-only after |
| 232 | initialization. */ |
| 233 | #define __unsafe_late_const __attribute__((__unsafe_late_const__)) |
| 234 | |
| 235 | /* An attribute to indicate that a function is unavailable when -fbounds-safety |
| 236 | is enabled because it is unsafe. Calls to functions annotated with this |
| 237 | attribute are errors when -fbounds-safety is enabled, but are allowed when |
| 238 | -fbounds-safety is disabled. |
| 239 | |
| 240 | Example: |
| 241 | |
| 242 | void* __ptrcheck_unavailable some_unsafe_api(void*); |
| 243 | */ |
| 244 | #define __ptrcheck_unavailable \ |
| 245 | __attribute__((__unavailable__("unavailable with -fbounds-safety."))) |
| 246 | |
| 247 | /* __ptrcheck_unavailable_r is the same as __ptrcheck_unavailable but it takes |
| 248 | as an argument the name of replacement function that is safe for use with |
| 249 | -fbounds-safety enabled. |
| 250 | |
| 251 | Example: |
| 252 | |
| 253 | void* __counted_by(size) safe_api(void* __counted_by(size), size_t size); |
| 254 | |
| 255 | void* __ptrcheck_unavailable_r(safe_api) some_unsafe_api(void*); |
| 256 | */ |
| 257 | #define __ptrcheck_unavailable_r(REPLACEMENT) \ |
| 258 | __attribute__((__unavailable__( \ |
| 259 | "unavailable with -fbounds-safety. Use " #REPLACEMENT " instead."))) |
| 260 | |
| 261 | #else |
| 262 | |
| 263 | /* We intentionally define to nothing pointer attributes which do not have an |
| 264 | impact on the ABI. __indexable and __bidi_indexable are not defined because |
| 265 | of the ABI incompatibility that makes the diagnostic preferable. */ |
| 266 | #define __single |
| 267 | #define __unsafe_indexable |
| 268 | #define __counted_by(N) |
| 269 | #define __sized_by(N) |
| 270 | #define __ended_by(E) |
| 271 | |
| 272 | /* We intentionally define the terminated_by attributes to nothing. */ |
| 273 | #define __terminated_by(T) |
| 274 | #define __null_terminated |
| 275 | |
| 276 | /* Similarly, we intentionally define to nothing the |
| 277 | __ptrcheck_abi_assume_single and __ptrcheck_abi_assume_unsafe_indexable |
| 278 | macros because they do not lead to an ABI incompatibility. However, we do not |
| 279 | define the indexable and unsafe_indexable ones because the diagnostic is |
| 280 | better than the silent ABI break. */ |
| 281 | #define __ptrcheck_abi_assume_single() |
| 282 | #define __ptrcheck_abi_assume_unsafe_indexable() |
| 283 | |
| 284 | /* __unsafe_forge intrinsics are defined as regular C casts. */ |
| 285 | #define __unsafe_forge_bidi_indexable(T, P, S) ((T)(P)) |
| 286 | #define __unsafe_forge_single(T, P) ((T)(P)) |
| 287 | #define __unsafe_forge_terminated_by(T, P, E) ((T)(P)) |
| 288 | #define __unsafe_forge_null_terminated(T, P) ((T)(P)) |
| 289 | |
| 290 | /* The conversion between terminated_by pointers just evaluates to the pointer |
| 291 | argument. */ |
| 292 | #define __terminated_by_to_indexable(P) (P) |
| 293 | #define __unsafe_terminated_by_to_indexable(P) (P) |
| 294 | #define __null_terminated_to_indexable(P) (P) |
| 295 | #define __unsafe_null_terminated_to_indexable(P) (P) |
| 296 | #define __unsafe_terminated_by_from_indexable(T, P, ...) (P) |
| 297 | #define __unsafe_null_terminated_from_indexable(P, ...) (P) |
| 298 | |
| 299 | /* decay operates normally; attribute is meaningless without pointer checks. */ |
| 300 | #define __array_decay_dicards_count_in_parameters |
| 301 | |
| 302 | #define __ptrcheck_unavailable |
| 303 | #define __ptrcheck_unavailable_r(R) |
| 304 | |
| 305 | #endif /* __has_ptrcheck */ |
| 306 | |
| 307 | #endif /* __PTRCHECK_H */ |
| 308 | |