| .. _hardening: | 
 |  | 
 | =============== | 
 | Hardening Modes | 
 | =============== | 
 |  | 
 | .. contents:: | 
 |    :local: | 
 |  | 
 | .. _using-hardening-modes: | 
 |  | 
 | Using hardening modes | 
 | ===================== | 
 |  | 
 | libc++ provides several hardening modes, where each mode enables a set of | 
 | assertions that prevent undefined behavior caused by violating preconditions of | 
 | the standard library. Different hardening modes make different trade-offs | 
 | between the amount of checking and runtime performance. The available hardening | 
 | modes are: | 
 |  | 
 | - **Unchecked mode/none**, which disables all hardening checks. | 
 | - **Fast mode**, which contains a set of security-critical checks that can be | 
 |   done with relatively little overhead in constant time and are intended to be | 
 |   used in production. We recommend most projects adopt this. | 
 | - **Extensive mode**, which contains all the checks from fast mode and some | 
 |   additional checks for undefined behavior that incur relatively little overhead | 
 |   but aren't security-critical. Production builds requiring a broader set of | 
 |   checks than fast mode should consider enabling extensive mode. The additional | 
 |   rigour impacts performance more than fast mode: we recommend benchmarking to | 
 |   determine if that is acceptable for your program. | 
 | - **Debug mode**, which enables all the available checks in the library, | 
 |   including heuristic checks that might have significant performance overhead as | 
 |   well as internal library assertions. This mode should be used in | 
 |   non-production environments (such as test suites, CI, or local development). | 
 |   We do not commit to a particular level of performance in this mode. | 
 |   In particular, this mode is *not* intended to be used in production. | 
 |  | 
 | .. note:: | 
 |  | 
 |    Enabling hardening has no impact on the ABI. | 
 |  | 
 | Notes for users | 
 | --------------- | 
 |  | 
 | As a libc++ user, consult with your vendor to determine the level of hardening | 
 | enabled by default. | 
 |  | 
 | Users wishing for a different hardening level to their vendor default are able | 
 | to control the level by passing **one** of the following options to the compiler: | 
 |  | 
 | - ``-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE`` | 
 | - ``-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST`` | 
 | - ``-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE`` | 
 | - ``-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG`` | 
 |  | 
 | .. warning:: | 
 |  | 
 |    The exact numeric values of these macros are unspecified and users should not | 
 |    rely on them (e.g. expect the values to be sorted in any way). | 
 |  | 
 | .. warning:: | 
 |  | 
 |    If you would prefer to override the hardening level on a per-translation-unit | 
 |    basis, you must do so **before** including any headers to avoid `ODR issues`_. | 
 |  | 
 | .. _`ODR issues`: https://en.cppreference.com/w/cpp/language/definition#:~:text=is%20ill%2Dformed.-,One%20Definition%20Rule,-Only%20one%20definition | 
 |  | 
 | .. note:: | 
 |  | 
 |    Since the static and shared library components of libc++ are built by the | 
 |    vendor, setting this macro will have no impact on the hardening mode for the | 
 |    pre-built components. Most libc++ code is header-based, so a user-provided | 
 |    value for ``_LIBCPP_HARDENING_MODE`` will be mostly respected. | 
 |  | 
 | Notes for vendors | 
 | ----------------- | 
 |  | 
 | Vendors can set the default hardening mode by providing | 
 | ``LIBCXX_HARDENING_MODE`` as a configuration option, with the possible values of | 
 | ``none``, ``fast``, ``extensive`` and ``debug``. The default value is ``none`` | 
 | which doesn't enable any hardening checks (this mode is sometimes called the | 
 | ``unchecked`` mode). | 
 |  | 
 | This option controls both the hardening mode that the precompiled library is | 
 | built with and the default hardening mode that users will build with. If set to | 
 | ``none``, the precompiled library will not contain any assertions, and user code | 
 | will default to building without assertions. | 
 |  | 
 | Vendors can also override the way the program is terminated when an assertion | 
 | fails by :ref:`providing a custom header <override-assertion-handler>`. | 
 |  | 
 | Assertion categories | 
 | ==================== | 
 |  | 
 | Inside the library, individual assertions are grouped into different | 
 | *categories*. Each hardening mode enables a different set of assertion | 
 | categories; categories provide an additional layer of abstraction that makes it | 
 | easier to reason about the high-level semantics of a hardening mode. | 
 |  | 
 | .. note:: | 
 |  | 
 |   Users are not intended to interact with these categories directly -- the | 
 |   categories are considered internal to the library and subject to change. | 
 |  | 
 | - ``valid-element-access`` -- checks that any attempts to access a container | 
 |   element, whether through the container object or through an iterator, are | 
 |   valid and do not attempt to go out of bounds or otherwise access | 
 |   a non-existent element. This also includes operations that set up an imminent | 
 |   invalid access (e.g. incrementing an end iterator). For iterator checks to | 
 |   work, bounded iterators must be enabled in the ABI. Types like | 
 |   ``std::optional`` and ``std::function`` are considered containers (with at | 
 |   most one element) for the purposes of this check. | 
 |  | 
 | - ``valid-input-range`` -- checks that ranges (whether expressed as an iterator | 
 |   pair, an iterator and a sentinel, an iterator and a count, or | 
 |   a ``std::range``) given as input to library functions are valid: | 
 |   - the sentinel is reachable from the begin iterator; | 
 |   - TODO(hardening): both iterators refer to the same container. | 
 |  | 
 |   ("input" here refers to "an input given to an algorithm", not to an iterator | 
 |   category) | 
 |  | 
 |   Violating assertions in this category leads to an out-of-bounds access. | 
 |  | 
 | - ``non-null`` -- checks that the pointer being dereferenced is not null. On | 
 |   most modern platforms, the zero address does not refer to an actual location | 
 |   in memory, so a null pointer dereference would not compromise the memory | 
 |   security of a program (however, it is still undefined behavior that can result | 
 |   in strange errors due to compiler optimizations). | 
 |  | 
 | - ``non-overlapping-ranges`` -- for functions that take several ranges as | 
 |   arguments, checks that those ranges do not overlap. | 
 |  | 
 | - ``valid-deallocation`` -- checks that an attempt to deallocate memory is valid | 
 |   (e.g. the given object was allocated by the given allocator). Violating this | 
 |   category typically results in a memory leak. | 
 |  | 
 | - ``valid-external-api-call`` -- checks that a call to an external API doesn't | 
 |   fail in an unexpected manner. This includes triggering documented cases of | 
 |   undefined behavior in an external library (like attempting to unlock an | 
 |   unlocked mutex in pthreads). Any API external to the library falls under this | 
 |   category (from system calls to compiler intrinsics). We generally don't expect | 
 |   these failures to compromise memory safety or otherwise create an immediate | 
 |   security issue. | 
 |  | 
 | - ``compatible-allocator`` -- checks any operations that exchange nodes between | 
 |   containers to make sure the containers have compatible allocators. | 
 |  | 
 | - ``argument-within-domain`` -- checks that the given argument is within the | 
 |   domain of valid arguments for the function. Violating this typically produces | 
 |   an incorrect result (e.g. ``std::clamp`` returns the original value without | 
 |   clamping it due to incorrect functors) or puts an object into an invalid state | 
 |   (e.g. a string view where only a subset of elements is accessible). This | 
 |   category is for assertions violating which doesn't cause any immediate issues | 
 |   in the library -- whatever the consequences are, they will happen in the user | 
 |   code. | 
 |  | 
 | - ``pedantic`` -- checks preconditions that are imposed by the C++ standard, | 
 |   but violating which happens to be benign in libc++. | 
 |  | 
 | - ``semantic-requirement`` -- checks that the given argument satisfies the | 
 |   semantic requirements imposed by the C++ standard. Typically, there is no | 
 |   simple way to completely prove that a semantic requirement is satisfied; | 
 |   thus, this would often be a heuristic check and it might be quite expensive. | 
 |  | 
 | - ``internal`` -- checks that internal invariants of the library hold. These | 
 |   assertions don't depend on user input. | 
 |  | 
 | - ``uncategorized`` -- for assertions that haven't been properly classified yet. | 
 |   This category is an escape hatch used for some existing assertions in the | 
 |   library; all new code should have its assertions properly classified. | 
 |  | 
 | Mapping between the hardening modes and the assertion categories | 
 | ================================================================ | 
 |  | 
 | .. list-table:: | 
 |     :header-rows: 1 | 
 |     :widths: auto | 
 |  | 
 |     * - Category name | 
 |       - ``fast`` | 
 |       - ``extensive`` | 
 |       - ``debug`` | 
 |     * - ``valid-element-access`` | 
 |       - ✅ | 
 |       - ✅ | 
 |       - ✅ | 
 |     * - ``valid-input-range`` | 
 |       - ✅ | 
 |       - ✅ | 
 |       - ✅ | 
 |     * - ``non-null`` | 
 |       - ❌ | 
 |       - ✅ | 
 |       - ✅ | 
 |     * - ``non-overlapping-ranges`` | 
 |       - ❌ | 
 |       - ✅ | 
 |       - ✅ | 
 |     * - ``valid-deallocation`` | 
 |       - ❌ | 
 |       - ✅ | 
 |       - ✅ | 
 |     * - ``valid-external-api-call`` | 
 |       - ❌ | 
 |       - ✅ | 
 |       - ✅ | 
 |     * - ``compatible-allocator`` | 
 |       - ❌ | 
 |       - ✅ | 
 |       - ✅ | 
 |     * - ``argument-within-domain`` | 
 |       - ❌ | 
 |       - ✅ | 
 |       - ✅ | 
 |     * - ``pedantic`` | 
 |       - ❌ | 
 |       - ✅ | 
 |       - ✅ | 
 |     * - ``semantic-requirement`` | 
 |       - ❌ | 
 |       - ❌ | 
 |       - ✅ | 
 |     * - ``internal`` | 
 |       - ❌ | 
 |       - ❌ | 
 |       - ✅ | 
 |     * - ``uncategorized`` | 
 |       - ❌ | 
 |       - ✅ | 
 |       - ✅ | 
 |  | 
 | .. note:: | 
 |  | 
 |   At the moment, each subsequent hardening mode is a strict superset of the | 
 |   previous one (in other words, each subsequent mode only enables additional | 
 |   assertion categories without disabling any), but this won't necessarily be | 
 |   true for any hardening modes that might be added in the future. | 
 |  | 
 | .. note:: | 
 |  | 
 |   The categories enabled by each mode are subject to change. Users should not | 
 |   rely on the precise assertions enabled by a mode at a given point in time. | 
 |   However, the library does guarantee to keep the hardening modes stable and | 
 |   to fulfill the semantics documented here. | 
 |  | 
 | Hardening assertion failure | 
 | =========================== | 
 |  | 
 | In production modes (``fast`` and ``extensive``), a hardening assertion failure | 
 | immediately ``_traps <https://clang.llvm.org/docs/LanguageExtensions.html#builtin-verbose-trap>`` | 
 | the program. This is the safest approach that also minimizes the code size | 
 | penalty as the failure handler maps to a single instruction. The downside is | 
 | that the failure provides no additional details other than the stack trace | 
 | (which might also be affected by optimizations). | 
 |  | 
 | In the ``debug`` mode, an assertion failure terminates the program in an | 
 | unspecified manner and also outputs the associated error message to the error | 
 | output. This is less secure and increases the size of the binary (among other | 
 | things, it has to store the error message strings) but makes the failure easier | 
 | to debug. It also allows testing the error messages in our test suite. | 
 |  | 
 | .. _override-assertion-handler: | 
 |  | 
 | Overriding the assertion failure handler | 
 | ---------------------------------------- | 
 |  | 
 | Vendors can override the default assertion handler mechanism by following these | 
 | steps: | 
 |  | 
 | - create a header file that provides a definition of a macro called | 
 |   ``_LIBCPP_ASSERTION_HANDLER``. The macro will be invoked when a hardening | 
 |   assertion fails, with a single parameter containing a null-terminated string | 
 |   with the error message. | 
 | - when configuring the library, provide the path to custom header (relative to | 
 |   the root of the repository) via the CMake variable | 
 |   ``LIBCXX_ASSERTION_HANDLER_FILE``. | 
 |  | 
 | Note that almost all libc++ headers include the assertion handler header which | 
 | means it should not include anything non-trivial from the standard library to | 
 | avoid creating circular dependencies. | 
 |  | 
 | There is no existing mechanism for users to override the assertion handler | 
 | because the ability to do the override other than at configure-time carries an | 
 | unavoidable code size penalty that would otherwise be imposed on all users, | 
 | whether they require such customization or not. Instead, we let vendors decide | 
 | what's right on their platform for their users -- a vendor who wishes to provide | 
 | this capability is free to do so, e.g. by declaring the assertion handler as an | 
 | overridable function. | 
 |  | 
 | ABI | 
 | === | 
 |  | 
 | Setting a hardening mode does **not** affect the ABI. Each mode uses the subset | 
 | of checks available in the current ABI configuration which is determined by the | 
 | platform. | 
 |  | 
 | It is important to stress that whether a particular check is enabled depends on | 
 | the combination of the selected hardening mode and the hardening-related ABI | 
 | options. Some checks require changing the ABI from the "default" to store | 
 | additional information in the library classes -- e.g. checking whether an | 
 | iterator is valid upon dereference generally requires storing data about bounds | 
 | inside the iterator object. Using ``std::span`` as an example, setting the | 
 | hardening mode to ``fast`` will always enable the ``valid-element-access`` | 
 | checks when accessing elements via a ``std::span`` object, but whether | 
 | dereferencing a ``std::span`` iterator does the equivalent check depends on the | 
 | ABI configuration. | 
 |  | 
 | ABI options | 
 | ----------- | 
 |  | 
 | Vendors can use some ABI options at CMake configuration time (when building libc++ | 
 | itself) to enable additional hardening checks. This is done by passing these | 
 | macros as ``-DLIBCXX_ABI_DEFINES="_LIBCPP_ABI_FOO;_LIBCPP_ABI_BAR;etc"`` at | 
 | CMake configuration time. The available options are: | 
 |  | 
 | - ``_LIBCPP_ABI_BOUNDED_ITERATORS`` -- changes the iterator type of select | 
 |   containers (see below) to a bounded iterator that keeps track of whether it's | 
 |   within the bounds of the original container and asserts valid bounds on every | 
 |   dereference. | 
 |  | 
 |   ABI impact: changes the iterator type of the relevant containers. | 
 |  | 
 |   Supported containers: | 
 |  | 
 |   - ``span``; | 
 |   - ``string_view``. | 
 |  | 
 | - ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING`` -- changes the iterator type of | 
 |   ``basic_string`` to a bounded iterator that keeps track of whether it's within | 
 |   the bounds of the original container and asserts it on every dereference and | 
 |   when performing iterator arithmetics. | 
 |  | 
 |   ABI impact: changes the iterator type of ``basic_string`` and its | 
 |   specializations, such as ``string`` and ``wstring``. | 
 |  | 
 | - ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR`` -- changes the iterator type of | 
 |   ``vector`` to a bounded iterator that keeps track of whether it's within the | 
 |   bounds of the original container and asserts it on every dereference and when | 
 |   performing iterator arithmetics. Note: this doesn't yet affect | 
 |   ``vector<bool>``. | 
 |  | 
 |   ABI impact: changes the iterator type of ``vector`` (except ``vector<bool>``). | 
 |  | 
 | - ``_LIBCPP_ABI_BOUNDED_UNIQUE_PTR`` -- tracks the bounds of the array stored inside | 
 |   a ``std::unique_ptr<T[]>``, allowing it to trap when accessed out-of-bounds. This | 
 |   requires the ``std::unique_ptr`` to be created using an API like ``std::make_unique`` | 
 |   or ``std::make_unique_for_overwrite``, otherwise the bounds information is not available | 
 |   to the library. | 
 |  | 
 |   ABI impact: changes the layout of ``std::unique_ptr<T[]>``, and the representation | 
 |               of a few library types that use ``std::unique_ptr`` internally, such as | 
 |               the unordered containers. | 
 |  | 
 | - ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY`` -- changes the iterator type of ``std::array`` to a | 
 |   bounded iterator that keeps track of whether it's within the bounds of the container and asserts it | 
 |   on every dereference and when performing iterator arithmetic. | 
 |  | 
 |   ABI impact: changes the iterator type of ``std::array``, its size and its layout. | 
 |  | 
 | ABI tags | 
 | -------- | 
 |  | 
 | We use ABI tags to allow translation units built with different hardening modes | 
 | to interact with each other without causing ODR violations. Knowing how | 
 | hardening modes are encoded into the ABI tags might be useful to examine | 
 | a binary and determine whether it was built with hardening enabled. | 
 |  | 
 | .. warning:: | 
 |   We don't commit to the encoding scheme used by the ABI tags being stable | 
 |   between different releases of libc++. The tags themselves are never stable, by | 
 |   design -- new releases increase the version number. The following describes | 
 |   the state of the latest release and is for informational purposes only. | 
 |  | 
 | The first character of an ABI tag encodes the hardening mode: | 
 |  | 
 | - ``f`` -- [f]ast mode; | 
 | - ``s`` -- extensive ("[s]afe") mode; | 
 | - ``d`` -- [d]ebug mode; | 
 | - ``n`` -- [n]one mode. | 
 |  | 
 | Hardened containers status | 
 | ========================== | 
 |  | 
 | .. list-table:: | 
 |     :header-rows: 1 | 
 |     :widths: auto | 
 |  | 
 |     * - Name | 
 |       - Member functions | 
 |       - Iterators (ABI-dependent) | 
 |     * - ``span`` | 
 |       - ✅ | 
 |       - ✅ | 
 |     * - ``string_view`` | 
 |       - ✅ | 
 |       - ✅ | 
 |     * - ``array`` | 
 |       - ✅ | 
 |       - ❌ | 
 |     * - ``vector`` | 
 |       - ✅ | 
 |       - ✅ (see note) | 
 |     * - ``string`` | 
 |       - ✅ | 
 |       - ✅ (see note) | 
 |     * - ``list`` | 
 |       - ✅ | 
 |       - ❌ | 
 |     * - ``forward_list`` | 
 |       - ✅ | 
 |       - ❌ | 
 |     * - ``deque`` | 
 |       - ✅ | 
 |       - ❌ | 
 |     * - ``map`` | 
 |       - ❌ | 
 |       - ❌ | 
 |     * - ``set`` | 
 |       - ❌ | 
 |       - ❌ | 
 |     * - ``multimap`` | 
 |       - ❌ | 
 |       - ❌ | 
 |     * - ``multiset`` | 
 |       - ❌ | 
 |       - ❌ | 
 |     * - ``unordered_map`` | 
 |       - Partial | 
 |       - Partial | 
 |     * - ``unordered_set`` | 
 |       - Partial | 
 |       - Partial | 
 |     * - ``unordered_multimap`` | 
 |       - Partial | 
 |       - Partial | 
 |     * - ``unordered_multiset`` | 
 |       - Partial | 
 |       - Partial | 
 |     * - ``mdspan`` | 
 |       - ✅ | 
 |       - ❌ | 
 |     * - ``optional`` | 
 |       - ✅ | 
 |       - N/A | 
 |     * - ``function`` | 
 |       - ❌ | 
 |       - N/A | 
 |     * - ``variant`` | 
 |       - N/A | 
 |       - N/A | 
 |     * - ``any`` | 
 |       - N/A | 
 |       - N/A | 
 |     * - ``expected`` | 
 |       - ✅ | 
 |       - N/A | 
 |     * - ``valarray`` | 
 |       - Partial | 
 |       - N/A | 
 |     * - ``bitset`` | 
 |       - ✅ | 
 |       - N/A | 
 |  | 
 | Note: for ``vector`` and ``string``, the iterator does not check for | 
 | invalidation (accesses made via an invalidated iterator still lead to undefined | 
 | behavior) | 
 |  | 
 | Note: ``vector<bool>`` iterator is not currently hardened. | 
 |  | 
 | Testing | 
 | ======= | 
 |  | 
 | Please see :ref:`Testing documentation <testing-hardening-assertions>`. | 
 |  | 
 | Further reading | 
 | =============== | 
 |  | 
 | - `Hardening RFC <https://discourse.llvm.org/t/rfc-hardening-in-libc/73925>`_: | 
 |   contains some of the design rationale. |