From: Matt Corallo Date: Sun, 11 Feb 2024 20:43:30 +0000 (+0000) Subject: Add fuzzing of DNS server response parsing X-Git-Tag: v0.5.4~65 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=017c50d3674e47489392523ef3655ca5b35c1622;p=dnssec-prover Add fuzzing of DNS server response parsing --- diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml new file mode 100644 index 0000000..c613c87 --- /dev/null +++ b/fuzz/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "fuzz" +version = "0.0.1" +authors = ["Automatically generated"] +publish = false +edition = "2021" +# Because the function is unused it gets dropped before we link lightning, so +# we have to duplicate build.rs here. Note that this is only required for +# fuzzing mode. + +[package.metadata] +cargo-fuzz = true + +[features] +afl_fuzz = ["afl"] +honggfuzz_fuzz = ["honggfuzz"] +libfuzzer_fuzz = ["libfuzzer-sys"] +stdin_fuzz = [] + +[dependencies] +dnssec-prover = { path = "../", features = ["validation", "std", "build_server"] } + +afl = { version = "0.12", optional = true } +honggfuzz = { version = "0.5", optional = true, default-features = false } +libfuzzer-sys = { version = "0.4", optional = true } + +[build-dependencies] +cc = "1.0" + +# Prevent this from interfering with workspaces +[workspace] +members = ["."] + +[profile.release] +lto = true +codegen-units = 1 +debug-assertions = true +overflow-checks = true + +# When testing a large fuzz corpus, -O1 offers a nice speedup +[profile.dev] +opt-level = 1 + +[[bin]] +name = "parse_response" +path = "src/parse_response.rs" diff --git a/fuzz/src/parse_response.rs b/fuzz/src/parse_response.rs new file mode 100644 index 0000000..b958776 --- /dev/null +++ b/fuzz/src/parse_response.rs @@ -0,0 +1,68 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +#![cfg_attr(feature = "libfuzzer_fuzz", no_main)] + +#[cfg(not(fuzzing))] +compile_error!("Fuzz targets need cfg=fuzzing"); + +extern crate dnssec_prover; +use dnssec_prover::query::fuzz_response; + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + fuzz_response(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + fuzz_response(data); + }); + } +} + +#[cfg(feature = "libfuzzer_fuzz")] +#[macro_use] extern crate libfuzzer_sys; +#[cfg(feature = "libfuzzer_fuzz")] +fuzz_target!(|data: &[u8]| { + fuzz_response(data); +}); + +#[cfg(feature = "stdin_fuzz")] +fn main() { + use std::io::Read; + + let mut data = Vec::with_capacity(8192); + std::io::stdin().read_to_end(&mut data).unwrap(); + fuzz_response(&data); +} + +#[test] +fn run_test_cases() { + use std::fs; + use std::io::Read; + + if let Ok(tests) = fs::read_dir("test_cases/parse_response") { + for test in tests { + let mut data: Vec = Vec::new(); + let path = test.unwrap().path(); + fs::File::open(&path).unwrap().read_to_end(&mut data).unwrap(); + + fuzz_response(&data); + } + } +} diff --git a/fuzz/test_cases/parse_response/SIGABRT.PC.7ffff7e42d3c.STACK.1b2d5a02ed.CODE.-6.ADDR.0.INSTR.mov____%eax,%ebp.fuzz b/fuzz/test_cases/parse_response/SIGABRT.PC.7ffff7e42d3c.STACK.1b2d5a02ed.CODE.-6.ADDR.0.INSTR.mov____%eax,%ebp.fuzz new file mode 100644 index 0000000..ba42741 Binary files /dev/null and b/fuzz/test_cases/parse_response/SIGABRT.PC.7ffff7e42d3c.STACK.1b2d5a02ed.CODE.-6.ADDR.0.INSTR.mov____%eax,%ebp.fuzz differ diff --git a/fuzz/test_cases/parse_response/SIGABRT.PC.7ffff7e42d3c.STACK.c7bb77f34.CODE.-6.ADDR.0.INSTR.mov____%eax,%ebp.fuzz b/fuzz/test_cases/parse_response/SIGABRT.PC.7ffff7e42d3c.STACK.c7bb77f34.CODE.-6.ADDR.0.INSTR.mov____%eax,%ebp.fuzz new file mode 100644 index 0000000..13f45bb Binary files /dev/null and b/fuzz/test_cases/parse_response/SIGABRT.PC.7ffff7e42d3c.STACK.c7bb77f34.CODE.-6.ADDR.0.INSTR.mov____%eax,%ebp.fuzz differ diff --git a/fuzz/test_cases/parse_response/SIGABRT.PC.7ffff7e42d3c.STACK.cbd61ac64.CODE.-6.ADDR.0.INSTR.mov____%eax,%ebp.fuzz b/fuzz/test_cases/parse_response/SIGABRT.PC.7ffff7e42d3c.STACK.cbd61ac64.CODE.-6.ADDR.0.INSTR.mov____%eax,%ebp.fuzz new file mode 100644 index 0000000..6ab92b6 Binary files /dev/null and b/fuzz/test_cases/parse_response/SIGABRT.PC.7ffff7e42d3c.STACK.cbd61ac64.CODE.-6.ADDR.0.INSTR.mov____%eax,%ebp.fuzz differ diff --git a/fuzz/test_cases/parse_response/SIGSEGV.PC.5555555998f9.STACK.1a75cee75b.CODE.1.ADDR.7fffff7feff8.INSTR.push___%rbx.fuzz b/fuzz/test_cases/parse_response/SIGSEGV.PC.5555555998f9.STACK.1a75cee75b.CODE.1.ADDR.7fffff7feff8.INSTR.push___%rbx.fuzz new file mode 100644 index 0000000..ba42741 Binary files /dev/null and b/fuzz/test_cases/parse_response/SIGSEGV.PC.5555555998f9.STACK.1a75cee75b.CODE.1.ADDR.7fffff7feff8.INSTR.push___%rbx.fuzz differ diff --git a/src/query.rs b/src/query.rs index d13e8c6..3b1d217 100644 --- a/src/query.rs +++ b/src/query.rs @@ -53,6 +53,13 @@ async fn send_query_async(stream: &mut TokioTcpStream, domain: &Name, ty: u16) - Ok(()) } +#[cfg(fuzzing)] +/// Read some input and parse it as if it came from a server, for fuzzing. +pub fn fuzz_response(response: &[u8]) { + let (mut proof, mut names) = (Vec::new(), Vec::new()); + let _ = handle_response(response, &mut proof, &mut names); +} + fn handle_response(resp: &[u8], proof: &mut Vec, rrsig_key_names: &mut Vec) -> Result { let mut read: &[u8] = resp; if emap(read_u16(&mut read))? != TXID { return Err(Error::new(ErrorKind::Other, "bad txid")); }