diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 027c8499dd..6e1178d53d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -108,6 +108,15 @@ jobs: - run: cargo update -Z minimal-versions - run: cargo check --all-features + fuzz: + name: Fuzz + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@nightly + - uses: dtolnay/install@cargo-fuzz + - run: cargo fuzz build -O + miri: name: Miri runs-on: ubuntu-latest @@ -137,3 +146,4 @@ jobs: - uses: actions/checkout@v3 - uses: dtolnay/install@cargo-outdated - run: cargo outdated --workspace --exit-code 1 + - run: cargo outdated --manifest-path fuzz/Cargo.toml --exit-code 1 diff --git a/fuzz/.gitignore b/fuzz/.gitignore new file mode 100644 index 0000000000..188f196098 --- /dev/null +++ b/fuzz/.gitignore @@ -0,0 +1,3 @@ +artifacts/ +corpus/ +target/ diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml new file mode 100644 index 0000000000..ed4b889745 --- /dev/null +++ b/fuzz/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "syn-fuzz" +version = "0.0.0" +authors = ["David Tolnay "] +edition = "2021" +publish = false + +[package.metadata] +cargo-fuzz = true + +[dependencies] +libfuzzer-sys = "0.4" +proc-macro2 = "1" +syn = { path = "..", default-features = false, features = ["full", "parsing"] } + +[[bin]] +name = "create_token_buffer" +path = "fuzz_targets/create_token_buffer.rs" +test = false +doc = false + +[[bin]] +name = "parse_file" +path = "fuzz_targets/parse_file.rs" +test = false +doc = false + +[workspace] diff --git a/fuzz/fuzz_targets/create_token_buffer.rs b/fuzz/fuzz_targets/create_token_buffer.rs new file mode 100644 index 0000000000..7b6622a160 --- /dev/null +++ b/fuzz/fuzz_targets/create_token_buffer.rs @@ -0,0 +1,18 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; +use proc_macro2::Span; +use std::str; +use syn::parse::{ParseStream, Parser}; + +fn immediate_fail(_input: ParseStream) -> syn::Result<()> { + Err(syn::Error::new(Span::call_site(), "")) +} + +fuzz_target!(|data: &[u8]| { + if data.len() < 300 { + if let Ok(string) = str::from_utf8(data) { + _ = immediate_fail.parse_str(string); + } + } +}); diff --git a/fuzz/fuzz_targets/parse_file.rs b/fuzz/fuzz_targets/parse_file.rs new file mode 100644 index 0000000000..4fa11dd924 --- /dev/null +++ b/fuzz/fuzz_targets/parse_file.rs @@ -0,0 +1,12 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; +use std::str; + +fuzz_target!(|data: &[u8]| { + if data.len() < 300 { + if let Ok(string) = str::from_utf8(data) { + _ = syn::parse_file(string); + } + } +});