parent
b2967e0b84
commit
213edc11e7
|
@ -11,11 +11,11 @@ cargo-fuzz = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libfuzzer-sys = "0.4"
|
libfuzzer-sys = "0.4"
|
||||||
wasm-smith = "0.8"
|
wasm-smith = "0.202.0"
|
||||||
env_logger = "0.9"
|
env_logger = "0.9"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
wasmparser = "0.95"
|
wasmparser = "0.202.0"
|
||||||
wasmtime = "7.0"
|
wasmtime = "19.0"
|
||||||
|
|
||||||
[dependencies.waffle]
|
[dependencies.waffle]
|
||||||
path = ".."
|
path = ".."
|
||||||
|
|
|
@ -4,12 +4,12 @@ use std::sync::atomic::{AtomicU64, Ordering};
|
||||||
|
|
||||||
use waffle::{FrontendOptions, Module};
|
use waffle::{FrontendOptions, Module};
|
||||||
|
|
||||||
fuzz_target!(
|
fuzz_target!(|module: waffle::fuzzing::ArbitraryModule| {
|
||||||
|module: wasm_smith::ConfiguredModule<waffle::fuzzing::Config>| {
|
let module = module.0;
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
log::debug!("original module: {:?}", module.module);
|
log::debug!("original module: {:?}", module);
|
||||||
|
|
||||||
let orig_bytes = module.module.to_bytes();
|
let orig_bytes = module.to_bytes();
|
||||||
|
|
||||||
if waffle::fuzzing::reject(&orig_bytes[..]) {
|
if waffle::fuzzing::reject(&orig_bytes[..]) {
|
||||||
log::debug!("Discarding fuzz run. Body:\n{:?}", module);
|
log::debug!("Discarding fuzz run. Body:\n{:?}", module);
|
||||||
|
@ -24,8 +24,7 @@ fuzz_target!(
|
||||||
let orig_module =
|
let orig_module =
|
||||||
wasmtime::Module::new(&engine, &orig_bytes[..]).expect("failed to parse original wasm");
|
wasmtime::Module::new(&engine, &orig_bytes[..]).expect("failed to parse original wasm");
|
||||||
let mut orig_store = wasmtime::Store::new(&engine, ());
|
let mut orig_store = wasmtime::Store::new(&engine, ());
|
||||||
orig_store.out_of_fuel_trap();
|
orig_store.set_fuel(10000).unwrap();
|
||||||
orig_store.add_fuel(10000).unwrap();
|
|
||||||
let orig_instance = wasmtime::Instance::new(&mut orig_store, &orig_module, &[]);
|
let orig_instance = wasmtime::Instance::new(&mut orig_store, &orig_module, &[]);
|
||||||
let orig_instance = match orig_instance {
|
let orig_instance = match orig_instance {
|
||||||
Ok(orig_instance) => orig_instance,
|
Ok(orig_instance) => orig_instance,
|
||||||
|
@ -51,13 +50,11 @@ fuzz_target!(
|
||||||
let roundtrip_module = wasmtime::Module::new(&engine, &roundtrip_bytes[..])
|
let roundtrip_module = wasmtime::Module::new(&engine, &roundtrip_bytes[..])
|
||||||
.expect("failed to parse roundtripped wasm");
|
.expect("failed to parse roundtripped wasm");
|
||||||
let mut roundtrip_store = wasmtime::Store::new(&engine, ());
|
let mut roundtrip_store = wasmtime::Store::new(&engine, ());
|
||||||
roundtrip_store.out_of_fuel_trap();
|
|
||||||
// After roundtrip, fuel consumption rate may differ. That's fine;
|
// After roundtrip, fuel consumption rate may differ. That's fine;
|
||||||
// what matters is that it terminated above without a trap (hence
|
// what matters is that it terminated above without a trap (hence
|
||||||
// halts in a reasonable time).
|
// halts in a reasonable time).
|
||||||
roundtrip_store.add_fuel(u64::MAX).unwrap();
|
roundtrip_store.set_fuel(u64::MAX).unwrap();
|
||||||
let roundtrip_instance =
|
let roundtrip_instance = wasmtime::Instance::new(&mut roundtrip_store, &roundtrip_module, &[])
|
||||||
wasmtime::Instance::new(&mut roundtrip_store, &roundtrip_module, &[])
|
|
||||||
.expect("cannot instantiate roundtripped wasm");
|
.expect("cannot instantiate roundtripped wasm");
|
||||||
|
|
||||||
// Ensure exports are equal.
|
// Ensure exports are equal.
|
||||||
|
@ -110,8 +107,7 @@ fuzz_target!(
|
||||||
}
|
}
|
||||||
|
|
||||||
success(total);
|
success(total);
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
static TOTAL: AtomicU64 = AtomicU64::new(0);
|
static TOTAL: AtomicU64 = AtomicU64::new(0);
|
||||||
static SUCCESS: AtomicU64 = AtomicU64::new(0);
|
static SUCCESS: AtomicU64 = AtomicU64::new(0);
|
||||||
|
|
|
@ -3,12 +3,12 @@ use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
use waffle::{FrontendOptions, InterpContext, InterpResult, Module};
|
use waffle::{FrontendOptions, InterpContext, InterpResult, Module};
|
||||||
|
|
||||||
fuzz_target!(
|
fuzz_target!(|module: waffle::fuzzing::ArbitraryModule| {
|
||||||
|module: wasm_smith::ConfiguredModule<waffle::fuzzing::Config>| {
|
let module = module.0;
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
log::debug!("original module: {:?}", module.module);
|
log::debug!("original module: {:?}", module);
|
||||||
|
|
||||||
let orig_bytes = module.module.to_bytes();
|
let orig_bytes = module.to_bytes();
|
||||||
|
|
||||||
if waffle::fuzzing::reject(&orig_bytes[..]) {
|
if waffle::fuzzing::reject(&orig_bytes[..]) {
|
||||||
log::debug!("Discarding fuzz run. Body:\n{:?}", module);
|
log::debug!("Discarding fuzz run. Body:\n{:?}", module);
|
||||||
|
@ -64,5 +64,4 @@ fuzz_target!(
|
||||||
|
|
||||||
assert_eq!(orig_ctx.memories, opt_ctx.memories);
|
assert_eq!(orig_ctx.memories, opt_ctx.memories);
|
||||||
assert_eq!(orig_ctx.globals, opt_ctx.globals);
|
assert_eq!(orig_ctx.globals, opt_ctx.globals);
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
|
@ -23,10 +23,10 @@ pub fn reject(bytes: &[u8]) -> bool {
|
||||||
wasmparser::Payload::StartSection { .. } => {
|
wasmparser::Payload::StartSection { .. } => {
|
||||||
has_start = true;
|
has_start = true;
|
||||||
}
|
}
|
||||||
wasmparser::Payload::ExportSection(mut reader) => {
|
wasmparser::Payload::ExportSection(reader) => {
|
||||||
for _ in 0..reader.get_count() {
|
for export in reader {
|
||||||
let e = reader.read().unwrap();
|
let export = export.unwrap();
|
||||||
match &e.kind {
|
match &export.kind {
|
||||||
&wasmparser::ExternalKind::Global => {
|
&wasmparser::ExternalKind::Global => {
|
||||||
num_globals += 1;
|
num_globals += 1;
|
||||||
}
|
}
|
||||||
|
@ -34,10 +34,10 @@ pub fn reject(bytes: &[u8]) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wasmparser::Payload::MemorySection(mut reader) => {
|
wasmparser::Payload::MemorySection(reader) => {
|
||||||
for _ in 0..reader.get_count() {
|
for mem in reader {
|
||||||
let m = reader.read().unwrap();
|
let mem = mem.unwrap();
|
||||||
if m.maximum.is_none() || m.maximum.unwrap() > 100 {
|
if mem.maximum.is_none() || mem.maximum.unwrap() > 100 {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,59 +53,32 @@ pub fn reject(bytes: &[u8]) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fuzzing_config() -> wasm_smith::Config {
|
||||||
|
wasm_smith::Config {
|
||||||
|
min_funcs: 1,
|
||||||
|
max_funcs: 1,
|
||||||
|
min_memories: 1,
|
||||||
|
max_memories: 1,
|
||||||
|
min_globals: 10,
|
||||||
|
max_globals: 10,
|
||||||
|
min_tables: 0,
|
||||||
|
max_tables: 0,
|
||||||
|
min_imports: 0,
|
||||||
|
max_imports: 0,
|
||||||
|
min_exports: 12,
|
||||||
|
max_exports: 12,
|
||||||
|
allow_start_export: true,
|
||||||
|
canonicalize_nans: true,
|
||||||
|
max_memory32_pages: 1,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Config;
|
pub struct ArbitraryModule(pub wasm_smith::Module);
|
||||||
|
|
||||||
impl<'a> arbitrary::Arbitrary<'a> for Config {
|
impl<'a> arbitrary::Arbitrary<'a> for ArbitraryModule {
|
||||||
fn arbitrary(_u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
|
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
|
||||||
Ok(Config)
|
Ok(Self(wasm_smith::Module::new(fuzzing_config(), u)?))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl wasm_smith::Config for Config {
|
|
||||||
fn min_funcs(&self) -> usize {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
fn max_funcs(&self) -> usize {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
fn min_memories(&self) -> u32 {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
fn max_memories(&self) -> usize {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
fn min_globals(&self) -> usize {
|
|
||||||
10
|
|
||||||
}
|
|
||||||
fn max_globals(&self) -> usize {
|
|
||||||
10
|
|
||||||
}
|
|
||||||
fn min_tables(&self) -> u32 {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
fn max_tables(&self) -> usize {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
fn min_imports(&self) -> usize {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
fn max_imports(&self) -> usize {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
fn min_exports(&self) -> usize {
|
|
||||||
12
|
|
||||||
}
|
|
||||||
fn max_exports(&self) -> usize {
|
|
||||||
12
|
|
||||||
}
|
|
||||||
fn allow_start_export(&self) -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
fn canonicalize_nans(&self) -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
fn max_memory_pages(&self, _is_64: bool) -> u64 {
|
|
||||||
1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue