Skip to content

Commit a5e5eb1

Browse files
var-consttru
authored andcommitted
[libc++][hardening] Remove hardening from release notes, undeprecate safe mode
This patch effectively maintains the status quo, making sure that the safe mode keeps working the same way as before. Hardening will target the next major release, allowing it to go through RFC and for the implementation to stabilize and mature. Differential Revision: https://reviews.llvm.org/D159171
1 parent 1174205 commit a5e5eb1

File tree

127 files changed

+354
-249
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

127 files changed

+354
-249
lines changed

libcxx/CMakeLists.txt

+9-5
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ include(CMakeDependentOption)
4848
include(HandleCompilerRT)
4949

5050
# Basic options ---------------------------------------------------------------
51+
option(LIBCXX_ENABLE_ASSERTIONS
52+
"Enable assertions inside the compiled library, and at the same time make it the
53+
default when compiling user code. Note that assertions can be enabled or disabled
54+
by users in their own code regardless of this option." OFF)
5155
option(LIBCXX_ENABLE_SHARED "Build libc++ as a shared library." ON)
5256
option(LIBCXX_ENABLE_STATIC "Build libc++ as a static library." ON)
5357
option(LIBCXX_ENABLE_FILESYSTEM
@@ -747,6 +751,11 @@ config_define_if_not(LIBCXX_ENABLE_LOCALIZATION _LIBCPP_HAS_NO_LOCALIZATION)
747751
config_define_if_not(LIBCXX_ENABLE_UNICODE _LIBCPP_HAS_NO_UNICODE)
748752
config_define_if_not(LIBCXX_ENABLE_WIDE_CHARACTERS _LIBCPP_HAS_NO_WIDE_CHARACTERS)
749753
config_define_if_not(LIBCXX_ENABLE_VENDOR_AVAILABILITY_ANNOTATIONS _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS)
754+
if (LIBCXX_ENABLE_ASSERTIONS)
755+
config_define(1 _LIBCPP_ENABLE_ASSERTIONS_DEFAULT)
756+
else()
757+
config_define(0 _LIBCPP_ENABLE_ASSERTIONS_DEFAULT)
758+
endif()
750759
if (LIBCXX_HARDENING_MODE STREQUAL "hardened")
751760
config_define(1 _LIBCPP_ENABLE_HARDENED_MODE_DEFAULT)
752761
config_define(0 _LIBCPP_ENABLE_DEBUG_MODE_DEFAULT)
@@ -757,11 +766,6 @@ elseif (LIBCXX_HARDENING_MODE STREQUAL "unchecked")
757766
config_define(0 _LIBCPP_ENABLE_HARDENED_MODE_DEFAULT)
758767
config_define(0 _LIBCPP_ENABLE_DEBUG_MODE_DEFAULT)
759768
endif()
760-
# TODO(LLVM 18): Remove this after branching for LLVM 17, this is a simple
761-
# courtesy for vendors to be notified about this change.
762-
if (LIBCXX_ENABLE_ASSERTIONS)
763-
message(FATAL_ERROR "LIBCXX_ENABLE_ASSERTIONS has been replaced by LIBCXX_HARDENING_MODE=hardened")
764-
endif()
765769

766770
if (LIBCXX_PSTL_CPU_BACKEND STREQUAL "serial")
767771
config_define(1 _LIBCPP_PSTL_CPU_BACKEND_SERIAL)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
set(LIBCXX_ENABLE_ASSERTIONS ON CACHE BOOL "")
2+
set(LIBCXXABI_ENABLE_ASSERTIONS ON CACHE BOOL "")
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
set(LIBCXX_HARDENING_MODE "debug" CACHE STRING "")
2+
set(LIBCXXABI_ENABLE_ASSERTIONS OFF CACHE BOOL "")
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
set(LIBCXX_HARDENING_MODE "hardened" CACHE STRING "")
2+
set(LIBCXXABI_ENABLE_ASSERTIONS OFF CACHE BOOL "")

libcxx/docs/BuildingLibcxx.rst

+9
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,15 @@ libc++ specific options
211211

212212
Toggle the installation of the libc++ headers.
213213

214+
.. option:: LIBCXX_ENABLE_ASSERTIONS:BOOL
215+
216+
**Default**: ``OFF``
217+
218+
Build libc++ with assertions enabled in the compiled library, and enable assertions
219+
by default when building user code as well. Assertions can be turned off by users
220+
by defining ``_LIBCPP_ENABLE_ASSERTIONS=0``. For details, see
221+
:ref:`the documentation <assertions-mode>`.
222+
214223
.. option:: LIBCXX_ENABLE_SHARED:BOOL
215224

216225
**Default**: ``ON``

libcxx/docs/Hardening.rst

-54
This file was deleted.

libcxx/docs/ReleaseNotes/17.rst

+2-24
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,6 @@ Improvements and New Features
8787
``std::ranges::find`` are now forwarding to ``std::memcmp`` for trivially
8888
equality comparable types, which can lead up to 40x performance improvements.
8989

90-
- ``std::string_view`` now provides iterators that check for out-of-bounds accesses when the safe
91-
libc++ mode is enabled.
92-
9390
- The performance of ``dynamic_cast`` on its hot paths is greatly improved and is as efficient as the
9491
``libsupc++`` implementation. Note that the performance improvements are shipped in ``libcxxabi``.
9592

@@ -105,19 +102,6 @@ Improvements and New Features
105102
Anything that does not rely on having an actual filesystem available will now work, such as ``std::filesystem::path``,
106103
``std::filesystem::perms`` and similar classes.
107104

108-
- The library now provides a hardened mode under which common cases of library undefined behavior will be turned into
109-
a reliable program termination. Vendors can configure whether the hardened mode is enabled by default with the
110-
``LIBCXX_HARDENING_MODE`` variable at CMake configuration time. Users can control whether the hardened mode is
111-
enabled on a per translation unit basis using the ``-D_LIBCPP_ENABLE_HARDENED_MODE=1`` macro. See
112-
``libcxx/docs/Hardening.rst`` for more details.
113-
114-
- The library now provides a debug mode which is a superset of the hardened mode, additionally enabling more expensive
115-
checks that are not suitable to be used in production. This replaces the legacy debug mode that was removed in this
116-
release. Unlike the legacy debug mode, this doesn't affect the ABI and doesn't require locking. Vendors can configure
117-
whether the debug mode is enabled by default with the ``LIBCXX_HARDENING_MODE`` variable at CMake configuration time.
118-
Users can control whether the debug mode is enabled on a per translation unit basis using the
119-
``-D_LIBCPP_ENABLE_DEBUG_MODE=1`` macro. See ``libcxx/docs/Hardening.rst`` for more details.
120-
121105
- ASan container annotations have been extended to cover all allocators in ``std::vector``.
122106

123107
- ASan annotations have been added to the ``std::deque`` container, to detect container overflows.
@@ -128,14 +112,8 @@ Improvements and New Features
128112
Deprecations and Removals
129113
-------------------------
130114

131-
- The "safe" mode is replaced by the hardened mode in this release. The ``LIBCXX_ENABLE_ASSERTIONS`` CMake variable is
132-
deprecated and setting it will trigger an error; use ``LIBCXX_HARDENING_MODE`` instead. Similarly, the
133-
``_LIBCPP_ENABLE_ASSERTIONS`` macro is deprecated and setting it to ``1`` now enables the hardened mode. See
134-
``libcxx/docs/Hardening.rst`` for more details.
135-
136-
- The legacy debug mode has been removed in this release. Setting the macro ``_LIBCPP_ENABLE_DEBUG_MODE`` to ``1`` now
137-
enables the new debug mode which is part of hardening (see the "Improvements and New Features" section above). The
138-
``LIBCXX_ENABLE_DEBUG_MODE`` CMake variable has been removed. For additional context, refer to the `Discourse post
115+
- The legacy debug mode has been removed in this release. The ``LIBCXX_ENABLE_DEBUG_MODE`` CMake variable has been
116+
removed. For additional context, refer to the `Discourse post
139117
<https://discourse.llvm.org/t/rfc-removing-the-legacy-debug-mode-from-libc/71026>`_.
140118

141119
- The ``<experimental/coroutine>`` header has been removed in this release. The ``<coroutine>`` header

libcxx/docs/UsingLibcxx.rst

+41-14
Original file line numberDiff line numberDiff line change
@@ -138,17 +138,50 @@ IWYU, you should run the tool like so:
138138
If you would prefer to not use that flag, then you can replace ``/path/to/include-what-you-use/share/libcxx.imp```
139139
file with the libc++-provided ``libcxx.imp`` file.
140140

141+
.. _assertions-mode:
142+
143+
Enabling the "safe libc++" mode
144+
===============================
145+
146+
Libc++ contains a number of assertions whose goal is to catch undefined behavior in the
147+
library, usually caused by precondition violations. Those assertions do not aim to be
148+
exhaustive -- instead they aim to provide a good balance between safety and performance.
149+
In particular, these assertions do not change the complexity of algorithms. However, they
150+
might, in some cases, interfere with compiler optimizations.
151+
152+
By default, these assertions are turned off. Vendors can decide to turn them on while building
153+
the compiled library by defining ``LIBCXX_ENABLE_ASSERTIONS=ON`` at CMake configuration time.
154+
When ``LIBCXX_ENABLE_ASSERTIONS`` is used, the compiled library will be built with assertions
155+
enabled, **and** user code will be built with assertions enabled by default. If
156+
``LIBCXX_ENABLE_ASSERTIONS=OFF`` at CMake configure time, the compiled library will not contain
157+
assertions and the default when building user code will be to have assertions disabled.
158+
As a user, you can consult your vendor to know whether assertions are enabled by default.
159+
160+
Furthermore, independently of any vendor-selected default, users can always control whether
161+
assertions are enabled in their code by defining ``_LIBCPP_ENABLE_ASSERTIONS=0|1`` before
162+
including any libc++ header (we recommend passing ``-D_LIBCPP_ENABLE_ASSERTIONS=X`` to the
163+
compiler). Note that if the compiled library was built by the vendor without assertions,
164+
functions compiled inside the static or shared library won't have assertions enabled even
165+
if the user defines ``_LIBCPP_ENABLE_ASSERTIONS=1`` (the same is true for the inverse case
166+
where the static or shared library was compiled **with** assertions but the user tries to
167+
disable them). However, most of the code in libc++ is in the headers, so the user-selected
168+
value for ``_LIBCPP_ENABLE_ASSERTIONS`` (if any) will usually be respected.
169+
170+
When an assertion fails, the program is aborted through a special verbose termination function. This
171+
behavior is customizable; see the :ref:`Overriding the default termination handler
172+
<termination-handler>` section for more information.
173+
141174
.. _termination-handler:
142175

143176
Overriding the default termination handler
144177
==========================================
145178

146-
When the library wants to terminate due to an unforeseen condition (such as a hardening assertion
147-
failure), the program is aborted through a special verbose termination function. The library provides
148-
a default function that prints an error message and calls ``std::abort()``. Note that this function is
149-
provided by the static or shared library, so it is only available when deploying to a platform where
150-
the compiled library is sufficiently recent. On older platforms, the program will terminate in an
151-
unspecified unsuccessful manner, but the quality of diagnostics won't be great.
179+
When the library wants to terminate due to an unforeseen condition (such as an assertion failure),
180+
the program is aborted through a special verbose termination function. The library provides
181+
a default function that prints an error message and calls ``std::abort()``. Note that this function
182+
is provided by the static or shared library, so it is only available when deploying to a platform
183+
where the compiled library is sufficiently recent. On older platforms, the program will terminate in
184+
an unspecified unsuccessful manner, but the quality of diagnostics won't be great.
152185

153186
However, users can also override that mechanism at two different levels. First, the mechanism can be
154187
overridden at compile time by defining the ``_LIBCPP_VERBOSE_ABORT(format, args...)`` variadic macro.
@@ -191,7 +224,7 @@ and ``operator delete``. For example:
191224
192225
int main() {
193226
std::vector<int> v;
194-
int& x = v[0]; // Your termination function will be called here if hardening is enabled.
227+
int& x = v[0]; // Your termination function will be called here if _LIBCPP_ENABLE_ASSERTIONS=1
195228
}
196229
197230
Also note that the verbose termination function should never return. Since assertions in libc++
@@ -206,20 +239,14 @@ Libc++ Configuration Macros
206239
===========================
207240

208241
Libc++ provides a number of configuration macros which can be used to enable
209-
or disable extended libc++ behavior, including enabling hardening or thread
242+
or disable extended libc++ behavior, including enabling the safe mode or thread
210243
safety annotations.
211244

212245
**_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS**:
213246
This macro is used to enable -Wthread-safety annotations on libc++'s
214247
``std::mutex`` and ``std::lock_guard``. By default, these annotations are
215248
disabled and must be manually enabled by the user.
216249

217-
**_LIBCPP_ENABLE_HARDENED_MODE**:
218-
This macro is used to enable the :ref:`hardened mode <using-hardened-mode>`.
219-
220-
**_LIBCPP_ENABLE_DEBUG_MODE**:
221-
This macro is used to enable the :ref:`debug mode <using-hardened-mode>`.
222-
223250
**_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS**:
224251
This macro is used to disable all visibility annotations inside libc++.
225252
Defining this macro and then building libc++ with hidden visibility gives a

libcxx/docs/index.rst

-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ Getting Started with libc++
4040
TestingLibcxx
4141
Contributing
4242
Modules
43-
Hardening
4443
ReleaseProcedure
4544
Status/Cxx14
4645
Status/Cxx17

libcxx/include/__config

+25-11
Original file line numberDiff line numberDiff line change
@@ -208,19 +208,16 @@
208208

209209
// HARDENING {
210210

211-
// TODO(hardening): remove this in LLVM 18.
212-
// This is for backward compatibility -- make enabling `_LIBCPP_ENABLE_ASSERTIONS` (which predates hardening modes)
213-
// equivalent to setting the hardened mode.
214-
# ifdef _LIBCPP_ENABLE_ASSERTIONS
215-
# warning "_LIBCPP_ENABLE_ASSERTIONS is deprecated, please use _LIBCPP_ENABLE_HARDENED_MODE instead."
216-
# if _LIBCPP_ENABLE_ASSERTIONS != 0 && _LIBCPP_ENABLE_ASSERTIONS != 1
217-
# error "_LIBCPP_ENABLE_ASSERTIONS must be set to 0 or 1"
218-
# endif
219-
# if _LIBCPP_ENABLE_ASSERTIONS
220-
# define _LIBCPP_ENABLE_HARDENED_MODE 1
221-
# endif
211+
# ifndef _LIBCPP_ENABLE_ASSERTIONS
212+
# define _LIBCPP_ENABLE_ASSERTIONS _LIBCPP_ENABLE_ASSERTIONS_DEFAULT
213+
# endif
214+
# if _LIBCPP_ENABLE_ASSERTIONS != 0 && _LIBCPP_ENABLE_ASSERTIONS != 1
215+
# error "_LIBCPP_ENABLE_ASSERTIONS must be set to 0 or 1"
222216
# endif
223217

218+
// NOTE: These modes are experimental and are not stable yet in LLVM 17. Please refrain from using them and use the
219+
// documented libc++ "safe" mode instead.
220+
//
224221
// Enables the hardened mode which consists of all checks intended to be used in production. Hardened mode prioritizes
225222
// security-critical checks that can be done with relatively little overhead in constant time. Mutually exclusive with
226223
// `_LIBCPP_ENABLE_DEBUG_MODE`.
@@ -275,6 +272,11 @@
275272
# error "Only one of _LIBCPP_ENABLE_HARDENED_MODE and _LIBCPP_ENABLE_DEBUG_MODE can be enabled."
276273
# endif
277274

275+
# if _LIBCPP_ENABLE_ASSERTIONS && (_LIBCPP_ENABLE_HARDENED_MODE || _LIBCPP_ENABLE_DEBUG_MODE)
276+
# error \
277+
"_LIBCPP_ENABLE_ASSERTIONS is mutually exclusive with _LIBCPP_ENABLE_HARDENED_MODE and _LIBCPP_ENABLE_DEBUG_MODE."
278+
# endif
279+
278280
// Hardened mode checks.
279281

280282
// clang-format off
@@ -303,6 +305,18 @@
303305
# define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSERT(expression, message)
304306
# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSERT(expression, message)
305307

308+
// Safe mode checks.
309+
310+
# elif _LIBCPP_ENABLE_ASSERTIONS
311+
312+
// All checks enabled.
313+
# define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message) _LIBCPP_ASSERT(expression, message)
314+
# define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message) _LIBCPP_ASSERT(expression, message)
315+
# define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) _LIBCPP_ASSERT(expression, message)
316+
# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) _LIBCPP_ASSERT(expression, message)
317+
# define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSERT(expression, message)
318+
# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSERT(expression, message)
319+
306320
// Disable all checks if hardening is not enabled.
307321

308322
# else

libcxx/include/__config_site.in

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#cmakedefine _LIBCPP_HAS_NO_RANDOM_DEVICE
2828
#cmakedefine _LIBCPP_HAS_NO_LOCALIZATION
2929
#cmakedefine _LIBCPP_HAS_NO_WIDE_CHARACTERS
30+
#cmakedefine01 _LIBCPP_ENABLE_ASSERTIONS_DEFAULT
3031

3132
// PSTL backends
3233
#cmakedefine _LIBCPP_PSTL_CPU_BACKEND_SERIAL

libcxx/test/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ if (NOT LIBCXX_ENABLE_RTTI)
2424
serialize_lit_param(enable_rtti False)
2525
endif()
2626

27+
if (LIBCXX_ENABLE_ASSERTIONS)
28+
serialize_lit_param(enable_assertions True)
29+
endif()
30+
2731
serialize_lit_param(hardening_mode "\"${LIBCXX_HARDENING_MODE}\"")
2832

2933
if (CMAKE_CXX_COMPILER_TARGET)

libcxx/test/libcxx/algorithms/alg.sorting/assert.min.max.pass.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
// REQUIRES: has-unix-headers
1212
// UNSUPPORTED: c++03, c++11, c++14, c++17
13-
// UNSUPPORTED: !libcpp-has-debug-mode
13+
// UNSUPPORTED: !libcpp-has-debug-mode && !libcpp-has-assertions
1414
// XFAIL: availability-verbose_abort-missing
1515

1616
#include <algorithm>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//===----------------------------------------------------------------------===//
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+
// Test that _LIBCPP_ASSERT doesn't do anything when assertions are disabled.
10+
// We need to use -Wno-macro-redefined because the test suite defines
11+
// _LIBCPP_ENABLE_ASSERTIONS=1 under some configurations.
12+
13+
// XFAIL: libcpp-has-hardened-mode, libcpp-has-debug-mode
14+
// ADDITIONAL_COMPILE_FLAGS: -Wno-macro-redefined -D_LIBCPP_ENABLE_ASSERTIONS=0
15+
16+
#include <cassert>
17+
18+
bool executed_condition = false;
19+
bool f() { executed_condition = true; return false; }
20+
21+
int main(int, char**) {
22+
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(f(), "message"); // should not execute anything
23+
assert(!executed_condition); // really make sure we did not execute anything at all
24+
return 0;
25+
}

libcxx/test/libcxx/assertions/modes/debug.pass.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// This test ensures that assertions trigger without the user having to do anything when the debug mode has been enabled
1010
// by default.
1111

12-
// UNSUPPORTED: !libcpp-has-debug-mode
12+
// REQUIRES: libcpp-has-debug-mode
1313
// `check_assertion.h` is only available starting from C++11.
1414
// UNSUPPORTED: c++03
1515
// `check_assertion.h` requires Unix headers.

libcxx/test/libcxx/assertions/modes/debug_mode_disabled_in_tu.pass.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
// This test ensures that we can disable the debug mode on a per-TU basis regardless of how the library was built.
1010

11-
// UNSUPPORTED: libcpp-has-hardened-mode
11+
// REQUIRES: libcpp-has-debug-mode
1212
// ADDITIONAL_COMPILE_FLAGS: -Wno-macro-redefined -D_LIBCPP_ENABLE_DEBUG_MODE=0
1313

1414
#include <cassert>

libcxx/test/libcxx/assertions/modes/debug_mode_enabled_in_tu.pass.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// This test ensures that we can enable the debug mode on a per-TU basis regardless of how the library was built.
1010

1111
// Hardened mode would additionally trigger the error that hardened and debug modes are mutually exclusive.
12-
// UNSUPPORTED: libcpp-has-hardened-mode
12+
// UNSUPPORTED: libcpp-has-hardened-mode, libcpp-has-debug-mode, libcpp-has-assertions
1313
// `check_assertion.h` is only available starting from C++11 and requires Unix headers.
1414
// UNSUPPORTED: c++03, !has-unix-headers
1515
// The ability to set a custom abort message is required to compare the assertion message.

0 commit comments

Comments
 (0)