Add hfuzz into repo (#103)

* Add fuzzing against spec interpreter.

* Redirect output of spec to /dev/null

* Also stderr

* Refactor

* Oops. Revert to temp file creation.

* Version of libfuzzer pinned

* Add honggfuzz.

* Impl hfuzz

* Update parity-wasm.

* Update honggfuzz to 0.5.9.

* Update parity-wasm

* Stack hash.

* Update script a bit.

* Unpin parity-wasm version

* Indentation
This commit is contained in:
Sergey Pepyakin 2018-06-25 17:46:13 +03:00 committed by GitHub
parent 9db7896e48
commit 2fb793c8b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 150 additions and 0 deletions

View File

@ -12,9 +12,11 @@ cargo-fuzz = true
wasmi = { path = ".." }
wabt = "0.2.0"
wasmparser = "0.14.1"
tempdir = "0.3.6"
[dependencies.libfuzzer-sys]
git = "https://github.com/rust-fuzz/libfuzzer-sys.git"
rev = "737524f7de1e85342b8b6cd1c01edc71018183ba"
# Prevent this from interfering with workspaces
[workspace]
@ -31,3 +33,7 @@ path = "fuzz_targets/load_wabt.rs"
[[bin]]
name = "load_wasmparser"
path = "fuzz_targets/load_wasmparser.rs"
[[bin]]
name = "load_spec"
path = "fuzz_targets/load_spec.rs"

View File

@ -0,0 +1,53 @@
#![no_main]
#[macro_use]
extern crate libfuzzer_sys;
extern crate wabt;
extern crate wasmi;
extern crate tempdir;
use std::fs::File;
use std::io::Write;
use std::process::{Command, Stdio};
fn run_spec(data: &[u8]) -> Result<(), ()> {
let temp_dir = tempdir::TempDir::new("spec").unwrap();
let mut seed_path = temp_dir.path().to_path_buf();
seed_path.push("test.wasm");
{
let mut seedfile =
File::create(&seed_path).expect("open temporary file for writing to store fuzzer input");
seedfile.write_all(data).expect(
"write fuzzer input to temporary file",
);
seedfile.flush().expect(
"flush fuzzer input to temporary file before starting wasm-opt",
);
}
let exit_status = Command::new("wasm")
.arg("-d")
.arg(&seed_path)
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.expect("failed to execute `wasm`");
if exit_status.success() {
Ok(())
} else {
Err(())
}
}
fn run_wasmi(data: &[u8]) -> Result<(), ()> {
let _ = wasmi::Module::from_buffer(data).map_err(|_| ())?;
Ok(())
}
fuzz_target!(|data: &[u8]| {
let wasmi_result = run_wasmi(data);
let wasm_result = run_spec(data);
assert_eq!(wasmi_result.is_ok(), wasm_result.is_ok());
});

2
hfuzz/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
hfuzz_workspace/
hfuzz_target/

10
hfuzz/Cargo.toml Normal file
View File

@ -0,0 +1,10 @@
[package]
name = "hfuzz"
version = "0.1.0"
authors = ["Sergey Pepyakin <s.pepyakin@gmail.com>"]
[dependencies]
honggfuzz = "=0.5.9" # Strict equal since hfuzz requires dep and cmd versions to match.
wasmi = { path = ".." }
tempdir = "0.3.6"
wabt = "0.2.0"

70
hfuzz/src/main.rs Normal file
View File

@ -0,0 +1,70 @@
#[macro_use] extern crate honggfuzz;
extern crate wabt;
extern crate wasmi;
extern crate tempdir;
use std::fs::File;
use std::io::Write;
use std::process::{Command, Stdio};
fn dump_all_into_buf(src: &[u8], buf: &mut [u8; 64]) {
let common_len = usize::min(src.len(), buf.len());
buf[0..common_len].copy_from_slice(&src[0..common_len]);
}
fn run_spec(data: &[u8], stdout_msg_buf: &mut [u8; 64], stderr_msg_buf: &mut [u8; 64]) -> Result<(), ()> {
let temp_dir = tempdir::TempDir::new("spec").unwrap();
let mut seed_path = temp_dir.path().to_path_buf();
seed_path.push("test.wasm");
{
let mut seedfile =
File::create(&seed_path).expect("open temporary file for writing to store fuzzer input");
seedfile.write_all(data).expect(
"write fuzzer input to temporary file",
);
seedfile.flush().expect(
"flush fuzzer input to temporary file before starting wasm-opt",
);
}
let output = Command::new("wasm")
.arg("-d")
.arg(&seed_path)
.stdout(Stdio::null())
.stderr(Stdio::null())
.output()
.expect("failed to execute `wasm`");
if output.status.success() {
Ok(())
} else {
dump_all_into_buf(&output.stdout, stdout_msg_buf);
dump_all_into_buf(&output.stderr, stderr_msg_buf);
Err(())
}
}
fn run_wasmi(data: &[u8]) -> Result<(), ()> {
let _ = wasmi::Module::from_buffer(data).map_err(|_| ())?;
Ok(())
}
fn main() {
loop {
fuzz!(|data: &[u8]| {
// Keep messages on stack. This should lead to a different stack hashes for
// different error messages.
let mut stdout_msg_buf: [u8; 64] = [0; 64];
let mut stderr_msg_buf: [u8; 64] = [0; 64];
let wasmi_result = run_wasmi(data);
let wasm_result = run_spec(data, &mut stdout_msg_buf, &mut stderr_msg_buf);
if wasmi_result.is_ok() != wasm_result.is_ok() {
panic!("stdout: {:?}, stderr: {:?}", &stdout_msg_buf[..], &stderr_msg_buf as &[u8]);
}
});
}
}

9
hfuzz/test.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/bash
export HFUZZ_RUN_ARGS="--max_file_size 2048"
die() { echo "$*"; exit 1; }
command -v wasm || die "spec interpreter 'wasm' is not on PATH";
rustup run nightly cargo hfuzz run hfuzz