diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 01fe4517846..d4f00323247 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -23,15 +23,13 @@ path = "../lib/compiler-singlepass" path = "../lib/engine-jit" [dependencies.wasmer-engine-native] path = "../lib/engine-native" +[dependencies.wasmer-middlewares] +path = "../lib/middlewares" # Prevent this from interfering with workspaces [workspace] members = ["."] -[[bin]] -name = "validate" -path = "fuzz_targets/validate.rs" - [[bin]] name = "jit_cranelift" path = "fuzz_targets/jit_cranelift.rs" @@ -44,6 +42,14 @@ path = "fuzz_targets/jit_llvm.rs" name = "jit_singlepass" path = "fuzz_targets/jit_singlepass.rs" +[[bin]] +name = "metering" +path = "fuzz_targets/metering.rs" + [[bin]] name = "native_cranelift" path = "fuzz_targets/native_cranelift.rs" + +[[bin]] +name = "validate" +path = "fuzz_targets/validate.rs" diff --git a/fuzz/fuzz_targets/metering.rs b/fuzz/fuzz_targets/metering.rs new file mode 100644 index 00000000000..80b04d1a877 --- /dev/null +++ b/fuzz/fuzz_targets/metering.rs @@ -0,0 +1,58 @@ +#![no_main] + +use libfuzzer_sys::{arbitrary, arbitrary::Arbitrary, fuzz_target}; +use std::sync::Arc; +use wasm_smith::{Config, ConfiguredModule}; +use wasmer::{imports, CompilerConfig, Instance, Module, Store}; +use wasmer::wasmparser::Operator; +use wasmer_compiler_cranelift::Cranelift; +use wasmer_engine_jit::JIT; +use wasmer_middlewares::Metering; + +#[derive(Arbitrary, Debug, Default, Copy, Clone)] +struct NoImportsConfig; +impl Config for NoImportsConfig { + fn max_imports(&self) -> usize { + 0 + } + fn max_memory_pages(&self) -> u32 { + // https://github.com/wasmerio/wasmer/issues/2187 + 65535 + } + fn allow_start_export(&self) -> bool { + false + } +} + +fn cost(operator: &Operator) -> u64 { + match operator { + Operator::LocalGet { .. } | Operator::I32Const { .. } => 1, + Operator::I32Add { .. } => 2, + _ => 0, + } +} + +fuzz_target!(|module: ConfiguredModule| { + let wasm_bytes = module.to_bytes(); + let mut compiler = Cranelift::default(); + compiler.canonicalize_nans(true); + compiler.enable_verifier(); + let metering = Arc::new(Metering::new(10, cost)); + compiler.push_middleware(metering); + let store = Store::new(&JIT::new(compiler).engine()); + let module = Module::new(&store, &wasm_bytes).unwrap(); + match Instance::new(&module, &imports! {}) { + Ok(_) => {} + Err(e) => { + let error_message = format!("{}", e); + if error_message + .contains("RuntimeError: memory out of bounds: data segment does not fit") + || error_message + .contains("RuntimeError: table out of bounds: elements segment does not fit") + { + return; + } + panic!("{}", e); + } + } +});