Add fuzz test for server::accept

This commit is contained in:
Wonwoo Choi 2020-03-08 18:29:28 +09:00
parent 90e9717750
commit 4be89d503f
8 changed files with 149 additions and 0 deletions

4
fuzz/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
target
corpus
artifacts

27
fuzz/Cargo.toml Normal file
View File

@ -0,0 +1,27 @@
[package]
name = "async-h1-fuzz"
version = "0.0.0"
authors = ["Automatically generated"]
publish = false
edition = "2018"
[package.metadata]
cargo-fuzz = true
[dependencies]
async-std = "1.5.0"
http-types = "1.0.0"
libfuzzer-sys = "0.3"
futures-io = "0.3"
[dependencies.async-h1]
path = ".."
# Prevent this from interfering with workspaces
[workspace]
members = ["."]
[[bin]]
name = "server_accept"
path = "fuzz_targets/server_accept.rs"

30
fuzz/dicts/server_accept Normal file
View File

@ -0,0 +1,30 @@
"HTTP/1.1"
"GET"
"POST"
"PUT"
"DELETE"
"PATCH"
"OPTIONS"
"CONNECT"
"HEAD"
" /"
"index.html"
"?q="
"content-type"
"transfer-encoding"
"chunked"
"text/plain"
"application/octet-stream"
"application/json"
"image/png"
"audio/opus"
"authorization"
"cookie"
"content-length"
"host"
"Basic"
"accept-encoding"
"gzip"
"br"
"\x0d\x0a"
": "

View File

@ -0,0 +1,56 @@
#![no_main]
use libfuzzer_sys::fuzz_target;
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use std::task::{Context, Poll};
use async_std::io::Cursor;
use futures_io::{AsyncRead, AsyncWrite};
#[derive(Clone, Debug)]
struct RwWrapper(Arc<Mutex<Cursor<Vec<u8>>>>);
impl RwWrapper {
fn new(input: Vec<u8>) -> Self {
Self(Arc::new(Mutex::new(Cursor::new(input))))
}
}
impl AsyncRead for RwWrapper {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<std::io::Result<usize>> {
Pin::new(&mut *self.0.lock().unwrap()).poll_read(cx, buf)
}
}
impl AsyncWrite for RwWrapper {
fn poll_write(
self: Pin<&mut Self>,
_cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<std::io::Result<usize>> {
Poll::Ready(Ok(buf.len()))
}
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
Poll::Ready(Ok(()))
}
fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
Poll::Ready(Ok(()))
}
}
fuzz_target!(|request: &[u8]| {
let stream = RwWrapper::new(request.to_vec());
async_std::task::block_on(async_h1::accept("http://localhost", stream, |req| async {
let mut res = http_types::Response::new(http_types::StatusCode::Ok);
res.set_body(req);
Ok(res)
}))
.ok();
});

View File

@ -0,0 +1,10 @@
POST / HTTP/1.1
content-type: text/plain
transfer-encoding: chunked
5
Hello
a
aaaaabbbbb
0

View File

@ -0,0 +1,5 @@
POST / HTTP/1.1
content-type: text/plain
content-length: 10
aaaaabbbbb

View File

@ -0,0 +1,3 @@
POST / HTTP/1.1
content-length: 0

14
run-fuzzer.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/sh
set -e
TARGET_NAME="$1"
if [ -z "$TARGET_NAME" ]; then
echo "$0: target name required" >&2
exit 1
fi
mkdir -p "./fuzz/corpus/${TARGET_NAME}/"
cargo +nightly fuzz run "${TARGET_NAME}" \
"./fuzz/corpus/${TARGET_NAME}/" "./fuzz/init_corpus/${TARGET_NAME}/" -- \
-dict="./fuzz/dicts/${TARGET_NAME}" \
-timeout=3