Skip to content

Commit e6667c2

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 25b58aa commit e6667c2

1 file changed

Lines changed: 155 additions & 0 deletions

File tree

.github/workflows/sanitizers.yml

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

0 commit comments

Comments
 (0)