xref: /xnu-8020.121.3/EXTERNAL_HEADERS/ptrcheck.h (revision fdd8201d7b966f0c3ea610489d29bd841d358941)
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 /* Directives that tells the compiler to assume that subsequent pointer types
89    have the ABI specified by the ABI parameter, which may be one of single,
90    indexable, bidi_indexable or unsafe_indexable. */
91 
92 /* In project files, the ABI is assumed to be single by default. In headers
93    included from libraries or the SDK, the ABI is assumed to be unsafe_indexable
94    by default. */
95 #define __ptrcheck_abi_assume_single() \
96   _Pragma("clang abi_ptr_attr set(single)")
97 
98 #define __ptrcheck_abi_assume_indexable() \
99   _Pragma("clang abi_ptr_attr set(indexable)")
100 
101 #define __ptrcheck_abi_assume_bidi_indexable() \
102   _Pragma("clang abi_ptr_attr set(bidi_indexable)")
103 
104 #define __ptrcheck_abi_assume_unsafe_indexable() \
105   _Pragma("clang abi_ptr_attr set(unsafe_indexable)")
106 
107 /* Create a __bidi_indexable pointer of a given pointer type (T), starting at
108    address P, pointing to S bytes of valid memory. T must be a pointer type. */
109 #define __unsafe_forge_bidi_indexable(T, P, S) \
110   ((T __bidi_indexable)__builtin_unsafe_forge_bidi_indexable((P), (S)))
111 
112 /* Create a __single pointer of a given type (T), starting at address P. T must
113    be a pointer type. */
114 #define __unsafe_forge_single(T, P) \
115   ((T __single)__builtin_unsafe_forge_single((P)))
116 
117 /* Create a wide pointer with the same lower bound and upper bounds as X, but
118    with a pointer component also equal to the lower bound. */
119 #define __ptr_lower_bound(X) __builtin_get_pointer_lower_bound(X)
120 
121 /* Create a wide pointer with the same lower bound and upper bounds as X, but
122    with a pointer component also equal to the upper bound. */
123 #define __ptr_upper_bound(X) __builtin_get_pointer_upper_bound(X)
124 
125 /* Instruct the compiler to disregard the bounds of an array used in a function
126    prototype and allow the decayed pointer to use __counted_by. This is a niche
127    capability that is only useful in limited patterns (the way that `mig` uses
128    arrays being one of them). */
129 #define __array_decay_dicards_count_in_parameters \
130   __attribute__((__decay_discards_count_in_parameters__))
131 
132 #else
133 
134 /* We intentionally define to nothing pointer attributes which do not have an
135    impact on the ABI. __indexable and __bidi_indexable are not defined because
136    of the ABI incompatibility that makes the diagnostic preferable. */
137 #define __single
138 #define __unsafe_indexable
139 #define __counted_by(N)
140 #define __sized_by(N)
141 #define __ended_by(E)
142 
143 /* Similarly, we intentionally define to nothing the
144    __ptrcheck_abi_assume_single and __ptrcheck_abi_assume_unsafe_indexable
145    macros because they do not lead to an ABI incompatibility. However, we do not
146    define the indexable and unsafe_indexable ones because the diagnostic is
147    better than the silent ABI break. */
148 #define __ptrcheck_abi_assume_single()
149 #define __ptrcheck_abi_assume_unsafe_indexable()
150 
151 /* __unsafe_forge intrinsics are defined as regular C casts. */
152 #define __unsafe_forge_bidi_indexable(T, P, S) ((T)(P))
153 #define __unsafe_forge_single(T, P) ((T)(P))
154 
155 /* decay operates normally; attribute is meaningless without pointer checks. */
156 #define __array_decay_dicards_count_in_parameters
157 
158 #endif /* __has_ptrcheck */
159 
160 #endif /* __PTRCHECK_H */
161