Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 48 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,54 @@ jobs:
name: Build WASM package with wasm-pack
run: wasm-pack build --target web --no-default-features --features alloc,panic-handler

fuzz-test:
name: Fuzz Testing
needs: check-previous-run
if: needs.check-previous-run.outputs.should_skip != 'true'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-24.04, ubuntu-24.04-arm]
fuzz-target:
- digest_crc32_autosar
- digest_crc32_bzip2
- digest_crc32_iscsi
- digest_crc32_iso_hdlc
- digest_crc64_ecma_182
- digest_crc64_nvme
- checksum_crc32_autosar
- checksum_crc32_bzip2
- checksum_crc32_iscsi
- checksum_crc32_iso_hdlc
- checksum_crc64_ecma_182
- checksum_crc64_nvme
steps:
- uses: actions/checkout@v4 # not pinning to commit hash since this is a GitHub action, which we trust
- uses: actions-rust-lang/setup-rust-toolchain@9d7e65c320fdb52dcd45ffaa68deb6c02c8754d9 # v1.12.0
with:
toolchain: nightly
cache-key: ${{ matrix.os }}-nightly-fuzz
- name: Install cargo-fuzz
run: cargo install cargo-fuzz
- name: Run fuzzer
run: |
cargo fuzz run ${{ matrix.fuzz-target }} -- \
-max_total_time=60 \
-rss_limit_mb=2048 \
-timeout=10 \
-print_final_stats=1
continue-on-error: true
- name: Upload artifacts on crash
if: failure()
uses: actions/upload-artifact@v4
with:
name: fuzz-artifacts-${{ matrix.os }}-${{ matrix.fuzz-target }}
path: fuzz/artifacts/${{ matrix.fuzz-target }}/

tests-complete:
name: All tests complete
needs: [check-previous-run, test-aarch64, test-x86_64, test-x86-linux, test-x86-windows, test-software, miri-test-x86_64, test-no-std, test-wasm]
needs: [check-previous-run, test-aarch64, test-x86_64, test-x86-linux, test-x86-windows, test-software, miri-test-x86_64, test-no-std, test-wasm, fuzz-test]
if: always()
runs-on: ubuntu-latest
steps:
Expand All @@ -323,7 +368,8 @@ jobs:
[ "${{ needs.test-software.result }}" == "failure" ] || \
[ "${{ needs.miri-test-x86_64.result }}" == "failure" ] || \
[ "${{ needs.test-no-std.result }}" == "failure" ] || \
[ "${{ needs.test-wasm.result }}" == "failure" ]; then
[ "${{ needs.test-wasm.result }}" == "failure" ] || \
[ "${{ needs.fuzz-test.result }}" == "failure" ]; then
echo "✗ One or more test jobs failed"
exit 1
fi
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,12 @@ In theory, much of the "heavy lifting" has been done, so it should be possible t

PRs welcome!

## Memory Safety

Given the heavy use of hardware intrinsics, this crate uses a decent amount of `unsafe` code.

To help ensure memory safety, this crate is validated using [Miri](https://github.com/rust-lang/miri) on `x86_64` as well as fuzz tested using [libFuzzer](https://github.com/rust-fuzz/libfuzzer) over millions of iterations.

## References

* [Catalogue of parametrised CRC algorithms](https://reveng.sourceforge.io/crc-catalogue/all.htm)
Expand Down
4 changes: 4 additions & 0 deletions fuzz/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
target
corpus
artifacts
coverage
184 changes: 184 additions & 0 deletions fuzz/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

98 changes: 98 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
[package]
name = "crc-fast-rust-fuzz"
version = "0.1.0"
publish = false
edition = "2021"

[package.metadata]
cargo-fuzz = true

[dependencies]
libfuzzer-sys = "0.4"

[dependencies.crc-fast]
path = ".."

[[bin]]
name = "digest_crc32_autosar"
path = "fuzz_targets/digest_crc32_autosar.rs"
test = false
doc = false
bench = false

[[bin]]
name = "digest_crc32_bzip2"
path = "fuzz_targets/digest_crc32_bzip2.rs"
test = false
doc = false
bench = false

[[bin]]
name = "digest_crc32_iscsi"
path = "fuzz_targets/digest_crc32_iscsi.rs"
test = false
doc = false
bench = false

[[bin]]
name = "digest_crc32_iso_hdlc"
path = "fuzz_targets/digest_crc32_iso_hdlc.rs"
test = false
doc = false
bench = false

[[bin]]
name = "digest_crc64_ecma_182"
path = "fuzz_targets/digest_crc64_ecma_182.rs"
test = false
doc = false
bench = false

[[bin]]
name = "digest_crc64_nvme"
path = "fuzz_targets/digest_crc64_nvme.rs"
test = false
doc = false
bench = false

[[bin]]
name = "checksum_crc32_autosar"
path = "fuzz_targets/checksum_crc32_autosar.rs"
test = false
doc = false
bench = false

[[bin]]
name = "checksum_crc32_bzip2"
path = "fuzz_targets/checksum_crc32_bzip2.rs"
test = false
doc = false
bench = false

[[bin]]
name = "checksum_crc32_iscsi"
path = "fuzz_targets/checksum_crc32_iscsi.rs"
test = false
doc = false
bench = false

[[bin]]
name = "checksum_crc32_iso_hdlc"
path = "fuzz_targets/checksum_crc32_iso_hdlc.rs"
test = false
doc = false
bench = false

[[bin]]
name = "checksum_crc64_ecma_182"
path = "fuzz_targets/checksum_crc64_ecma_182.rs"
test = false
doc = false
bench = false

[[bin]]
name = "checksum_crc64_nvme"
path = "fuzz_targets/checksum_crc64_nvme.rs"
test = false
doc = false
bench = false
10 changes: 10 additions & 0 deletions fuzz/fuzz_targets/checksum_crc32_autosar.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//! Fuzz target for CRC-32/AUTOSAR checksum calculation, which is a reflected variant.

#![no_main]

use crc_fast::{CrcAlgorithm, checksum};
use libfuzzer_sys::fuzz_target;

fuzz_target!(|data: &[u8]| {
checksum(CrcAlgorithm::Crc32Autosar, data);
});
10 changes: 10 additions & 0 deletions fuzz/fuzz_targets/checksum_crc32_bzip2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//! Fuzz target for CRC-32/BZIP2 checksum calculation, which is a forward variant.

#![no_main]

use crc_fast::{CrcAlgorithm, checksum};
use libfuzzer_sys::fuzz_target;

fuzz_target!(|data: &[u8]| {
checksum(CrcAlgorithm::Crc32Bzip2, data);
});
Loading
Loading