diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 5d3c7d1..4122d58 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -64,6 +64,47 @@ jobs: - name: Lint code with clippy run: cargo clippy + fuzzing: + if: ${{ github.ref == 'main' || !github.event.pull_request.draft || contains(github.event.pull_request.labels.*.name, 'fuzz-me') }} + needs: validity + runs-on: ubuntu-latest + timeout-minutes: 15 + continue-on-error: true + strategy: + matrix: + fuzz-target: [source_roundtrip_naive] + + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: actions/cache@v4 + with: + path: ${{ env.CACHE_PATHS }} + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + + - name: Install latest nightly and set it as default + run: | + rustup install nightly + rustup default nightly + + - name: Install cargo-fuzz + run: cargo install --git https://github.com/rust-fuzz/cargo-fuzz.git + + - name: Run fuzzing + env: + SHORT_CIRCUIT: true + run: | + if ${{ env.SHORT_CIRCUIT }}; then + cargo fuzz run -s none ${{ matrix.fuzz-target }} -- -timeout=10 -use_value_profile=1 -max_total_time=120 + else + cargo fuzz run -s none ${{ matrix.fuzz-target }} -- -timeout=10 -use_value_profile=1 -max_total_time=300 -fork=1 -ignore_crashes=1 + + # if test -d fuzz/artifacts; then + # find fuzz/artifacts -type f -print -exec xxd {} \; -exec cargo fuzz fmt -s none module_roundtrip_structured {} \;; false; + # fi + fi + working-directory: fuzz + publish-ability: runs-on: ubuntu-latest if: false diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml new file mode 100644 index 0000000..fb53a45 --- /dev/null +++ b/fuzz/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "simple-json-parser-fuzz" +version = "0.0.0" +publish = false +edition = "2021" + +[dependencies] +libfuzzer-sys = "0.4" + +[dependencies.simple-json-parser] +path = ".." + +[package.metadata] +cargo-fuzz = true + +[[bin]] +name = "source_roundtrip_naive" +path = "fuzz_targets/source_roundtrip_naive.rs" +test = false +doc = false diff --git a/fuzz/fuzz_targets/source_roundtrip_naive.rs b/fuzz/fuzz_targets/source_roundtrip_naive.rs new file mode 100644 index 0000000..7967c56 --- /dev/null +++ b/fuzz/fuzz_targets/source_roundtrip_naive.rs @@ -0,0 +1,21 @@ +#![no_main] + +use libfuzzer_sys::{fuzz_target, Corpus}; +use simple_json_parser::parse; +use std::str; + +/// `do_fuzz` will take an arbitrary string, parse once and see if it returned a valid source +fn do_fuzz(data: &str) -> Corpus { + let input = data.trim_start(); + + let result = parse(&input, |_keys, _value| {}); + + match result { + Ok(_value) => Corpus::Keep, + Err(_err) => Corpus::Reject, + } +} + +fuzz_target!(|data: &str| { + do_fuzz(data); +});