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