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 | |