Skip to content

Commit d48f412

Browse files
ci: add ASan and UBSan CI jobs
- New sanitizers.yml with separate ASan, UBSan, and ASan+LSan jobs, all built with clang - Uses -Db_sanitize and -Db_lundef=false for proper sanitizer runtime linking - ASan runs with detect_leaks=0 (libfuse teardown false positives); ASan+LSan runs with detect_leaks=1 and continue-on-error: true - Sanitizer logs written to workspace-local log_path files and uploaded as artifacts - Hard-fail FUSE preflight, explicit SSH setup, pytest timeouts, JUnit XML - All actions pinned to Node 24-capable SHAs, runner pinned to ubuntu-24.04
1 parent afbdf92 commit d48f412

1 file changed

Lines changed: 157 additions & 0 deletions

File tree

.github/workflows/sanitizers.yml

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
name: sanitizers
2+
3+
on:
4+
push:
5+
pull_request:
6+
schedule:
7+
- cron: '0 4 * * 1' # Every Monday at 04:00 UTC
8+
workflow_dispatch:
9+
10+
permissions:
11+
contents: read
12+
13+
concurrency:
14+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
15+
cancel-in-progress: true
16+
17+
jobs:
18+
sanitize:
19+
name: ${{ matrix.sanitizer }}
20+
runs-on: ubuntu-24.04
21+
timeout-minutes: 30
22+
strategy:
23+
fail-fast: false
24+
matrix:
25+
include:
26+
- sanitizer: asan
27+
san_flag: address
28+
san_opts: "detect_leaks=0:halt_on_error=1:symbolize=1"
29+
extra_cflags: "-fno-omit-frame-pointer -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0"
30+
- sanitizer: ubsan
31+
san_flag: undefined
32+
san_opts: "halt_on_error=1:print_stacktrace=1"
33+
extra_cflags: "-fno-omit-frame-pointer"
34+
steps:
35+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
36+
37+
- name: Set up Python
38+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
39+
with:
40+
python-version: '3.12'
41+
42+
- name: Install dependencies
43+
run: |
44+
sudo apt-get update
45+
sudo apt-get install -y clang llvm ninja-build pkg-config libglib2.0-dev libfuse3-dev fuse3 openssh-client openssh-server
46+
pip3 install meson pytest pytest-timeout
47+
48+
- name: Setup SSH
49+
run: |
50+
mkdir -p ~/.ssh
51+
chmod 700 ~/.ssh
52+
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -q -N ""
53+
cat ~/.ssh/id_ed25519.pub > ~/.ssh/authorized_keys
54+
chmod 600 ~/.ssh/authorized_keys
55+
sudo systemctl start ssh || sudo service ssh start
56+
ssh -o StrictHostKeyChecking=no -o BatchMode=yes localhost true
57+
58+
- name: Check FUSE availability
59+
run: |
60+
test -e /dev/fuse
61+
command -v fusermount3
62+
63+
- name: Build
64+
env:
65+
CC: clang
66+
CFLAGS: ${{ matrix.extra_cflags }}
67+
run: |
68+
meson setup build -Db_sanitize=${{ matrix.san_flag }} -Db_lundef=false -Dwerror=true
69+
ninja -C build
70+
71+
- name: Create sanitizer log directory
72+
run: mkdir -p sanitizer-logs
73+
74+
- name: Test
75+
env:
76+
ASAN_OPTIONS: "${{ matrix.sanitizer == 'asan' && format('{0}:log_path={1}/sanitizer-logs/asan', matrix.san_opts, github.workspace) || '' }}"
77+
UBSAN_OPTIONS: "${{ matrix.sanitizer == 'ubsan' && format('{0}:log_path={1}/sanitizer-logs/ubsan', matrix.san_opts, github.workspace) || '' }}"
78+
ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer
79+
run: |
80+
cd build
81+
python3 -m pytest test/ --timeout=180 --maxfail=99 --junitxml=test-results.xml
82+
timeout-minutes: 20
83+
84+
- name: Upload test results
85+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
86+
if: always()
87+
with:
88+
name: test-results-${{ matrix.sanitizer }}
89+
path: |
90+
build/test-results.xml
91+
build/meson-logs/
92+
sanitizer-logs/
93+
94+
asan-lsan:
95+
name: ASan + LeakSanitizer
96+
runs-on: ubuntu-24.04
97+
timeout-minutes: 30
98+
continue-on-error: true
99+
steps:
100+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
101+
102+
- name: Set up Python
103+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
104+
with:
105+
python-version: '3.12'
106+
107+
- name: Install dependencies
108+
run: |
109+
sudo apt-get update
110+
sudo apt-get install -y clang llvm ninja-build pkg-config libglib2.0-dev libfuse3-dev fuse3 openssh-client openssh-server
111+
pip3 install meson pytest pytest-timeout
112+
113+
- name: Setup SSH
114+
run: |
115+
mkdir -p ~/.ssh
116+
chmod 700 ~/.ssh
117+
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -q -N ""
118+
cat ~/.ssh/id_ed25519.pub > ~/.ssh/authorized_keys
119+
chmod 600 ~/.ssh/authorized_keys
120+
sudo systemctl start ssh || sudo service ssh start
121+
ssh -o StrictHostKeyChecking=no -o BatchMode=yes localhost true
122+
123+
- name: Check FUSE availability
124+
run: |
125+
test -e /dev/fuse
126+
command -v fusermount3
127+
128+
- name: Build
129+
env:
130+
CC: clang
131+
CFLAGS: "-fno-omit-frame-pointer -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0"
132+
run: |
133+
meson setup build -Db_sanitize=address -Db_lundef=false -Dwerror=true
134+
ninja -C build
135+
136+
- name: Create sanitizer log directory
137+
run: mkdir -p sanitizer-logs
138+
139+
- name: Test
140+
env:
141+
ASAN_OPTIONS: "detect_leaks=1:halt_on_error=1:symbolize=1:log_path=${{ github.workspace }}/sanitizer-logs/asan-lsan"
142+
LSAN_OPTIONS: "suppressions=${{ github.workspace }}/test/lsan_suppress.txt"
143+
ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer
144+
run: |
145+
cd build
146+
python3 -m pytest test/ --timeout=180 --maxfail=99 --junitxml=test-results.xml
147+
timeout-minutes: 20
148+
149+
- name: Upload test results
150+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
151+
if: always()
152+
with:
153+
name: test-results-asan-lsan
154+
path: |
155+
build/test-results.xml
156+
build/meson-logs/
157+
sanitizer-logs/

0 commit comments

Comments
 (0)