diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt --- a/libcxx/CMakeLists.txt +++ b/libcxx/CMakeLists.txt @@ -67,6 +67,18 @@ By default, this is turned off. Turning it on results in a different ABI (additional symbols but also potentially different layouts of types), and one should not mix code built against a dylib that has debug mode and code built against a regular dylib." OFF) +option(LIBCXX_ENABLE_HARDENED_MODE + "Enable the hardened mode inside the compiled library and make it the default + when compiling user code. Note that users can override this setting in their + own code. Setting this to "ON" implicitly enables assertions, unless + `LIBCXX_ENABLE_ASSERTIONS` has been explicitly set to "OFF". This does not + affect the ABI." OFF)" + option(LIBCXX_ENABLE_HARDENED_DEBUG_MODE + "Enable the debug mode inside the compiled library and make it the default + when compiling user code. Note that users can override this setting in their + own code. Setting this to "ON" implicitly enables assertions, unless + `LIBCXX_ENABLE_ASSERTIONS` has been explicitly set to "OFF". This does not + affect the ABI." OFF)" option(LIBCXX_ENABLE_RANDOM_DEVICE "Whether to include support for std::random_device in the library. Disabling this can be useful when building the library for platforms that don't have @@ -797,6 +809,16 @@ else() config_define(0 _LIBCPP_ENABLE_ASSERTIONS_DEFAULT) endif() +if (LIBCXX_ENABLE_HARDENED_MODE) + config_define(1 _LIBCPP_ENABLE_HARDENED_MODE_DEFAULT) +else() + config_define(0 _LIBCPP_ENABLE_HARDENED_MODE_DEFAULT) +endif() +if (LIBCXX_ENABLE_HARDENED_DEBUG_MODE) + config_define(1 _LIBCPP_ENABLE_HARDENED_DEBUG_MODE_DEFAULT) +else() + config_define(0 _LIBCPP_ENABLE_HARDENED_DEBUG_MODE_DEFAULT) +endif() if (LIBCXX_PSTL_CPU_BACKEND STREQUAL "serial") config_define(1 _LIBCPP_PSTL_CPU_BACKEND_SERIAL) diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -191,6 +191,71 @@ # define _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION # endif +// HARDENING { + +// Enables the hardened mode which consists of all checks intended to be used in production. Hardened mode prioritizes +// security-critical checks that can be done with relatively little overhead in constant time. Mutually exclusive with +// `_LIBCPP_ENABLE_HARDENED_DEBUG_MODE`. +// +//#define _LIBCPP_ENABLE_HARDENED_MODE 1 + +// Enables the debug mode which contains all the checks from the hardened mode and additionally more expensive checks +// that may affect the complexity of algorithms. The debug mode is intended to be used for testing, not in production. +// Mutually exclusive with `_LIBCPP_ENABLE_HARDENED_MODE`. +// +//#define _LIBCPP_ENABLE_HARDENED_DEBUG_MODE 1 + +// Available checks: + +// TODO(hardening): add documentation for different checks here. + +#ifndef _LIBCPP_ENABLE_HARDENED_MODE +# define _LIBCPP_ENABLE_HARDENED_MODE _LIBCPP_ENABLE_HARDENED_MODE_DEFAULT +#endif +#if _LIBCPP_ENABLE_HARDENED_MODE != 0 && _LIBCPP_ENABLE_HARDENED_MODE != 1 +# error "_LIBCPP_ENABLE_HARDENED_MODE must be set to 0 or 1." +#endif + +#ifndef _LIBCPP_ENABLE_HARDENED_DEBUG_MODE +# define _LIBCPP_ENABLE_HARDENED_DEBUG_MODE _LIBCPP_ENABLE_HARDENED_DEBUG_MODE_DEFAULT +#endif +#if _LIBCPP_ENABLE_HARDENED_DEBUG_MODE != 0 && _LIBCPP_ENABLE_HARDENED_DEBUG_MODE != 1 +# error "_LIBCPP_ENABLE_HARDENED_DEBUG_MODE must be set to 0 or 1." +#endif + +#if _LIBCPP_ENABLE_HARDENED_MODE && _LIBCPP_ENABLE_HARDENED_DEBUG_MODE +# error "Only one of _LIBCPP_ENABLE_HARDENED_MODE and _LIBCPP_ENABLE_HARDENED_DEBUG_MODE can be enabled." +#endif + +// Hardened mode checks. +#if _LIBCPP_ENABLE_HARDENED_MODE + +// Automatically enable assertions in hardened mode (unless the user explicitly turned them off). +# ifndef _LIBCPP_ENABLE_ASSERTIONS +# define _LIBCPP_ENABLE_ASSERTIONS 1 +# endif + +// TODO(hardening): more checks to be added here... + +// Debug mode checks. +#elif _LIBCPP_ENABLE_HARDENED_DEBUG_MODE + +// Automatically enable assertions in debug mode (unless the user explicitly turned them off). +# ifndef _LIBCPP_ENABLE_ASSERTIONS +# define _LIBCPP_ENABLE_ASSERTIONS 1 +# endif + +// TODO(hardening): more checks to be added here... + +// Disable all checks if neither the hardened mode nor the debug mode is enabled. +#else + +// TODO: more checks to be added here... + +#endif // _LIBCPP_ENABLE_HARDENED_MODE + +// } HARDENING + # define _LIBCPP_TOSTRING2(x) #x # define _LIBCPP_TOSTRING(x) _LIBCPP_TOSTRING2(x) diff --git a/libcxx/include/__config_site.in b/libcxx/include/__config_site.in --- a/libcxx/include/__config_site.in +++ b/libcxx/include/__config_site.in @@ -35,6 +35,10 @@ #cmakedefine _LIBCPP_PSTL_CPU_BACKEND_SERIAL #cmakedefine _LIBCPP_PSTL_CPU_BACKEND_THREAD +// Hardening. +#cmakedefine01 _LIBCPP_ENABLE_HARDENED_MODE_DEFAULT +#cmakedefine01 _LIBCPP_ENABLE_HARDENED_DEBUG_MODE_DEFAULT + // __USE_MINGW_ANSI_STDIO gets redefined on MinGW #ifdef __clang__ # pragma clang diagnostic push diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py --- a/libcxx/utils/libcxx/test/params.py +++ b/libcxx/utils/libcxx/test/params.py @@ -294,6 +294,30 @@ AddFeature("libcpp-has-assertions"), ], ), + Parameter( + name="enable_hardened_mode", + choices=[True, False], + type=bool, + default=False, + help="Whether to enable the hardened mode when compiling the test suite. This is only meaningful when " + "running the tests against libc++.", + actions=lambda enabled: [] if not enabled else [ + AddCompileFlag("-D_LIBCPP_ENABLE_HARDENED_MODE=1"), + AddFeature("libcpp-has-hardened-mode"), + ], + ), + Parameter( + name="enable_hardened_debug_mode", + choices=[True, False], + type=bool, + default=False, + help="Whether to enable the debug mode when compiling the test suite. This is only meaningful when " + "running the tests against libc++.", + actions=lambda enabled: [] if not enabled else [ + AddCompileFlag("-D_LIBCPP_ENABLE_HARDENED_DEBUG_MODE=1"), + AddFeature("libcpp-has-hardened-debug-mode"), + ], + ), Parameter( name="additional_features", type=list,