commit bd3c9412e69e4857935308cca9c905ebc24e2f9f
parent bc2eb7a2259306c3f15a8eba052e104c1dd2da1e
Author: Nika Layzell <nika@thelayzells.com>
Date: Wed, 1 Oct 2025 14:34:59 +0000
Bug 1989114 - Add a build flag to enable stl hardening, r=firefox-build-system-reviewers,glandium,sergesanspaille
Unlike the previous approach, this now includes MSVC STL using the new
_MSVC_STL_HARDENING define, and supports being explicitly enabled even
in release builds.
This patch also fixes some apparent bugs in the implementation of
debug-mode STL hardening with libc++, where the version check was
backwards, and the define for old versions was incorrect.
This does not turn on hardening by-default for release builds, as that
could impact performance and needs additional performance testing to
ensure it will not cause issues.
Differential Revision: https://phabricator.services.mozilla.com/D265161
Diffstat:
2 files changed, 77 insertions(+), 37 deletions(-)
diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolchain.configure
@@ -2163,41 +2163,35 @@ include("arm.configure", when=depends(target.cpu)(lambda cpu: cpu == "arm"))
# Libstdc++ feature detection
# ==============================================================
-with only_when("--enable-debug"):
- using_libstdcxx = try_compile(
- language="C++",
- includes=["new"],
- body="#ifndef __GLIBCXX__\n#error 1\n#endif",
- when=depends(c_compiler)(lambda c: c.type != "clang-cl"),
- )
+using_msvc_stl = depends(cxx_compiler)(lambda c: c.type == "clang-cl")
- libstdcxx_assertions = depends(when=using_libstdcxx)("_GLIBCXX_ASSERTIONS")
+using_msvc_stl_202503_or_newer = try_compile(
+ language="C++",
+ includes=["new"],
+ body="#if !defined(_MSVC_STL_UPDATE) || _MSVC_STL_UPDATE < 202503L\n#error 1\n#endif",
+ when=using_msvc_stl,
+)
- using_libcxx = try_compile(
- language="C++",
- includes=["new"],
- body="#ifndef _LIBCPP_VERSION\n#error 1\n#endif",
- when=~using_libstdcxx,
- )
+using_libstdcxx = try_compile(
+ language="C++",
+ includes=["new"],
+ body="#ifndef __GLIBCXX__\n#error 1\n#endif",
+ when=~using_msvc_stl,
+)
- @depends(
- try_compile(language="C++", body="#if _LIBCPP_STD_VER >= 18\n#error 1\n#endif"),
- when=using_libcxx,
- )
- def libcxx_assertions(modern_libcxx):
- if modern_libcxx:
- return "_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG"
- else:
- return "_LIBCPP_HARDENING_MODE_DEBUG"
+using_libcxx = try_compile(
+ language="C++",
+ includes=["new"],
+ body="#ifndef _LIBCPP_VERSION\n#error 1\n#endif",
+ when=~using_libstdcxx,
+)
- @depends(
- libstdcxx_assertions,
- libcxx_assertions,
- when=libstdcxx_assertions | libcxx_assertions,
- )
- @checking("which standard c++ library assertions to use")
- def stdlibcxx_assertions(libstdcxx, libcxx):
- return libstdcxx or libcxx
+using_libcxx_19_or_newer = try_compile(
+ language="C++",
+ includes=["new"],
+ body="#if _LIBCPP_VERSION < 190000\n#error 1\n#endif",
+ when=using_libcxx,
+)
@depends(
@@ -2864,10 +2858,9 @@ option(
"--enable-optimize",
c_compiler,
target,
- stdlibcxx_assertions,
)
def security_hardening_cflags(
- hardening_flag, asan, debug, optimize, c_compiler, target, cxx_assert
+ hardening_flag, asan, debug, optimize, c_compiler, target
):
compiler_is_gccish = c_compiler.type in ("gcc", "clang")
mingw_clang = c_compiler.type == "clang" and target.os == "WINNT"
@@ -2890,10 +2883,6 @@ def security_hardening_cflags(
flags.append("-U_FORTIFY_SOURCE")
flags.append("-D_FORTIFY_SOURCE=2")
- # Lib c++ debug mode
- if cxx_assert:
- flags.append(f"-D{cxx_assert}")
-
# fstack-protector ------------------------------------
# Enable only if hardening is not disabled and ASAN is
# not on as ASAN will catch the crashes for us
@@ -2982,6 +2971,52 @@ set_config(
)
+option(
+ "--enable-stl-hardening",
+ default=moz_debug,
+ help="{Enable|Disable} C++ STL hardening",
+)
+
+
+@depends(
+ "--enable-stl-hardening",
+ moz_debug,
+ using_msvc_stl_202503_or_newer,
+ using_libstdcxx,
+ using_libcxx,
+ using_libcxx_19_or_newer,
+)
+def stl_hardening_flags(
+ enabled,
+ debug,
+ using_msvc_stl_202503_or_newer,
+ using_libstdcxx,
+ using_libcxx,
+ using_libcxx_19_or_newer,
+):
+ if not enabled:
+ return
+
+ if using_msvc_stl_202503_or_newer:
+ return ["-D_MSVC_STL_HARDENING=1"]
+ if using_libstdcxx:
+ return ["-D_GLIBCXX_ASSERTIONS=1"]
+ if using_libcxx:
+ if using_libcxx_19_or_newer:
+ if debug:
+ return ["-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG"]
+ else:
+ return ["-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE"]
+ else:
+ return ["-D_LIBCPP_ENABLE_ASSERTIONS=1"]
+
+ if enabled.origin != "default":
+ die("C++ STL does not support hardening")
+
+
+set_config("MOZ_STL_HARDENING_FLAGS", stl_hardening_flags)
+
+
# Intel Control-flow Enforcement Technology
# ==============================================================
# We keep this separate from the hardening flags above, because we want to be
diff --git a/python/mozbuild/mozbuild/frontend/context.py b/python/mozbuild/mozbuild/frontend/context.py
@@ -563,6 +563,11 @@ class CompileFlags(TargetCompileFlags):
self.flag_variables = (
("STL", context.config.substs.get("STL_FLAGS"), ("CXXFLAGS",)),
(
+ "STL_HARDENING",
+ context.config.substs.get("STL_HARDENING_FLAGS"),
+ ("CXXFLAGS",),
+ ),
+ (
"VISIBILITY",
context.config.substs.get("VISIBILITY_FLAGS"),
("CXXFLAGS", "CFLAGS"),