Skip to content

Commit b99f54e

Browse files
Adopt the OpenSSF Compiler Options Hardening Guide for C and C++
1 parent 49100c8 commit b99f54e

5 files changed

Lines changed: 186 additions & 18 deletions

File tree

CMakeLists.txt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,13 @@ endif (BUILD_SHARED_LIBS)
5252
add_library (${PROJECT_NAME} ${LIB_TYPE} "")
5353

5454
# Define the compile options according to the compiler
55+
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake-harden.cmake)
56+
harden(${PROJECT_NAME} CXX RUNTIME)
5557
target_compile_options(${PROJECT_NAME} PRIVATE
5658
$<$<CXX_COMPILER_ID:MSVC>:/bigobj>
5759
$<$<CXX_COMPILER_ID:MSVC>:/MP>
5860
$<$<CXX_COMPILER_ID:MSVC>:/W4>
5961
$<$<CXX_COMPILER_ID:MSVC>:/utf-8> # Necessary for fmt library which AVRO depends on
60-
$<$<CXX_COMPILER_ID:GNU>:-Wall>
61-
$<$<CXX_COMPILER_ID:GNU>:-Wextra>
62-
$<$<CXX_COMPILER_ID:GNU>:-Wcast-qual>
63-
$<$<CXX_COMPILER_ID:GNU>:-pedantic>
64-
$<$<CXX_COMPILER_ID:CLANG>:-Weverything>
6562
)
6663

6764
if (WIN32)

cmake/cmake-harden.cmake

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
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 on aarch64|arm64 architecture
26+
# add -Wl,-z,nodlopen as a comment since we need dlopen for SWIG
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+
-fno-delete-null-pointer-checks
83+
-fno-strict-overflow
84+
-fno-strict-aliasing
85+
-ftrivial-auto-var-init=zero
86+
-fexceptions
87+
-fhardened
88+
)
89+
90+
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64")
91+
add_hardened_compiler_flags(
92+
-mbranch-protection=standard
93+
)
94+
endif()
95+
96+
# 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
97+
add_hardened_linker_flags(
98+
# dlopen is needed for JAVA and Python swig port.
99+
# -z,nodlopen
100+
-z,noexecstack
101+
-z,relro
102+
-z,now
103+
--as-needed
104+
--no-copy-dt-needed-entries
105+
)
106+
107+
if(runtime)
108+
add_hardened_compiler_flags(
109+
-fstack-clash-protection
110+
-fstack-protector-strong
111+
)
112+
endif()
113+
endmacro()
114+
115+
macro(harden_clang)
116+
harden_posix()
117+
endmacro()
118+
119+
macro(harden_gnu)
120+
harden_posix()
121+
122+
add_hardened_compiler_flags(
123+
-Wtrampolines
124+
)
125+
endmacro()
126+
127+
macro(harden_msvc)
128+
# message(WARNING "Compiler hardening is not yet supported for MSVC")
129+
endmacro()
130+
131+
function(harden target)
132+
set(option_keywords
133+
C
134+
CXX
135+
RUNTIME
136+
)
137+
138+
cmake_parse_arguments(
139+
PARSE_ARGV 1 ARGV "${option_keywords}" "" ""
140+
)
141+
142+
set(runtime ${ARGV_RUNTIME})
143+
144+
if(ARGV_CXX)
145+
set(lang CXX)
146+
else()
147+
set(lang C)
148+
endif()
149+
150+
set(compiler ${CMAKE_${lang}_COMPILER_ID})
151+
152+
if(compiler MATCHES "Clang")
153+
harden_clang()
154+
elseif(compiler MATCHES "GNU")
155+
harden_gnu()
156+
elseif(compiler MATCHES "MSVC")
157+
harden_msvc()
158+
endif()
159+
endfunction()

cs/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ message("SWIG C# files have been generated.")
3636
#Add the swig cpp file to the FesapiCpp
3737
target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/swig/swigGeneratedCsWrapper.cpp)
3838
target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/swig/swigGeneratedCsWrapper.h)
39+
# Disable warnings on SWIG generated file which we do not control
40+
if (WIN32)
41+
set_source_files_properties(${CMAKE_SOURCE_DIR}/swig/swigGeneratedCsWrapper.cpp PROPERTIES COMPILE_OPTIONS "/W0")
42+
else()
43+
set_source_files_properties(${CMAKE_SOURCE_DIR}/swig/swigGeneratedCsWrapper.cpp PROPERTIES COMPILE_OPTIONS "-w")
44+
endif()
3945

4046
# Create the Visual Studio project from a template file
4147
set (CS_LIBRARY_NAME FetpapiCs)

java/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ endif (SWIG_LINKED_TO_RELEASE)
9090

9191
target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/swig/swigGeneratedJavaWrapper.cpp)
9292
target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/swig/swigGeneratedJavaWrapper.h)
93+
# Disable warnings on SWIG generated file which we do not control
94+
if (WIN32)
95+
set_source_files_properties(${CMAKE_SOURCE_DIR}/swig/swigGeneratedJavaWrapper.cpp PROPERTIES COMPILE_OPTIONS "/W0")
96+
else()
97+
set_source_files_properties(${CMAKE_SOURCE_DIR}/swig/swigGeneratedJavaWrapper.cpp PROPERTIES COMPILE_OPTIONS "-w")
98+
endif()
9399

94100
target_include_directories(${PROJECT_NAME} PUBLIC ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2})
95101

src/etp/EtpMessages.h

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ namespace Energistics {
575575
namespace avro {
576576
template<> struct codec_traits<Energistics::Etp::v12::Datatypes::AnyArrayType> {
577577
static void encode(Encoder& e, const Energistics::Etp::v12::Datatypes::AnyArrayType& v) {
578-
e.encodeEnum(static_cast<std::underlying_type<Energistics::Etp::v12::Datatypes::AnyArrayType>::type>(v));
578+
e.encodeEnum(static_cast<std::size_t>(v));
579579
}
580580
static void decode(Decoder& d, Energistics::Etp::v12::Datatypes::AnyArrayType& v) {
581581
v = static_cast<Energistics::Etp::v12::Datatypes::AnyArrayType>(d.decodeEnum());
@@ -616,7 +616,7 @@ namespace Energistics {
616616
namespace avro {
617617
template<> struct codec_traits<Energistics::Etp::v12::Datatypes::AnyLogicalArrayType> {
618618
static void encode(Encoder& e, const Energistics::Etp::v12::Datatypes::AnyLogicalArrayType& v) {
619-
e.encodeEnum(static_cast<std::underlying_type<Energistics::Etp::v12::Datatypes::AnyLogicalArrayType>::type>(v));
619+
e.encodeEnum(static_cast<std::size_t>(v));
620620
}
621621
static void decode(Decoder& d, Energistics::Etp::v12::Datatypes::AnyLogicalArrayType& v) {
622622
v = static_cast<Energistics::Etp::v12::Datatypes::AnyLogicalArrayType>(d.decodeEnum());
@@ -1151,7 +1151,7 @@ namespace Energistics {
11511151
namespace avro {
11521152
template<> struct codec_traits<Energistics::Etp::v12::Datatypes::DataObjectCapabilityKind> {
11531153
static void encode(Encoder& e, const Energistics::Etp::v12::Datatypes::DataObjectCapabilityKind& v) {
1154-
e.encodeEnum(static_cast<std::underlying_type<Energistics::Etp::v12::Datatypes::DataObjectCapabilityKind>::type>(v));
1154+
e.encodeEnum(static_cast<std::size_t>(v));
11551155
}
11561156
static void decode(Decoder& d, Energistics::Etp::v12::Datatypes::DataObjectCapabilityKind& v) {
11571157
v = static_cast<Energistics::Etp::v12::Datatypes::DataObjectCapabilityKind>(d.decodeEnum());
@@ -1587,7 +1587,7 @@ namespace Energistics {
15871587
namespace avro {
15881588
template<> struct codec_traits<Energistics::Etp::v12::Datatypes::EndpointCapabilityKind> {
15891589
static void encode(Encoder& e, const Energistics::Etp::v12::Datatypes::EndpointCapabilityKind& v) {
1590-
e.encodeEnum(static_cast<std::underlying_type<Energistics::Etp::v12::Datatypes::EndpointCapabilityKind>::type>(v));
1590+
e.encodeEnum(static_cast<std::size_t>(v));
15911591
}
15921592
static void decode(Decoder& d, Energistics::Etp::v12::Datatypes::EndpointCapabilityKind& v) {
15931593
v = static_cast<Energistics::Etp::v12::Datatypes::EndpointCapabilityKind>(d.decodeEnum());
@@ -1696,7 +1696,7 @@ namespace Energistics {
16961696
namespace avro {
16971697
template<> struct codec_traits<Energistics::Etp::v12::Datatypes::ProtocolCapabilityKind> {
16981698
static void encode(Encoder& e, const Energistics::Etp::v12::Datatypes::ProtocolCapabilityKind& v) {
1699-
e.encodeEnum(static_cast<std::underlying_type<Energistics::Etp::v12::Datatypes::ProtocolCapabilityKind>::type>(v));
1699+
e.encodeEnum(static_cast<std::size_t>(v));
17001700
}
17011701
static void decode(Decoder& d, Energistics::Etp::v12::Datatypes::ProtocolCapabilityKind& v) {
17021702
v = static_cast<Energistics::Etp::v12::Datatypes::ProtocolCapabilityKind>(d.decodeEnum());
@@ -2382,7 +2382,7 @@ namespace Energistics {
23822382
namespace avro {
23832383
template<> struct codec_traits<Energistics::Etp::v12::Datatypes::ChannelData::ChannelDataKind> {
23842384
static void encode(Encoder& e, const Energistics::Etp::v12::Datatypes::ChannelData::ChannelDataKind& v) {
2385-
e.encodeEnum(static_cast<std::underlying_type<Energistics::Etp::v12::Datatypes::ChannelData::ChannelDataKind>::type>(v));
2385+
e.encodeEnum(static_cast<std::size_t>(v));
23862386
}
23872387
static void decode(Decoder& d, Energistics::Etp::v12::Datatypes::ChannelData::ChannelDataKind& v) {
23882388
v = static_cast<Energistics::Etp::v12::Datatypes::ChannelData::ChannelDataKind>(d.decodeEnum());
@@ -2451,7 +2451,7 @@ namespace Energistics {
24512451
namespace avro {
24522452
template<> struct codec_traits<Energistics::Etp::v12::Datatypes::ChannelData::ChannelIndexKind> {
24532453
static void encode(Encoder& e, const Energistics::Etp::v12::Datatypes::ChannelData::ChannelIndexKind& v) {
2454-
e.encodeEnum(static_cast<std::underlying_type<Energistics::Etp::v12::Datatypes::ChannelData::ChannelIndexKind>::type>(v));
2454+
e.encodeEnum(static_cast<std::size_t>(v));
24552455
}
24562456
static void decode(Decoder& d, Energistics::Etp::v12::Datatypes::ChannelData::ChannelIndexKind& v) {
24572457
v = static_cast<Energistics::Etp::v12::Datatypes::ChannelData::ChannelIndexKind>(d.decodeEnum());
@@ -2502,7 +2502,7 @@ namespace Energistics {
25022502
namespace avro {
25032503
template<> struct codec_traits<Energistics::Etp::v12::Datatypes::ChannelData::IndexDirection> {
25042504
static void encode(Encoder& e, const Energistics::Etp::v12::Datatypes::ChannelData::IndexDirection& v) {
2505-
e.encodeEnum(static_cast<std::underlying_type<Energistics::Etp::v12::Datatypes::ChannelData::IndexDirection>::type>(v));
2505+
e.encodeEnum(static_cast<std::size_t>(v));
25062506
}
25072507
static void decode(Decoder& d, Energistics::Etp::v12::Datatypes::ChannelData::IndexDirection& v) {
25082508
v = static_cast<Energistics::Etp::v12::Datatypes::ChannelData::IndexDirection>(d.decodeEnum());
@@ -2527,7 +2527,7 @@ namespace Energistics {
25272527
namespace avro {
25282528
template<> struct codec_traits<Energistics::Etp::v12::Datatypes::ChannelData::PassDirection> {
25292529
static void encode(Encoder& e, const Energistics::Etp::v12::Datatypes::ChannelData::PassDirection& v) {
2530-
e.encodeEnum(static_cast<std::underlying_type<Energistics::Etp::v12::Datatypes::ChannelData::PassDirection>::type>(v));
2530+
e.encodeEnum(static_cast<std::size_t>(v));
25312531
}
25322532
static void decode(Decoder& d, Energistics::Etp::v12::Datatypes::ChannelData::PassDirection& v) {
25332533
v = static_cast<Energistics::Etp::v12::Datatypes::ChannelData::PassDirection>(d.decodeEnum());
@@ -3279,7 +3279,7 @@ namespace Energistics {
32793279
namespace avro {
32803280
template<> struct codec_traits<Energistics::Etp::v12::Datatypes::Object::ActiveStatusKind> {
32813281
static void encode(Encoder& e, const Energistics::Etp::v12::Datatypes::Object::ActiveStatusKind& v) {
3282-
e.encodeEnum(static_cast<std::underlying_type<Energistics::Etp::v12::Datatypes::Object::ActiveStatusKind>::type>(v));
3282+
e.encodeEnum(static_cast<std::size_t>(v));
32833283
}
32843284
static void decode(Decoder& d, Energistics::Etp::v12::Datatypes::Object::ActiveStatusKind& v) {
32853285
v = static_cast<Energistics::Etp::v12::Datatypes::Object::ActiveStatusKind>(d.decodeEnum());
@@ -3359,7 +3359,7 @@ namespace Energistics {
33593359
namespace avro {
33603360
template<> struct codec_traits<Energistics::Etp::v12::Datatypes::Object::ContextScopeKind> {
33613361
static void encode(Encoder& e, const Energistics::Etp::v12::Datatypes::Object::ContextScopeKind& v) {
3362-
e.encodeEnum(static_cast<std::underlying_type<Energistics::Etp::v12::Datatypes::Object::ContextScopeKind>::type>(v));
3362+
e.encodeEnum(static_cast<std::size_t>(v));
33633363
}
33643364
static void decode(Decoder& d, Energistics::Etp::v12::Datatypes::Object::ContextScopeKind& v) {
33653365
v = static_cast<Energistics::Etp::v12::Datatypes::Object::ContextScopeKind>(d.decodeEnum());
@@ -4129,7 +4129,7 @@ namespace Energistics {
41294129
namespace avro {
41304130
template<> struct codec_traits<Energistics::Etp::v12::Datatypes::Object::ObjectChangeKind> {
41314131
static void encode(Encoder& e, const Energistics::Etp::v12::Datatypes::Object::ObjectChangeKind& v) {
4132-
e.encodeEnum(static_cast<std::underlying_type<Energistics::Etp::v12::Datatypes::Object::ObjectChangeKind>::type>(v));
4132+
e.encodeEnum(static_cast<std::size_t>(v));
41334133
}
41344134
static void decode(Decoder& d, Energistics::Etp::v12::Datatypes::Object::ObjectChangeKind& v) {
41354135
v = static_cast<Energistics::Etp::v12::Datatypes::Object::ObjectChangeKind>(d.decodeEnum());
@@ -4270,7 +4270,7 @@ namespace Energistics {
42704270
namespace avro {
42714271
template<> struct codec_traits<Energistics::Etp::v12::Datatypes::Object::RelationshipKind> {
42724272
static void encode(Encoder& e, const Energistics::Etp::v12::Datatypes::Object::RelationshipKind& v) {
4273-
e.encodeEnum(static_cast<std::underlying_type<Energistics::Etp::v12::Datatypes::Object::RelationshipKind>::type>(v));
4273+
e.encodeEnum(static_cast<std::size_t>(v));
42744274
}
42754275
static void decode(Decoder& d, Energistics::Etp::v12::Datatypes::Object::RelationshipKind& v) {
42764276
v = static_cast<Energistics::Etp::v12::Datatypes::Object::RelationshipKind>(d.decodeEnum());

0 commit comments

Comments
 (0)