Skip to content

Commit 35a43c8

Browse files
authored
add a sanitizer build (#188)
Add sanitizers to the CI builds
1 parent d0c89cd commit 35a43c8

15 files changed

Lines changed: 372 additions & 80 deletions

File tree

.github/actions/run-clang-tidy-pr.sh

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ set -euo pipefail
33

44
ROOT_DIR=$(pwd)
55

6+
is_third_party_file() {
7+
local source_file="$1"
8+
[[ "$source_file" == ThirdParty/* ]]
9+
}
10+
611
append_include_args() {
712
local raw_paths="$1"
813
local split_paths
@@ -24,7 +29,13 @@ FILES_URL="$(jq -r '.pull_request._links.self.href' "$GITHUB_EVENT_PATH")/files"
2429
FILES=$(curl -s -X GET -G "$FILES_URL" | jq -r '.[] | .filename')
2530
echo "====Files Changed in PR===="
2631
echo "$FILES"
27-
filecount=$(echo "$FILES" | grep -c -E '\.(cpp|cc|cxx|c)$' || true)
32+
filecount=$(
33+
while read -r line; do
34+
if [[ "$line" =~ \.(cpp|cc|cxx|c)$ ]] && ! is_third_party_file "$line"; then
35+
echo "$line"
36+
fi
37+
done <<<"$FILES" | grep -c .
38+
)
2839
echo "Total changed: $filecount"
2940
tidyerr=0
3041
if ((filecount > 0 && filecount <= 25)); then
@@ -57,6 +68,10 @@ if ((filecount > 0 && filecount <= 25)); then
5768
fi
5869
while read -r line; do
5970
if echo "$line" | grep -E '\.(cpp|cc|cxx|c)$'; then
71+
if is_third_party_file "$line"; then
72+
echo "skipping ${line}: third-party source"
73+
continue
74+
fi
6075
source_file="${ROOT_DIR}/${line}"
6176
if ! file_in_compile_db "$source_file"; then
6277
echo "skipping ${line}: not present in compilation database"

.github/workflows/asan.yml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: Address Sanitizer
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
workflow_dispatch:
11+
12+
permissions:
13+
contents: read
14+
15+
concurrency:
16+
group: asan-${{ github.workflow }}-${{ github.ref }}
17+
cancel-in-progress: true
18+
19+
jobs:
20+
asan:
21+
name: ASan
22+
runs-on: ubuntu-latest
23+
container:
24+
image: helics/buildenv:sanitizers-22
25+
env:
26+
ASAN_OPTIONS: detect_leaks=0
27+
LSAN_OPTIONS: verbosity=1:log_threads=1
28+
29+
steps:
30+
- uses: actions/checkout@v6
31+
with:
32+
submodules: recursive
33+
34+
- name: Mark workspace as safe for git
35+
run: git config --global --add safe.directory "${GITHUB_WORKSPACE}"
36+
37+
- name: Install SuiteSparse build dependencies
38+
shell: bash
39+
run: |
40+
apt-get update
41+
apt-get install -y libblas-dev liblapack-dev
42+
43+
- name: Configure
44+
shell: bash
45+
run: >
46+
cmake -S . -B build
47+
-C "${GITHUB_WORKSPACE}/scripts/asan-cache.cmake"
48+
-DCMAKE_C_COMPILER=clang
49+
-DCMAKE_CXX_COMPILER=clang++
50+
-DBUILD_TESTING=ON
51+
-DGRIDDYN_BUILD_TESTS=ON
52+
-DGRIDDYN_SUITESPARSE_FORCE_SUBPROJECT=ON
53+
-DGRIDDYN_ENABLE_FMI=OFF
54+
-DGRIDDYN_ENABLE_HELICS_EXECUTABLE=OFF
55+
56+
- name: Build
57+
shell: bash
58+
run: cmake --build build --parallel 4
59+
60+
- name: Run ASan tests
61+
shell: bash
62+
run: ctest --test-dir build --output-on-failure -L Continuous

.github/workflows/msan.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Memory Sanitizer
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
workflow_dispatch:
11+
12+
permissions:
13+
contents: read
14+
15+
concurrency:
16+
group: msan-${{ github.workflow }}-${{ github.ref }}
17+
cancel-in-progress: true
18+
19+
jobs:
20+
msan:
21+
name: MSan
22+
runs-on: ubuntu-latest
23+
container:
24+
image: helics/buildenv:sanitizers-22
25+
26+
steps:
27+
- uses: actions/checkout@v6
28+
with:
29+
submodules: recursive
30+
31+
- name: Mark workspace as safe for git
32+
run: git config --global --add safe.directory "${GITHUB_WORKSPACE}"
33+
34+
- name: Install SuiteSparse build dependencies
35+
shell: bash
36+
run: |
37+
apt-get update
38+
apt-get install -y libblas-dev liblapack-dev libunwind-dev
39+
40+
- name: Prepare MSan runtime libraries
41+
shell: bash
42+
run: |
43+
libunwind_path="$(ldconfig -p | awk '/libunwind\.so/ { print $NF; exit }')"
44+
if [ -z "${libunwind_path}" ]; then
45+
echo "Unable to locate a libunwind shared library"
46+
exit 1
47+
fi
48+
if [ ! -e /root/develop/libcxx_msan/lib/libunwind.so.1 ]; then
49+
ln -s "${libunwind_path}" /root/develop/libcxx_msan/lib/libunwind.so.1
50+
fi
51+
52+
- name: Configure
53+
shell: bash
54+
run: >
55+
cmake -S . -B build
56+
-DCMAKE_C_COMPILER=clang
57+
-DCMAKE_CXX_COMPILER=clang++
58+
-DCMAKE_C_FLAGS="-fsanitize=memory -fsanitize-ignorelist=${GITHUB_WORKSPACE}/config/msan_ignorelist.txt -fno-omit-frame-pointer -g -O1"
59+
-DCMAKE_CXX_FLAGS="-fsanitize=memory -fsanitize-ignorelist=${GITHUB_WORKSPACE}/config/msan_ignorelist.txt -nostdinc++ -nostdlib++ -L/root/develop/libcxx_msan/lib -lc++ -lc++abi -I/root/develop/libcxx_msan/include -I/root/develop/libcxx_msan/include/c++/v1 -Wno-unused-command-line-argument -Wno-reserved-identifier -Wno-reserved-macro-identifier -fno-omit-frame-pointer -g -O1 -Wl,-rpath=/root/develop/libcxx_msan/lib"
60+
-DBUILD_TESTING=ON
61+
-DGRIDDYN_BUILD_TESTS=ON
62+
-DGRIDDYN_SUITESPARSE_FORCE_SUBPROJECT=ON
63+
-DGRIDDYN_ENABLE_FMI=OFF
64+
-DGRIDDYN_ENABLE_HELICS_EXECUTABLE=OFF
65+
66+
- name: Build
67+
shell: bash
68+
run: cmake --build build --parallel 4
69+
70+
- name: Run MSan tests
71+
shell: bash
72+
run: LD_LIBRARY_PATH="/root/develop/libcxx_msan/lib:/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH}" ctest --test-dir build --output-on-failure -L Continuous

.github/workflows/tsan.yml

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
name: Thread Sanitizer
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
workflow_dispatch:
11+
12+
permissions:
13+
contents: read
14+
15+
concurrency:
16+
group: tsan-${{ github.workflow }}-${{ github.ref }}
17+
cancel-in-progress: true
18+
19+
jobs:
20+
tsan:
21+
name: TSan
22+
runs-on: ubuntu-latest
23+
container:
24+
image: helics/buildenv:sanitizers-22
25+
26+
steps:
27+
- uses: actions/checkout@v6
28+
with:
29+
submodules: recursive
30+
31+
- name: Mark workspace as safe for git
32+
run: git config --global --add safe.directory "${GITHUB_WORKSPACE}"
33+
34+
- name: Install SuiteSparse build dependencies
35+
shell: bash
36+
run: |
37+
apt-get update
38+
apt-get install -y libblas-dev liblapack-dev libunwind-dev
39+
40+
- name: Prepare TSan runtime libraries
41+
shell: bash
42+
run: |
43+
libunwind_path="$(ldconfig -p | awk '/libunwind\.so/ { print $NF; exit }')"
44+
if [ -z "${libunwind_path}" ]; then
45+
echo "Unable to locate a libunwind shared library"
46+
exit 1
47+
fi
48+
if [ ! -e /root/develop/libcxx_tsan/lib/libunwind.so.1 ]; then
49+
ln -s "${libunwind_path}" /root/develop/libcxx_tsan/lib/libunwind.so.1
50+
fi
51+
52+
- name: Configure
53+
shell: bash
54+
run: >
55+
cmake -S . -B build
56+
-DCMAKE_C_COMPILER=clang
57+
-DCMAKE_CXX_COMPILER=clang++
58+
-DCMAKE_C_FLAGS="-fsanitize=thread -fno-omit-frame-pointer -g -O1"
59+
-DCMAKE_CXX_FLAGS="-fsanitize=thread -nostdinc++ -nostdlib++ -L/root/develop/libcxx_tsan/lib -lc++ -lc++abi -I/root/develop/libcxx_tsan/include -I/root/develop/libcxx_tsan/include/c++/v1 -Wno-unused-command-line-argument -Wno-reserved-identifier -Wno-reserved-macro-identifier -fno-omit-frame-pointer -g -O1 -Wl,-rpath=/root/develop/libcxx_tsan/lib"
60+
-DBUILD_TESTING=ON
61+
-DGRIDDYN_BUILD_TESTS=ON
62+
-DGRIDDYN_SUITESPARSE_FORCE_SUBPROJECT=ON
63+
-DGRIDDYN_ENABLE_FMI=OFF
64+
-DGRIDDYN_ENABLE_HELICS_EXECUTABLE=OFF
65+
66+
- name: Build
67+
shell: bash
68+
run: cmake --build build --parallel 4
69+
70+
- name: Run TSan tests
71+
shell: bash
72+
run: >
73+
LD_LIBRARY_PATH="/root/develop/libcxx_tsan/lib:/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH}"
74+
TSAN_OPTIONS="second_deadlock_stack=1 suppressions=${GITHUB_WORKSPACE}/config/tsan_suppression.txt history_size=4"
75+
ctest --test-dir build --output-on-failure -L Continuous

ThirdParty/Minizip/miniunz.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ static int do_extract_currentfile(unzFile uf, const int* popt_extract_without_pa
322322
}
323323

324324
size_buf = WRITEBUFFERSIZE;
325-
buf = (void*)malloc(size_buf);
325+
buf = (void*)calloc(size_buf, 1);
326326
if (buf==NULL)
327327
{
328328
printf("Error allocating memory\n");

ThirdParty/Minizip/zip.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,6 +1392,7 @@ extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, c
13921392
zi->ci.encrypt = 0;
13931393
zi->ci.stream_initialised = 0;
13941394
zi->ci.pos_in_buffered_data = 0;
1395+
memset(zi->ci.buffered_data, 0, sizeof(zi->ci.buffered_data));
13951396
zi->ci.raw = raw;
13961397
zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream);
13971398

config/cmake/SundialsKLU.cmake

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,18 @@ endforeach()
2323

2424
# Fall back to imported namespaces when available.
2525
if(NOT _griddyn_klu_link_targets)
26-
foreach(_klu_tgt IN ITEMS Suitesparse::klu Suitesparse::btf Suitesparse::amd
27-
Suitesparse::colamd Suitesparse::suitesparseconfig
26+
foreach(
27+
_klu_tgt IN
28+
ITEMS SuiteSparse::klu
29+
SuiteSparse::btf
30+
SuiteSparse::amd
31+
SuiteSparse::colamd
32+
SuiteSparse::suitesparseconfig
33+
Suitesparse::klu
34+
Suitesparse::btf
35+
Suitesparse::amd
36+
Suitesparse::colamd
37+
Suitesparse::suitesparseconfig
2838
)
2939
if(TARGET ${_klu_tgt})
3040
list(APPEND _griddyn_klu_link_targets ${_klu_tgt})

config/cmake/addKLU.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ cmake_dependent_advanced_option(
3333
"NOT ${PROJECT_NAME}_USE_SYSTEM_SUITESPARSE_ONLY" OFF
3434
)
3535

36-
set(SuiteSparseNameSpace Suitesparse)
36+
set(SuiteSparseNameSpace SuiteSparse)
3737

3838
cmake_dependent_advanced_option(
3939
${PROJECT_NAME}_USE_SUITESPARSE_STATIC_LIBRARY "use the suitesparse static library" OFF

config/msan_ignorelist.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Ignore known MemorySanitizer noise from bundled third-party KLU teardown.
2+
# This lets the MSan workflow continue far enough to report issues in GridDyn
3+
# code instead of stopping immediately in SuiteSparse internals.
4+
src:*/ThirdParty/suitesparse-cmake/SuiteSparse/KLU/*
5+
fun:KLU_free_numeric
6+
7+
# Ignore known MemorySanitizer noise from bundled Minizip extraction internals.
8+
# GridDyn exercises these via zipUtilities, but the current report is entirely
9+
# within third-party decompression code rather than GridDyn-owned logic.
10+
src:*/ThirdParty/Minizip/*
11+
fun:unzReadCurrentFile
12+
fun:zip64FlushWriteBuffer
13+
fun:zipCloseFileInZipRaw64

config/tsan_suppression.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# This is a known purposeful leak and possible resulting race condition detection on closing of shared libraries
2+
3+
# potential race condition from
4+
race:cxa_at_exit_wrapper
5+
6+
# false positive https://github.com/google/sanitizers/issues/1620
7+
mutex:timed_mutex::unlock

0 commit comments

Comments
 (0)