xref: /xnu-8020.101.4/EXTERNAL_HEADERS/ptrcheck.h (revision e7776783b89a353188416a9a346c6cdb4928faad)
1*e7776783SApple OSS Distributions /*===---- ptrcheck.h - Pointer bounds hints & specifications ----------------===
2*e7776783SApple OSS Distributions  *
3*e7776783SApple OSS Distributions  * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*e7776783SApple OSS Distributions  * See https://llvm.org/LICENSE.txt for license information.
5*e7776783SApple OSS Distributions  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*e7776783SApple OSS Distributions  *
7*e7776783SApple OSS Distributions  *===-----------------------------------------------------------------------===
8*e7776783SApple OSS Distributions  */
9*e7776783SApple OSS Distributions 
10*e7776783SApple OSS Distributions #ifndef __PTRCHECK_H
11*e7776783SApple OSS Distributions #define __PTRCHECK_H
12*e7776783SApple OSS Distributions 
13*e7776783SApple OSS Distributions /* __has_ptrcheck can be used in preprocessor macros (and other parts of the
14*e7776783SApple OSS Distributions    language expecting constant expressions) to test if bounds attributes
15*e7776783SApple OSS Distributions    exist. */
16*e7776783SApple OSS Distributions #if defined(__has_feature) && __has_feature(bounds_attributes)
17*e7776783SApple OSS Distributions   #define __has_ptrcheck 1
18*e7776783SApple OSS Distributions #else
19*e7776783SApple OSS Distributions   #define __has_ptrcheck 0
20*e7776783SApple OSS Distributions #endif
21*e7776783SApple OSS Distributions 
22*e7776783SApple OSS Distributions #if __has_ptrcheck
23*e7776783SApple OSS Distributions 
24*e7776783SApple OSS Distributions /* An attribute that modifies a pointer type such that its ABI is three pointer
25*e7776783SApple OSS Distributions    components: the pointer value itself (the pointer value); one-past-the-end of
26*e7776783SApple OSS Distributions    the object it is derived from (the upper bound); and the base address of the
27*e7776783SApple OSS Distributions    object it is derived from (the lower bound). The pointer value is allowed to
28*e7776783SApple OSS Distributions    lie outside the [lower bound, upper bound) interval, and it supports the
29*e7776783SApple OSS Distributions    entire range of arithmetic operations that are usually applicable to
30*e7776783SApple OSS Distributions    pointers. Bounds are implicitly checked only when the pointer is dereferenced
31*e7776783SApple OSS Distributions    or converted to a different representation. */
32*e7776783SApple OSS Distributions #define __bidi_indexable __attribute__((__bidi_indexable__))
33*e7776783SApple OSS Distributions 
34*e7776783SApple OSS Distributions /* An attribute that modifies a pointer type such that its ABI is two pointer
35*e7776783SApple OSS Distributions    components: the pointer value itself (the lower bound); and one-past-the-end
36*e7776783SApple OSS Distributions    of the object it is derived from (the upper bound). Indexable pointers do not
37*e7776783SApple OSS Distributions    support negative arithmetic operations: it is a compile-time error to use a
38*e7776783SApple OSS Distributions    subtraction or add a negative quantity to them, and it is a runtime error if
39*e7776783SApple OSS Distributions    the same happens at runtime while it can't be detected at compile-time. Same
40*e7776783SApple OSS Distributions    as __bidi_indexable pointers, __indexable pointers are bounds-checked when
41*e7776783SApple OSS Distributions    dereferenced or converted to another representation. */
42*e7776783SApple OSS Distributions #define __indexable __attribute__((__indexable__))
43*e7776783SApple OSS Distributions 
44*e7776783SApple OSS Distributions /* An attribute that modifies a pointer type such than it has the ABI of a
45*e7776783SApple OSS Distributions    regular C pointer, without allowing pointer arithmetic. Pointer arithmetic is
46*e7776783SApple OSS Distributions    a compile-time error. A __single pointer is expected to be either NULL or
47*e7776783SApple OSS Distributions    point to exactly one valid value. */
48*e7776783SApple OSS Distributions #define __single __attribute__((__single__))
49*e7776783SApple OSS Distributions 
50*e7776783SApple OSS Distributions /* An attribute that modifies a pointer type such than it can be used exactly
51*e7776783SApple OSS Distributions    like a regular C pointer, with unchecked arithmetic and dereferencing. An
52*e7776783SApple OSS Distributions    __unsafe_indexable pointer cannot convert implicitly to another type of
53*e7776783SApple OSS Distributions    pointer since that would require information that is not available to the
54*e7776783SApple OSS Distributions    program. You must use __unsafe_forge_bidi_indexable or __unsafe_forge_single
55*e7776783SApple OSS Distributions    to convert __unsafe_indexable pointers to so-called safe pointers. */
56*e7776783SApple OSS Distributions #define __unsafe_indexable __attribute__((__unsafe_indexable__))
57*e7776783SApple OSS Distributions 
58*e7776783SApple OSS Distributions /* An attribute that modifies a pointer type such that it has the ABI of a
59*e7776783SApple OSS Distributions    regular C pointer, but it implicitly converts to a __bidi_indexable pointer
60*e7776783SApple OSS Distributions    with bounds that assume there are N valid elements starting at its address.
61*e7776783SApple OSS Distributions    The conversion happens at the same point the object converts to an rvalue, or
62*e7776783SApple OSS Distributions    immediately for values which cannot be lvalues (such as function calls). */
63*e7776783SApple OSS Distributions 
64*e7776783SApple OSS Distributions /* Assignments to the pointer object must be accompanied with an assignment to
65*e7776783SApple OSS Distributions    N if it is assignable. */
66*e7776783SApple OSS Distributions 
67*e7776783SApple OSS Distributions /* N must either be an expression that evaluates to a constant, or an integer
68*e7776783SApple OSS Distributions    declaration from the same scope, or (for structure fields) a declaration
69*e7776783SApple OSS Distributions    contained in basic arithmetic. */
70*e7776783SApple OSS Distributions #define __counted_by(N) __attribute__((__counted_by__(N)))
71*e7776783SApple OSS Distributions 
72*e7776783SApple OSS Distributions /* Identical to __counted_by(N), aside that N is a byte count instead of an
73*e7776783SApple OSS Distributions    object count. */
74*e7776783SApple OSS Distributions #define __sized_by(N) __attribute__((__sized_by__(N)))
75*e7776783SApple OSS Distributions 
76*e7776783SApple OSS Distributions /* An attribute that modifies a pointer type such that it has the ABI of a
77*e7776783SApple OSS Distributions    regular C pointer, but it implicitly converts to a __bidi_indexable pointer
78*e7776783SApple OSS Distributions    with bounds that assume that E is one-past-the-end of the original object.
79*e7776783SApple OSS Distributions    Implicitly, referencing E in the same scope will create a pointer that
80*e7776783SApple OSS Distributions    converts to a __bidi_indexable pointer one-past-the-end of the original
81*e7776783SApple OSS Distributions    object, but with a lower bound set to the value of the pointer that is
82*e7776783SApple OSS Distributions    attributed. */
83*e7776783SApple OSS Distributions 
84*e7776783SApple OSS Distributions /* Assignments to the pointer object must be accompanied with an assignment to
85*e7776783SApple OSS Distributions    E if it is assignable. */
86*e7776783SApple OSS Distributions #define __ended_by(E) __attribute__((__ended_by__(E)))
87*e7776783SApple OSS Distributions 
88*e7776783SApple OSS Distributions /* Directives that tells the compiler to assume that subsequent pointer types
89*e7776783SApple OSS Distributions    have the ABI specified by the ABI parameter, which may be one of single,
90*e7776783SApple OSS Distributions    indexable, bidi_indexable or unsafe_indexable. */
91*e7776783SApple OSS Distributions 
92*e7776783SApple OSS Distributions /* In project files, the ABI is assumed to be single by default. In headers
93*e7776783SApple OSS Distributions    included from libraries or the SDK, the ABI is assumed to be unsafe_indexable
94*e7776783SApple OSS Distributions    by default. */
95*e7776783SApple OSS Distributions #define __ptrcheck_abi_assume_single() \
96*e7776783SApple OSS Distributions   _Pragma("clang abi_ptr_attr set(single)")
97*e7776783SApple OSS Distributions 
98*e7776783SApple OSS Distributions #define __ptrcheck_abi_assume_indexable() \
99*e7776783SApple OSS Distributions   _Pragma("clang abi_ptr_attr set(indexable)")
100*e7776783SApple OSS Distributions 
101*e7776783SApple OSS Distributions #define __ptrcheck_abi_assume_bidi_indexable() \
102*e7776783SApple OSS Distributions   _Pragma("clang abi_ptr_attr set(bidi_indexable)")
103*e7776783SApple OSS Distributions 
104*e7776783SApple OSS Distributions #define __ptrcheck_abi_assume_unsafe_indexable() \
105*e7776783SApple OSS Distributions   _Pragma("clang abi_ptr_attr set(unsafe_indexable)")
106*e7776783SApple OSS Distributions 
107*e7776783SApple OSS Distributions /* Create a __bidi_indexable pointer of a given pointer type (T), starting at
108*e7776783SApple OSS Distributions    address P, pointing to S bytes of valid memory. T must be a pointer type. */
109*e7776783SApple OSS Distributions #define __unsafe_forge_bidi_indexable(T, P, S) \
110*e7776783SApple OSS Distributions   ((T __bidi_indexable)__builtin_unsafe_forge_bidi_indexable((P), (S)))
111*e7776783SApple OSS Distributions 
112*e7776783SApple OSS Distributions /* Create a __single pointer of a given type (T), starting at address P. T must
113*e7776783SApple OSS Distributions    be a pointer type. */
114*e7776783SApple OSS Distributions #define __unsafe_forge_single(T, P) \
115*e7776783SApple OSS Distributions   ((T __single)__builtin_unsafe_forge_single((P)))
116*e7776783SApple OSS Distributions 
117*e7776783SApple OSS Distributions /* Create a wide pointer with the same lower bound and upper bounds as X, but
118*e7776783SApple OSS Distributions    with a pointer component also equal to the lower bound. */
119*e7776783SApple OSS Distributions #define __ptr_lower_bound(X) __builtin_get_pointer_lower_bound(X)
120*e7776783SApple OSS Distributions 
121*e7776783SApple OSS Distributions /* Create a wide pointer with the same lower bound and upper bounds as X, but
122*e7776783SApple OSS Distributions    with a pointer component also equal to the upper bound. */
123*e7776783SApple OSS Distributions #define __ptr_upper_bound(X) __builtin_get_pointer_upper_bound(X)
124*e7776783SApple OSS Distributions 
125*e7776783SApple OSS Distributions /* Instruct the compiler to disregard the bounds of an array used in a function
126*e7776783SApple OSS Distributions    prototype and allow the decayed pointer to use __counted_by. This is a niche
127*e7776783SApple OSS Distributions    capability that is only useful in limited patterns (the way that `mig` uses
128*e7776783SApple OSS Distributions    arrays being one of them). */
129*e7776783SApple OSS Distributions #define __array_decay_dicards_count_in_parameters \
130*e7776783SApple OSS Distributions   __attribute__((__decay_discards_count_in_parameters__))
131*e7776783SApple OSS Distributions 
132*e7776783SApple OSS Distributions #else
133*e7776783SApple OSS Distributions 
134*e7776783SApple OSS Distributions /* We intentionally define to nothing pointer attributes which do not have an
135*e7776783SApple OSS Distributions    impact on the ABI. __indexable and __bidi_indexable are not defined because
136*e7776783SApple OSS Distributions    of the ABI incompatibility that makes the diagnostic preferable. */
137*e7776783SApple OSS Distributions #define __single
138*e7776783SApple OSS Distributions #define __unsafe_indexable
139*e7776783SApple OSS Distributions #define __counted_by(N)
140*e7776783SApple OSS Distributions #define __sized_by(N)
141*e7776783SApple OSS Distributions #define __ended_by(E)
142*e7776783SApple OSS Distributions 
143*e7776783SApple OSS Distributions /* Similarly, we intentionally define to nothing the
144*e7776783SApple OSS Distributions    __ptrcheck_abi_assume_single and __ptrcheck_abi_assume_unsafe_indexable
145*e7776783SApple OSS Distributions    macros because they do not lead to an ABI incompatibility. However, we do not
146*e7776783SApple OSS Distributions    define the indexable and unsafe_indexable ones because the diagnostic is
147*e7776783SApple OSS Distributions    better than the silent ABI break. */
148*e7776783SApple OSS Distributions #define __ptrcheck_abi_assume_single()
149*e7776783SApple OSS Distributions #define __ptrcheck_abi_assume_unsafe_indexable()
150*e7776783SApple OSS Distributions 
151*e7776783SApple OSS Distributions /* __unsafe_forge intrinsics are defined as regular C casts. */
152*e7776783SApple OSS Distributions #define __unsafe_forge_bidi_indexable(T, P, S) ((T)(P))
153*e7776783SApple OSS Distributions #define __unsafe_forge_single(T, P) ((T)(P))
154*e7776783SApple OSS Distributions 
155*e7776783SApple OSS Distributions /* decay operates normally; attribute is meaningless without pointer checks. */
156*e7776783SApple OSS Distributions #define __array_decay_dicards_count_in_parameters
157*e7776783SApple OSS Distributions 
158*e7776783SApple OSS Distributions #endif /* __has_ptrcheck */
159*e7776783SApple OSS Distributions 
160*e7776783SApple OSS Distributions #endif /* __PTRCHECK_H */
161