|
14 | 14 | #include <__configuration/abi.h> |
15 | 15 | #include <__configuration/availability.h> |
16 | 16 | #include <__configuration/compiler.h> |
| 17 | +#include <__configuration/experimental.h> |
| 18 | +#include <__configuration/hardening.h> |
17 | 19 | #include <__configuration/language.h> |
18 | 20 | #include <__configuration/platform.h> |
19 | 21 |
|
|
38 | 40 | # define _LIBCPP_FREESTANDING |
39 | 41 | # endif |
40 | 42 |
|
41 | | -// NOLINTNEXTLINE(libcpp-cpp-version-check) |
42 | | -# if __cplusplus < 201103L |
43 | | -# define _LIBCPP_CXX03_LANG |
44 | | -# endif |
45 | | - |
46 | | -# if __has_feature(experimental_library) |
47 | | -# ifndef _LIBCPP_ENABLE_EXPERIMENTAL |
48 | | -# define _LIBCPP_ENABLE_EXPERIMENTAL |
49 | | -# endif |
50 | | -# endif |
51 | | - |
52 | | -// Incomplete features get their own specific disabling flags. This makes it |
53 | | -// easier to grep for target specific flags once the feature is complete. |
54 | | -# if defined(_LIBCPP_ENABLE_EXPERIMENTAL) || defined(_LIBCPP_BUILDING_LIBRARY) |
55 | | -# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 1 |
56 | | -# else |
57 | | -# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 0 |
58 | | -# endif |
59 | | - |
60 | | -# define _LIBCPP_HAS_EXPERIMENTAL_PSTL _LIBCPP_HAS_EXPERIMENTAL_LIBRARY |
61 | | -# define _LIBCPP_HAS_EXPERIMENTAL_TZDB _LIBCPP_HAS_EXPERIMENTAL_LIBRARY |
62 | | -# define _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM _LIBCPP_HAS_EXPERIMENTAL_LIBRARY |
63 | | -# define _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC _LIBCPP_HAS_EXPERIMENTAL_LIBRARY |
64 | | - |
65 | | -// HARDENING { |
66 | | - |
67 | | -// TODO(LLVM 23): Remove this. We're making these an error to catch folks who might not have migrated. |
68 | | -// Since hardening went through several changes (many of which impacted user-facing macros), |
69 | | -// we're keeping these checks around for a bit longer than usual. Failure to properly configure |
70 | | -// hardening results in checks being dropped silently, which is a pretty big deal. |
71 | | -# if defined(_LIBCPP_ENABLE_ASSERTIONS) |
72 | | -# error "_LIBCPP_ENABLE_ASSERTIONS has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)" |
73 | | -# endif |
74 | | -# if defined(_LIBCPP_ENABLE_HARDENED_MODE) |
75 | | -# error "_LIBCPP_ENABLE_HARDENED_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)" |
76 | | -# endif |
77 | | -# if defined(_LIBCPP_ENABLE_SAFE_MODE) |
78 | | -# error "_LIBCPP_ENABLE_SAFE_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)" |
79 | | -# endif |
80 | | -# if defined(_LIBCPP_ENABLE_DEBUG_MODE) |
81 | | -# error "_LIBCPP_ENABLE_DEBUG_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)" |
82 | | -# endif |
83 | | - |
84 | | -// The library provides the macro `_LIBCPP_HARDENING_MODE` which can be set to one of the following values: |
85 | | -// |
86 | | -// - `_LIBCPP_HARDENING_MODE_NONE`; |
87 | | -// - `_LIBCPP_HARDENING_MODE_FAST`; |
88 | | -// - `_LIBCPP_HARDENING_MODE_EXTENSIVE`; |
89 | | -// - `_LIBCPP_HARDENING_MODE_DEBUG`. |
90 | | -// |
91 | | -// These values have the following effects: |
92 | | -// |
93 | | -// - `_LIBCPP_HARDENING_MODE_NONE` -- sets the hardening mode to "none" which disables all runtime hardening checks; |
94 | | -// |
95 | | -// - `_LIBCPP_HARDENING_MODE_FAST` -- sets that hardening mode to "fast". The fast mode enables security-critical checks |
96 | | -// that can be done with relatively little runtime overhead in constant time; |
97 | | -// |
98 | | -// - `_LIBCPP_HARDENING_MODE_EXTENSIVE` -- sets the hardening mode to "extensive". The extensive mode is a superset of |
99 | | -// the fast mode that additionally enables checks that are relatively cheap and prevent common types of logic errors |
100 | | -// but are not necessarily security-critical; |
101 | | -// |
102 | | -// - `_LIBCPP_HARDENING_MODE_DEBUG` -- sets the hardening mode to "debug". The debug mode is a superset of the extensive |
103 | | -// mode and enables all checks available in the library, including internal assertions. Checks that are part of the |
104 | | -// debug mode can be very expensive and thus the debug mode is intended to be used for testing, not in production. |
105 | | - |
106 | | -// Inside the library, assertions are categorized so they can be cherry-picked based on the chosen hardening mode. These |
107 | | -// macros are only for internal use -- users should only pick one of the high-level hardening modes described above. |
108 | | -// |
109 | | -// - `_LIBCPP_ASSERT_VALID_INPUT_RANGE` -- checks that ranges (whether expressed as an iterator pair, an iterator and |
110 | | -// a sentinel, an iterator and a count, or a `std::range`) given as input to library functions are valid: |
111 | | -// - the sentinel is reachable from the begin iterator; |
112 | | -// - TODO(hardening): both iterators refer to the same container. |
113 | | -// |
114 | | -// - `_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS` -- checks that any attempts to access a container element, whether through |
115 | | -// the container object or through an iterator, are valid and do not attempt to go out of bounds or otherwise access |
116 | | -// a non-existent element. For iterator checks to work, bounded iterators must be enabled in the ABI. Types like |
117 | | -// `optional` and `function` are considered one-element containers for the purposes of this check. |
118 | | -// |
119 | | -// - `_LIBCPP_ASSERT_NON_NULL` -- checks that the pointer being dereferenced is not null. On most modern platforms zero |
120 | | -// address does not refer to an actual location in memory, so a null pointer dereference would not compromize the |
121 | | -// memory security of a program (however, it is still undefined behavior that can result in strange errors due to |
122 | | -// compiler optimizations). |
123 | | -// |
124 | | -// - `_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES` -- for functions that take several ranges as arguments, checks that the |
125 | | -// given ranges do not overlap. |
126 | | -// |
127 | | -// - `_LIBCPP_ASSERT_VALID_DEALLOCATION` -- checks that an attempt to deallocate memory is valid (e.g. the given object |
128 | | -// was allocated by the given allocator). Violating this category typically results in a memory leak. |
129 | | -// |
130 | | -// - `_LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL` -- checks that a call to an external API doesn't fail in |
131 | | -// an unexpected manner. This includes triggering documented cases of undefined behavior in an external library (like |
132 | | -// attempting to unlock an unlocked mutex in pthreads). Any API external to the library falls under this category |
133 | | -// (from system calls to compiler intrinsics). We generally don't expect these failures to compromize memory safety or |
134 | | -// otherwise create an immediate security issue. |
135 | | -// |
136 | | -// - `_LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR` -- checks any operations that exchange nodes between containers to make sure |
137 | | -// the containers have compatible allocators. |
138 | | -// |
139 | | -// - `_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN` -- checks that the given argument is within the domain of valid arguments |
140 | | -// for the function. Violating this typically produces an incorrect result (e.g. the clamp algorithm returns the |
141 | | -// original value without clamping it due to incorrect functors) or puts an object into an invalid state (e.g. |
142 | | -// a string view where only a subset of elements is possible to access). This category is for assertions violating |
143 | | -// which doesn't cause any immediate issues in the library -- whatever the consequences are, they will happen in the |
144 | | -// user code. |
145 | | -// |
146 | | -// - `_LIBCPP_ASSERT_PEDANTIC` -- checks prerequisites which are imposed by the Standard, but violating which happens to |
147 | | -// be benign in our implementation. |
148 | | -// |
149 | | -// - `_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT` -- checks that the given argument satisfies the semantic requirements imposed |
150 | | -// by the Standard. Typically, there is no simple way to completely prove that a semantic requirement is satisfied; |
151 | | -// thus, this would often be a heuristic check and it might be quite expensive. |
152 | | -// |
153 | | -// - `_LIBCPP_ASSERT_INTERNAL` -- checks that internal invariants of the library hold. These assertions don't depend on |
154 | | -// user input. |
155 | | -// |
156 | | -// - `_LIBCPP_ASSERT_UNCATEGORIZED` -- for assertions that haven't been properly classified yet. |
157 | | - |
158 | | -// clang-format off |
159 | | -# define _LIBCPP_HARDENING_MODE_NONE (1 << 1) |
160 | | -# define _LIBCPP_HARDENING_MODE_FAST (1 << 2) |
161 | | -# define _LIBCPP_HARDENING_MODE_EXTENSIVE (1 << 4) // Deliberately not ordered. |
162 | | -# define _LIBCPP_HARDENING_MODE_DEBUG (1 << 3) |
163 | | -// clang-format on |
164 | | - |
165 | | -# ifndef _LIBCPP_HARDENING_MODE |
166 | | - |
167 | | -# ifndef _LIBCPP_HARDENING_MODE_DEFAULT |
168 | | -# error _LIBCPP_HARDENING_MODE_DEFAULT is not defined. This definition should be set at configuration time in the \ |
169 | | -`__config_site` header, please make sure your installation of libc++ is not broken. |
170 | | -# endif |
171 | | - |
172 | | -# define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_DEFAULT |
173 | | -# endif |
174 | | - |
175 | | -# if _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_NONE && \ |
176 | | - _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_FAST && \ |
177 | | - _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_EXTENSIVE && \ |
178 | | - _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_DEBUG |
179 | | -# error _LIBCPP_HARDENING_MODE must be set to one of the following values: \ |
180 | | -_LIBCPP_HARDENING_MODE_NONE, \ |
181 | | -_LIBCPP_HARDENING_MODE_FAST, \ |
182 | | -_LIBCPP_HARDENING_MODE_EXTENSIVE, \ |
183 | | -_LIBCPP_HARDENING_MODE_DEBUG |
184 | | -# endif |
185 | | - |
186 | | -// Hardening assertion semantics generally mirror the evaluation semantics of C++26 Contracts: |
187 | | -// - `ignore` evaluates the assertion but doesn't do anything if it fails (note that it differs from the Contracts |
188 | | -// `ignore` semantic which wouldn't evaluate the assertion at all); |
189 | | -// - `observe` logs an error (indicating, if possible, that the error is fatal) and continues execution; |
190 | | -// - `quick-enforce` terminates the program as fast as possible (via trapping); |
191 | | -// - `enforce` logs an error and then terminates the program. |
192 | | -// |
193 | | -// Notes: |
194 | | -// - Continuing execution after a hardening check fails results in undefined behavior; the `observe` semantic is meant |
195 | | -// to make adopting hardening easier but should not be used outside of this scenario; |
196 | | -// - C++26 wording for Library Hardening precludes a conforming Hardened implementation from using the Contracts |
197 | | -// `ignore` semantic when evaluating hardened preconditions in the Library. Libc++ allows using this semantic for |
198 | | -// hardened preconditions, however, be aware that using `ignore` does not produce a conforming "Hardened" |
199 | | -// implementation, unlike the other semantics above. |
200 | | -// clang-format off |
201 | | -# define _LIBCPP_ASSERTION_SEMANTIC_IGNORE (1 << 1) |
202 | | -# define _LIBCPP_ASSERTION_SEMANTIC_OBSERVE (1 << 2) |
203 | | -# define _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE (1 << 3) |
204 | | -# define _LIBCPP_ASSERTION_SEMANTIC_ENFORCE (1 << 4) |
205 | | -// clang-format on |
206 | | - |
207 | | -// Allow users to define an arbitrary assertion semantic; otherwise, use the default mapping from modes to semantics. |
208 | | -// The default is for production-capable modes to use `quick-enforce` (i.e., trap) and for the `debug` mode to use |
209 | | -// `enforce` (i.e., log and abort). |
210 | | -# ifndef _LIBCPP_ASSERTION_SEMANTIC |
211 | | - |
212 | | -# if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG |
213 | | -# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_ENFORCE |
214 | | -# else |
215 | | -# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE |
216 | | -# endif |
217 | | - |
218 | | -# else |
219 | | -# if !_LIBCPP_HAS_EXPERIMENTAL_LIBRARY |
220 | | -# error "Assertion semantics are an experimental feature." |
221 | | -# endif |
222 | | -# if defined(_LIBCPP_CXX03_LANG) |
223 | | -# error "Assertion semantics are not available in the C++03 mode." |
224 | | -# endif |
225 | | - |
226 | | -# endif // _LIBCPP_ASSERTION_SEMANTIC |
227 | | - |
228 | | -// } HARDENING |
229 | | - |
230 | 43 | # define _LIBCPP_TOSTRING2(x) #x |
231 | 44 | # define _LIBCPP_TOSTRING(x) _LIBCPP_TOSTRING2(x) |
232 | 45 |
|
|
0 commit comments