Skip to content

Commit 0e866e4

Browse files
committed
added fuzzing to ci pipeline
1 parent 4ecd532 commit 0e866e4

1 file changed

Lines changed: 230 additions & 0 deletions

File tree

.github/workflows/fuzz.yml

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
name: Fuzz Testing
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
schedule:
9+
# Run daily at 2 AM UTC
10+
- cron: '0 2 * * *'
11+
workflow_dispatch:
12+
inputs:
13+
duration:
14+
description: 'Fuzzing duration in seconds'
15+
required: false
16+
default: '600'
17+
target:
18+
description: 'Fuzz target to run (all_protocols or validate_with_python)'
19+
required: false
20+
default: 'all_protocols'
21+
22+
env:
23+
CARGO_TERM_COLOR: always
24+
RUST_BACKTRACE: 1
25+
26+
jobs:
27+
fuzz-fast:
28+
name: Fast Fuzzing (all_protocols)
29+
runs-on: ubuntu-latest
30+
if: github.event_name == 'pull_request' || github.event_name == 'push'
31+
steps:
32+
- name: Checkout code
33+
uses: actions/checkout@v4
34+
35+
- name: Install Rust toolchain
36+
uses: dtolnay/rust-toolchain@nightly
37+
38+
- name: Install cargo-fuzz
39+
run: cargo install cargo-fuzz
40+
41+
- name: Cache fuzz corpus
42+
uses: actions/cache@v4
43+
with:
44+
path: fuzz/corpus/all_protocols
45+
key: fuzz-corpus-all-protocols-${{ github.sha }}
46+
restore-keys: |
47+
fuzz-corpus-all-protocols-
48+
49+
- name: Run fast fuzzing (5 minutes)
50+
run: |
51+
cargo fuzz run all_protocols -- \
52+
-max_total_time=300 \
53+
-print_final_stats=1 \
54+
-verbosity=1
55+
continue-on-error: true
56+
57+
- name: Check for crashes
58+
if: always()
59+
run: |
60+
if [ -d "fuzz/artifacts/all_protocols" ] && [ "$(ls -A fuzz/artifacts/all_protocols)" ]; then
61+
echo "::error::Fuzzing found crashes!"
62+
ls -la fuzz/artifacts/all_protocols/
63+
exit 1
64+
fi
65+
66+
- name: Upload crash artifacts
67+
if: failure()
68+
uses: actions/upload-artifact@v4
69+
with:
70+
name: fuzz-crashes-all-protocols
71+
path: fuzz/artifacts/all_protocols/
72+
if-no-files-found: ignore
73+
74+
fuzz-thorough:
75+
name: Thorough Fuzzing (validate_with_python)
76+
runs-on: ubuntu-latest
77+
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
78+
steps:
79+
- name: Checkout code
80+
uses: actions/checkout@v4
81+
82+
- name: Install Rust toolchain
83+
uses: dtolnay/rust-toolchain@nightly
84+
85+
- name: Install Python
86+
uses: actions/setup-python@v5
87+
with:
88+
python-version: '3.11'
89+
90+
- name: Install cargo-fuzz
91+
run: cargo install cargo-fuzz
92+
93+
- name: Cache fuzz corpus
94+
uses: actions/cache@v4
95+
with:
96+
path: fuzz/corpus/validate_with_python
97+
key: fuzz-corpus-validate-python-${{ github.sha }}
98+
restore-keys: |
99+
fuzz-corpus-validate-python-
100+
101+
- name: Determine fuzzing duration
102+
id: duration
103+
run: |
104+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
105+
echo "duration=${{ github.event.inputs.duration }}" >> $GITHUB_OUTPUT
106+
else
107+
echo "duration=1800" >> $GITHUB_OUTPUT
108+
fi
109+
110+
- name: Run thorough fuzzing with Python validation
111+
run: |
112+
cargo fuzz run validate_with_python -- \
113+
-max_total_time=${{ steps.duration.outputs.duration }} \
114+
-print_final_stats=1 \
115+
-verbosity=1
116+
continue-on-error: true
117+
118+
- name: Check for crashes
119+
if: always()
120+
run: |
121+
if [ -d "fuzz/artifacts/validate_with_python" ] && [ "$(ls -A fuzz/artifacts/validate_with_python)" ]; then
122+
echo "::error::Fuzzing found crashes!"
123+
ls -la fuzz/artifacts/validate_with_python/
124+
exit 1
125+
fi
126+
127+
- name: Upload crash artifacts
128+
if: failure()
129+
uses: actions/upload-artifact@v4
130+
with:
131+
name: fuzz-crashes-validate-python
132+
path: fuzz/artifacts/validate_with_python/
133+
if-no-files-found: ignore
134+
135+
fuzz-custom:
136+
name: Custom Fuzzing Run
137+
runs-on: ubuntu-latest
138+
if: github.event_name == 'workflow_dispatch'
139+
steps:
140+
- name: Checkout code
141+
uses: actions/checkout@v4
142+
143+
- name: Install Rust toolchain
144+
uses: dtolnay/rust-toolchain@nightly
145+
146+
- name: Install Python
147+
uses: actions/setup-python@v5
148+
with:
149+
python-version: '3.11'
150+
151+
- name: Install cargo-fuzz
152+
run: cargo install cargo-fuzz
153+
154+
- name: Cache fuzz corpus
155+
uses: actions/cache@v4
156+
with:
157+
path: fuzz/corpus/${{ github.event.inputs.target }}
158+
key: fuzz-corpus-${{ github.event.inputs.target }}-${{ github.sha }}
159+
restore-keys: |
160+
fuzz-corpus-${{ github.event.inputs.target }}-
161+
162+
- name: Run custom fuzzing
163+
run: |
164+
cargo fuzz run ${{ github.event.inputs.target }} -- \
165+
-max_total_time=${{ github.event.inputs.duration }} \
166+
-print_final_stats=1 \
167+
-verbosity=1
168+
continue-on-error: true
169+
170+
- name: Check for crashes
171+
if: always()
172+
run: |
173+
if [ -d "fuzz/artifacts/${{ github.event.inputs.target }}" ] && [ "$(ls -A fuzz/artifacts/${{ github.event.inputs.target }})" ]; then
174+
echo "::error::Fuzzing found crashes!"
175+
ls -la fuzz/artifacts/${{ github.event.inputs.target }}/
176+
exit 1
177+
fi
178+
179+
- name: Upload crash artifacts
180+
if: failure()
181+
uses: actions/upload-artifact@v4
182+
with:
183+
name: fuzz-crashes-${{ github.event.inputs.target }}
184+
path: fuzz/artifacts/${{ github.event.inputs.target }}/
185+
if-no-files-found: ignore
186+
187+
minimize-corpus:
188+
name: Minimize Corpus
189+
runs-on: ubuntu-latest
190+
if: github.event_name == 'schedule'
191+
needs: [fuzz-thorough]
192+
steps:
193+
- name: Checkout code
194+
uses: actions/checkout@v4
195+
196+
- name: Install Rust toolchain
197+
uses: dtolnay/rust-toolchain@nightly
198+
199+
- name: Install cargo-fuzz
200+
run: cargo install cargo-fuzz
201+
202+
- name: Restore corpus
203+
uses: actions/cache@v4
204+
with:
205+
path: |
206+
fuzz/corpus/all_protocols
207+
fuzz/corpus/validate_with_python
208+
key: fuzz-corpus-all-${{ github.sha }}
209+
restore-keys: |
210+
fuzz-corpus-all-
211+
212+
- name: Minimize all_protocols corpus
213+
run: cargo fuzz cmin all_protocols
214+
continue-on-error: true
215+
216+
- name: Minimize validate_with_python corpus
217+
run: cargo fuzz cmin validate_with_python
218+
continue-on-error: true
219+
220+
- name: Report corpus stats
221+
run: |
222+
echo "## Corpus Statistics" >> $GITHUB_STEP_SUMMARY
223+
echo "" >> $GITHUB_STEP_SUMMARY
224+
echo "### all_protocols" >> $GITHUB_STEP_SUMMARY
225+
echo "Files: $(find fuzz/corpus/all_protocols -type f | wc -l)" >> $GITHUB_STEP_SUMMARY
226+
echo "Size: $(du -sh fuzz/corpus/all_protocols | cut -f1)" >> $GITHUB_STEP_SUMMARY
227+
echo "" >> $GITHUB_STEP_SUMMARY
228+
echo "### validate_with_python" >> $GITHUB_STEP_SUMMARY
229+
echo "Files: $(find fuzz/corpus/validate_with_python -type f | wc -l)" >> $GITHUB_STEP_SUMMARY
230+
echo "Size: $(du -sh fuzz/corpus/validate_with_python | cut -f1)" >> $GITHUB_STEP_SUMMARY

0 commit comments

Comments
 (0)