Skip to content

Commit a9bc2bf

Browse files
Adopt the OpenSSF Compiler Options Hardening Guide for C and C++
1 parent ab7af2b commit a9bc2bf

3 files changed

Lines changed: 158 additions & 6 deletions

File tree

cmake/cmake-harden.cmake

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# Copyright 2025 Holepunch Inc
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
# Downloaded on 2026-03-16 from https://github.com/holepunchto/cmake-harden/blob/main/cmake-harden.cmake
16+
# Changelog
17+
# 2026-03-16
18+
# add -Wextra
19+
# add -Wsign-conversion
20+
# add -Wbidi-chars=any
21+
# add -U_FORTIFY_SOURCE
22+
# add -D_FORTIFY_SOURCE=3
23+
# add -D_GLIBCXX_ASSERTIONS
24+
# add -fcf-protection=full
25+
# add -mbranch-protection=standard
26+
# add -Wl,-z,nodlopen
27+
# add -Wl,--as-needed
28+
# add -Wl,--no-copy-dt-needed-entries
29+
# add fexceptions
30+
# add fhardened
31+
# rename GCC compiler to GNU compiler to apply to gcc and g++
32+
# Check Linker Flag and use LINKER: prefix
33+
34+
cmake_minimum_required(VERSION 3.19)
35+
36+
include_guard()
37+
38+
include(CheckCompilerFlag)
39+
include(CheckLinkerFlag)
40+
41+
# https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html
42+
43+
macro(add_hardened_compiler_flags)
44+
foreach(flag ${ARGV})
45+
check_compiler_flag(${lang} ${flag} supports_${flag})
46+
47+
if(supports_${flag})
48+
target_compile_options(${target} PRIVATE ${flag})
49+
endif()
50+
endforeach()
51+
endmacro()
52+
53+
macro(add_hardened_linker_flags)
54+
foreach(flag ${ARGV})
55+
check_linker_flag(${lang} LINKER:${flag} supports_${flag})
56+
57+
if(supports_${flag})
58+
target_link_options(${target} PRIVATE LINKER:${flag})
59+
endif()
60+
endforeach()
61+
endmacro()
62+
63+
macro(harden_posix)
64+
add_hardened_compiler_flags(
65+
-Wall
66+
-Wextra
67+
-Wformat
68+
-Wformat=2
69+
-Wconversion
70+
-Wsign-conversion
71+
-Wimplicit-fallthrough
72+
-Wbidi-chars=any
73+
-Werror=format-security
74+
-Werror=implicit
75+
-Werror=incompatible-pointer-types
76+
-Werror=int-conversion
77+
-U_FORTIFY_SOURCE
78+
-D_FORTIFY_SOURCE=3
79+
-D_GLIBCXX_ASSERTIONS
80+
-fstrict-flex-arrays=3
81+
-fcf-protection=full
82+
-mbranch-protection=standard
83+
-fno-delete-null-pointer-checks
84+
-fno-strict-overflow
85+
-fno-strict-aliasing
86+
-ftrivial-auto-var-init=zero
87+
-fexceptions
88+
-fhardened
89+
)
90+
91+
# The SHARED and MODULE library targets have by default position independent code enabled : https://cmake.org/cmake/help/latest/variable/CMAKE_POSITION_INDEPENDENT_CODE.html
92+
add_hardened_linker_flags(
93+
# dlopen is needed for JAVA and Python swig port.
94+
# -z,nodlopen
95+
-z,noexecstack
96+
-z,relro
97+
-z,now
98+
--as-needed
99+
--no-copy-dt-needed-entries
100+
)
101+
102+
if(runtime)
103+
add_hardened_compiler_flags(
104+
-fstack-clash-protection
105+
-fstack-protector-strong
106+
)
107+
endif()
108+
endmacro()
109+
110+
macro(harden_clang)
111+
harden_posix()
112+
endmacro()
113+
114+
macro(harden_gnu)
115+
harden_posix()
116+
117+
add_hardened_compiler_flags(
118+
-Wtrampolines
119+
)
120+
endmacro()
121+
122+
macro(harden_msvc)
123+
message(WARNING "Compiler hardening is not yet supported for MSVC")
124+
endmacro()
125+
126+
function(harden target)
127+
set(option_keywords
128+
C
129+
CXX
130+
RUNTIME
131+
)
132+
133+
cmake_parse_arguments(
134+
PARSE_ARGV 1 ARGV "${option_keywords}" "" ""
135+
)
136+
137+
set(runtime ${ARGV_RUNTIME})
138+
139+
if(ARGV_CXX)
140+
set(lang CXX)
141+
else()
142+
set(lang C)
143+
endif()
144+
145+
set(compiler ${CMAKE_${lang}_COMPILER_ID})
146+
147+
if(compiler MATCHES "Clang")
148+
harden_clang()
149+
elseif(compiler MATCHES "GNU")
150+
harden_gnu()
151+
elseif(compiler MATCHES "MSVC")
152+
harden_msvc()
153+
endif()
154+
endfunction()

python/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Included in ../src/CMakeLists.txt if Python build is selected.
22

33
find_package(SWIG 3.0 REQUIRED)
4+
45
find_package(Python3 REQUIRED)
56

67
set (Fesapi_PYTHON_VERSION ${Fesapi_VERSION_MAJOR}.${Fesapi_VERSION_MINOR}.${Fesapi_VERSION_PATCH})

src/CMakeLists.txt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,12 @@ set (EML_PREFIX_2_0 "eml2_0")
4040
set (EML_PREFIX_2_3 "eml2_3")
4141

4242
# Define the compile options according to the compiler
43-
target_compile_options(${CPP_LIBRARY_NAME} PRIVATE
43+
include(${FESAPI_ROOT_DIR}/cmake/cmake-harden.cmake)
44+
harden(${CPP_LIBRARY_NAME} CXX RUNTIME)
45+
target_compile_options(${CPP_LIBRARY_NAME} PRIVATE
4446
$<$<CXX_COMPILER_ID:MSVC>:/bigobj>
4547
$<$<CXX_COMPILER_ID:MSVC>:/MP>
4648
$<$<CXX_COMPILER_ID:MSVC>:/W4>
47-
$<$<CXX_COMPILER_ID:GNU>:-Wall>
48-
$<$<CXX_COMPILER_ID:GNU>:-Wextra>
49-
$<$<CXX_COMPILER_ID:GNU>:-Wcast-qual>
50-
$<$<CXX_COMPILER_ID:GNU>:-pedantic>
51-
$<$<CXX_COMPILER_ID:CLANG>:-Weverything>
5249
)
5350
if (WITH_RESQML2_2)
5451
target_compile_definitions(${CPP_LIBRARY_NAME} PUBLIC "-DWITH_RESQML2_2")

0 commit comments

Comments
 (0)