Skip to content

Commit 33a33ee

Browse files
committed
Modernize sanitizer scripts
The previous sanitizer support was implemented in a very rigid manner, with the compile options available for each sanitizer type been preset, and enabling of each sanitizer through a preset variable. This change makes it so that setting of compile options can be set on a per-sanitizer-type basis and then added to builds via functions. Use via the legacy `USE_SANITIZER` is available, but deprecated. This is also flexible enough to allow overriding of the compile options, via variables either in-script or passed in via the command-line. Results of checks for compile compatability are cached, reducing time on subsequent builds, provided the associated compile options are not updated. Checks for sanitizer availability/compatability are no longer platform dependent. It will check on all platforms.
1 parent 45f72fd commit 33a33ee

File tree

4 files changed

+406
-202
lines changed

4 files changed

+406
-202
lines changed

.gitlab-ci.yml

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ stages:
22
- Analysis
33
- Targeted Code Coverage
44
- All Code Coverage
5-
- Fedora
6-
- openSUSE
5+
- Sanitizers
76

87
variables:
98
CTEST_OUTPUT_ON_FAILURE: "1"
@@ -427,10 +426,10 @@ Windows/All CC Clang Shared:
427426
- ninja -C build ccov-report
428427
- ninja -C build ccov-all-report
429428

430-
# Fedora
429+
# Sanitizers
431430

432-
.fedora_success_template: &fedora_success_template
433-
stage: Fedora
431+
.linux_success_template: &linux_success_template
432+
stage: Sanitizers
434433
image: stabletec/build-core:fedora
435434
parallel:
436435
matrix:
@@ -444,8 +443,8 @@ Windows/All CC Clang Shared:
444443
- ninja -C build
445444
- ninja -C build test
446445

447-
.fedora_failure_template: &fedora_failure_template
448-
stage: Fedora
446+
.linux_failure_template: &linux_failure_template
447+
stage: Sanitizers
449448
image: stabletec/build-core:fedora
450449
parallel:
451450
matrix:
@@ -459,37 +458,79 @@ Windows/All CC Clang Shared:
459458
- ninja -C build
460459
- "! ninja -C build test"
461460

462-
Fedora/Static Analysis:
461+
Linux/Static Analysis:
463462
variables:
464463
CC: clang
465464
CXX: clang++
466465
CMAKE_OPTIONS: -DCLANG_TIDY=ON -DCPPCHECK=ON
467-
<<: *fedora_success_template
466+
<<: *linux_success_template
468467

469-
Fedora/ThreadSanitizer:
468+
Linux/Clang/ThreadSanitizer:
470469
variables:
471470
CC: clang
472471
CXX: clang++
473-
CMAKE_OPTIONS: -DUSE_SANITIZER=Thread
474-
<<: *fedora_failure_template
472+
CMAKE_OPTIONS: -D EXAMPLE_USE_SANITIZER=thread
473+
<<: *linux_failure_template
475474

476-
Fedora/AddressSanitizer:
475+
Linux/Clang/AddressSanitizer:
477476
variables:
478477
CC: clang
479478
CXX: clang++
480-
CMAKE_OPTIONS: -DUSE_SANITIZER=Address
481-
<<: *fedora_failure_template
479+
CMAKE_OPTIONS: -D EXAMPLE_USE_SANITIZER=address
480+
<<: *linux_failure_template
482481

483-
Fedora/LeakSanitizer:
482+
Linux/Clang/LeakSanitizer:
484483
variables:
485484
CC: clang
486485
CXX: clang++
487-
CMAKE_OPTIONS: -DUSE_SANITIZER=Leak
488-
<<: *fedora_failure_template
486+
CMAKE_OPTIONS: -D EXAMPLE_USE_SANITIZER=leak
487+
<<: *linux_failure_template
489488

490-
Fedora/UndefinedSanitizer:
489+
Linux/Clang/MemorySanitizer:
491490
variables:
492491
CC: clang
493492
CXX: clang++
494-
CMAKE_OPTIONS: -DUSE_SANITIZER=Undefined
495-
<<: *fedora_success_template
493+
CMAKE_OPTIONS: -D EXAMPLE_USE_SANITIZER=memory
494+
<<: *linux_failure_template
495+
496+
Linux/Clang/UndefinedSanitizer:
497+
variables:
498+
CC: clang
499+
CXX: clang++
500+
CMAKE_OPTIONS: -D EXAMPLE_USE_SANITIZER=undefined
501+
<<: *linux_success_template
502+
503+
Linux/Clang/ThreadSanitizer (LEGACY):
504+
variables:
505+
CC: clang
506+
CXX: clang++
507+
CMAKE_OPTIONS: -D USE_SANITIZER=thread
508+
<<: *linux_failure_template
509+
510+
Linux/Clang/AddressSanitizer (LEGACY):
511+
variables:
512+
CC: clang
513+
CXX: clang++
514+
CMAKE_OPTIONS: -D USE_SANITIZER=address
515+
<<: *linux_failure_template
516+
517+
Linux/Clang/LeakSanitizer (LEGACY):
518+
variables:
519+
CC: clang
520+
CXX: clang++
521+
CMAKE_OPTIONS: -D USE_SANITIZER=leak
522+
<<: *linux_failure_template
523+
524+
Linux/Clang/MemorySanitizer (LEGACY):
525+
variables:
526+
CC: clang
527+
CXX: clang++
528+
CMAKE_OPTIONS: -D USE_SANITIZER=memory
529+
<<: *linux_failure_template
530+
531+
Linux/Clang/UndefinedSanitizer (LEGACY):
532+
variables:
533+
CC: clang
534+
CXX: clang++
535+
CMAKE_OPTIONS: -D USE_SANITIZER=undefined
536+
<<: *linux_success_template

README.md

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,17 @@ This is a collection of quite useful scripts that expand the possibilities for b
77

88
- [C++ Standards `c++-standards.cmake`](#c-standards-c-standardscmake)
99
- [Sanitizer Builds `sanitizers.cmake`](#sanitizer-builds-sanitizerscmake)
10+
- [Usage](#usage)
1011
- [Code Coverage `code-coverage.cmake`](#code-coverage-code-coveragecmake)
1112
- [Added Targets](#added-targets)
12-
- [Usage](#usage)
13+
- [Usage](#usage-1)
1314
- [Example 1 - All targets instrumented](#example-1---all-targets-instrumented)
1415
- [1a - Via global command](#1a---via-global-command)
1516
- [1b - Via target commands](#1b---via-target-commands)
1617
- [Example 2: Target instrumented, but with regex pattern of files to be excluded from report](#example-2-target-instrumented-but-with-regex-pattern-of-files-to-be-excluded-from-report)
1718
- [Example 3: Target added to the 'ccov' and 'ccov-all' targets](#example-3-target-added-to-the-ccov-and-ccov-all-targets)
1819
- [AFL Fuzzing Instrumentation `afl-fuzzing.cmake`](#afl-fuzzing-instrumentation-afl-fuzzingcmake)
19-
- [Usage](#usage-1)
20+
- [Usage](#usage-2)
2021
- [Compiler Options `compiler-options.cmake`](#compiler-options-compiler-optionscmake)
2122
- [Dependency Graph `dependency-graph.cmake`](#dependency-graph-dependency-graphcmake)
2223
- [Required Arguments](#required-arguments)
@@ -88,16 +89,55 @@ A quick rundown of the tools available, and what they do:
8889
- [MemorySanitizer](https://clang.llvm.org/docs/MemorySanitizer.html) detects uninitialized reads.
8990
- [Control Flow Integrity](https://clang.llvm.org/docs/ControlFlowIntegrity.html) is designed to detect certain forms of undefined behaviour that can potentially allow attackers to subvert the program's control flow.
9091

91-
These are used by declaring the `USE_SANITIZER` CMake variable as string containing any of:
92-
- Address
93-
- Memory
94-
- MemoryWithOrigins
95-
- Undefined
96-
- Thread
97-
- Leak
98-
- CFI
92+
### Usage
93+
94+
The most basic way to enable sanitizers is to simply call `add_sanitizer_support` with the desired sanitizer names, whereupon it will check for the availability and compatability of the combined flags and apply to following compile targets:
95+
```cmake
96+
# apply address and leak sanitizers
97+
add_sanitizer_support(address leak)
98+
# future targets will be compiled with '-fsanitize=address -fsanitize=leak'
99+
```
100+
101+
Compile options on a per-sanitizer basis can be accomplished by calling `set_sanitizer_options` before with the name of the sanitizer and desired compile options:
102+
```cmake
103+
# set custom options that will be applies with that specific sanitizer
104+
set_sanitizer_options(address -fno-omit-frame-pointer)
105+
106+
add_sanitizer_support(address leak)
107+
# future targets will be compiled with '-fsanitize=address -fno-omit-frame-pointer -fsanitize=leak'
108+
```
109+
110+
Per-sanitizer compile options can also be set by setting the named `SANITIZER_${SANITIZER_NAME}_OPTIONS` variable before, either in script or via the command line.
111+
```cmake
112+
# CMake called from command line as `cmake -S . -B build -D SANITIZER_ADDRESS_OPTION='-fno-omit-frame-pointer'`
113+
114+
add_sanitizer_support(address)
115+
# future targets will be compiled with '-fsanitize=address -fno-omit-frame-pointer'
116+
# despite no call to `set_sanitizer_options`
117+
```
118+
119+
To prevent custom sanitizer options from external source being overwritten, the `DEFAULT` option can be used, so that the flags are only used if none have been set previously:
120+
```cmake
121+
# command line has options set via command-line: `cmake -S . -B build -D SANITIZER_ADDRESS_OPTION='-fno-omit-frame-pointer'`
99122
100-
Multiple values are allowed, e.g. `-DUSE_SANITIZER=Address,Leak` but some sanitizers cannot be combined together, e.g.`-DUSE_SANITIZER=Address,Memory` will result in configuration error. The delimeter character is not required and `-DUSE_SANITIZER=AddressLeak` would work as well.
123+
# attempt to set custom options that will not apply since the variable already exists
124+
# and `DEFAULT` option is passed in.
125+
set_sanitizer_options(address DEFAULT -some-other-flag)
126+
127+
add_sanitizer_support(address)
128+
# future targets will be compiled with '-fsanitize=address -fno-omit-frame-pointer'
129+
```
130+
131+
Different sets of options used with the sanitizer can be accomplished by defining the sanitizer serparately with the call to `set_sanitizer_option`:
132+
```cmake
133+
# Despite both using the 'memory' sanitizer, which specific set of flags can be chosen
134+
# when calling `add_sanitizer_support` with either 'memory' or 'memorywithorigins'
135+
set_sanitizer_options(memory DEFAULT -fno-omit-frame-pointer)
136+
set_sanitizer_options(memorywithorigins DEFAULT
137+
SANITIZER memory
138+
-fno-omit-frame-pointer
139+
-fsanitize-memory-track-origins)
140+
```
101141

102142
## Code Coverage [`code-coverage.cmake`](code-coverage.cmake)
103143

example/all/CMakeLists.txt

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,46 @@ set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../..;")
77
include(c++-standards)
88
include(code-coverage)
99
include(formatting)
10-
include(sanitizers)
1110
include(tools)
1211
include(dependency-graph)
1312

1413
# Require C++11
1514
cxx_11()
1615

1716
# Tools
18-
file(GLOB_RECURSE FFILES *.[hc] *.[hc]pp)
19-
clang_format(format ${FFILES})
17+
if(NOT WIN32)
18+
file(GLOB_RECURSE FFILES *.[hc] *.[hc]pp)
19+
clang_format(format ${FFILES})
2020

21-
cmake_format(cmake-format ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
22-
CMakeLists.txt)
21+
cmake_format(cmake-format ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
22+
CMakeLists.txt)
2323

24-
clang_tidy(-format-style=file -checks=* -header-filter='${CMAKE_SOURCE_DIR}/*')
25-
include_what_you_use(-Xiwyu)
26-
cppcheck(
27-
--enable=warning,performance,portability,missingInclude
28-
--template="[{severity}][{id}] {message} {callstack} \(On {file}:{line}\)"
29-
--suppress=missingIncludeSystem --quiet --verbose --force)
24+
clang_tidy(-format-style=file -checks=*
25+
-header-filter='${CMAKE_SOURCE_DIR}/*')
26+
include_what_you_use(-Xiwyu)
27+
cppcheck(
28+
--enable=warning,performance,portability,missingInclude
29+
--template="[{severity}][{id}] {message} {callstack} \(On {file}:{line}\)"
30+
--suppress=missingIncludeSystem --quiet --verbose --force)
31+
endif()
3032

3133
enable_testing()
3234

35+
# Sanitizers
36+
include(sanitizers)
37+
38+
set_sanitizer_options(address DEFAULT)
39+
set_sanitizer_options(leak DEFAULT)
40+
set_sanitizer_options(memory DEFAULT)
41+
set_sanitizer_options(memorywithorigins DEFAULT SANITIZER memory
42+
-fsanitize-memory-track-origins)
43+
set_sanitizer_options(undefined DEFAULT)
44+
set_sanitizer_options(thread DEFAULT)
45+
46+
if(EXAMPLE_USE_SANITIZER)
47+
add_sanitizer_support(${EXAMPLE_USE_SANITIZER})
48+
endif()
49+
3350
# Fails with ThreadSanitizer
3451
add_executable(tsanFail ../src/tsan_fail.cpp)
3552
target_code_coverage(tsanFail AUTO ALL)
@@ -44,7 +61,7 @@ target_code_coverage(lsanFail AUTO ALL)
4461
add_test(lsan lsanFail)
4562

4663
# Fails with AddressSanitizer
47-
if(USE_SANITIZER MATCHES "[Aa]ddress")
64+
if(EXAMPLE_USE_SANITIZER MATCHES "([Aa]ddress)")
4865
add_executable(asanFail ../src/asan_fail.cpp)
4966
target_code_coverage(asanFail AUTO ALL)
5067
add_test(asan asanFail)

0 commit comments

Comments
 (0)