From 8d2ec838e48c64bcb6ef81ea31806219f06e0f42 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Sat, 19 Nov 2022 14:36:50 +0000 Subject: [PATCH] add fuzzing harness for simple_http --- .gitignore | 2 ++ fuzz/.gitignore | 4 +++ fuzz/Cargo.toml | 24 +++++++++++++ fuzz/fuzz_targets/simple_http.rs | 60 ++++++++++++++++++++++++++++++++ fuzz/travis-fuzz.sh | 40 +++++++++++++++++++++ src/simple_http.rs | 3 ++ 6 files changed, 133 insertions(+) create mode 100644 fuzz/.gitignore create mode 100644 fuzz/Cargo.toml create mode 100644 fuzz/fuzz_targets/simple_http.rs create mode 100755 fuzz/travis-fuzz.sh diff --git a/.gitignore b/.gitignore index 46bf68e8..9422e6ec 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ target Cargo.lock +fuzz/hfuzz_workspace/ +fuzz/hfuzz_target/ diff --git a/fuzz/.gitignore b/fuzz/.gitignore new file mode 100644 index 00000000..572e03bd --- /dev/null +++ b/fuzz/.gitignore @@ -0,0 +1,4 @@ + +target +corpus +artifacts diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml new file mode 100644 index 00000000..c5b0d03b --- /dev/null +++ b/fuzz/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "jsonrpc-fuzz" +version = "0.0.1" +authors = ["Automatically generated"] +publish = false + +[package.metadata] +cargo-fuzz = true + +[features] +honggfuzz_fuzz = ["honggfuzz"] + +[dependencies] +honggfuzz = { version = "0.5", optional = true, default-features = false } +jsonrpc = { path = ".." } + +# Prevent this from interfering with workspaces +[workspace] +members = ["."] + +[[bin]] +name = "simple_http" +path = "fuzz_targets/simple_http.rs" + diff --git a/fuzz/fuzz_targets/simple_http.rs b/fuzz/fuzz_targets/simple_http.rs new file mode 100644 index 00000000..53812b0c --- /dev/null +++ b/fuzz/fuzz_targets/simple_http.rs @@ -0,0 +1,60 @@ + +extern crate jsonrpc; + +#[cfg(not(fuzzing))] +compile_error!("You must set RUSTFLAGS=--cfg=fuzzing to run these test, or run the actual fuzz harness."); + +use jsonrpc::Client; +use jsonrpc::simple_http::SimpleHttpTransport; +use jsonrpc::simple_http::FUZZ_TCP_SOCK; + +use std::io; + +fn do_test(data: &[u8]) { + *FUZZ_TCP_SOCK.lock().unwrap() = Some(io::Cursor::new(data.to_vec())); + + let t = SimpleHttpTransport::builder() + .url("localhost:123").expect("parse url") + .auth("", None) + .build(); + + let client = Client::with_transport(t); + let request = client.build_request("uptime", &[]); + let _ = client.send_request(request); +} + +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + honggfuzz::fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(test)] +mod tests { + fn extend_vec_from_hex(hex: &str) -> Vec { + let mut out = vec![]; + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + out + } + + #[test] + fn duplicate_crash() { + super::do_test(&extend_vec_from_hex("00")); + } +} diff --git a/fuzz/travis-fuzz.sh b/fuzz/travis-fuzz.sh new file mode 100755 index 00000000..71bff44a --- /dev/null +++ b/fuzz/travis-fuzz.sh @@ -0,0 +1,40 @@ +#!/bin/bash +set -e + +# Check that input files are correct Windows file names +incorrectFilenames=$(find . -type f -name "*,*" -o -name "*:*" -o -name "*<*" -o -name "*>*" -o -name "*|*" -o -name "*\?*" -o -name "*\**" -o -name "*\"*" | wc -l) + +if [ ${incorrectFilenames} -gt 0 ]; then + echo 'Exiting early due to Windows-incompatible filenames in this tree. If this is happening' + echo 'to you on a local run, deleting the `hfuzz_workspace/` directory will probably fix it.' + exit 2 +fi + +if [ "$1" == "" ]; then + TARGETS=fuzz_targets/* +else + TARGETS=fuzz_targets/"$1".rs +fi + +cargo --version +rustc --version + +# Testing +cargo install --force honggfuzz --no-default-features +for TARGET in $TARGETS; do + echo "Fuzzing target $TARGET" + FILENAME=$(basename $TARGET) + FILE="${FILENAME%.*}" + if [ -d hfuzz_input/$FILE ]; then + HFUZZ_INPUT_ARGS="-f hfuzz_input/$FILE/input" + fi + HFUZZ_BUILD_ARGS="--features honggfuzz_fuzz" HFUZZ_RUN_ARGS="--run_time 30 --exit_upon_crash -v $HFUZZ_INPUT_ARGS" cargo hfuzz run $FILE + + if [ -f hfuzz_workspace/$FILE/HONGGFUZZ.REPORT.TXT ]; then + cat hfuzz_workspace/$FILE/HONGGFUZZ.REPORT.TXT + for CASE in hfuzz_workspace/$FILE/SIG*; do + cat $CASE | xxd -p -c1000 + done + exit 1 + fi +done diff --git a/src/simple_http.rs b/src/simple_http.rs index 83fa3438..93debf44 100644 --- a/src/simple_http.rs +++ b/src/simple_http.rs @@ -93,6 +93,9 @@ impl Default for SimpleHttpTransport { DEFAULT_PORT, ), path: "/".to_owned(), + #[cfg(fuzzing)] + timeout: Duration::from_millis(1), + #[cfg(not(fuzzing))] timeout: Duration::from_secs(15), basic_auth: None, #[cfg(feature = "proxy")]