Skip to content

Fuzzing and Testing

bisu edited this page Sep 21, 2026 · 1 revision

Fuzzing and Testing

Unit tests

Run the full suite:

cargo test --locked

Tests live inline in src/ modules and cover: header parsing, section/segment decoding, string escaping, mitigation analysis (PIE/NX/RELRO/canary), dynamic-table decoding — including a stripped ELF fixture with no section headers (dynamic table recovered from PT_DYNAMIC), and rejection of malformed inputs (out-of-bounds tables, oversized strings, truncated files).

Fuzzing

The ELF parser is fuzzed with cargo-fuzz:

cargo install cargo-fuzz --locked
cargo fuzz run parse_elf -- -max_total_time=300

The target (fuzz/fuzz_targets/parse_elf.rs) feeds arbitrary bytes straight to binary_inspector::elf::parse and asserts nothing except that the parser never panics:

fuzz_target!(|data: &[u8]| {
    let _ = binary_inspector::elf::parse(data, data.len() as u64);
});

CI fuzzing

.github/workflows/fuzz.yml runs weekly (Sundays 02:00 UTC) and on demand:

  • Installs cargo-fuzz (install failure fails the job — no swallowing)
  • Runs 60 seconds of fuzzing; any crash fails the job (no || true)
  • Pins nightly toolchain and all actions to commit SHAs

Because parsing is panic-free by design, a crash found by fuzzing is treated as a high-severity parser bug: fix it, then add a malformed-input regression test reproducing it (see Contributing).

Manual regression workflow

For every parser bug:

  1. Reduce the crashing input to the smallest byte pattern.
  2. Add a #[test] in the relevant module that feeds it to parse (or the specific helper) and asserts the error/expected result.
  3. Confirm the test fails against the unfixed code, then passes after the fix.

Clone this wiki locally