diff --git a/crates/fuzzing/src/oracles.rs b/crates/fuzzing/src/oracles.rs index 38f355c36f..7d07117c8b 100644 --- a/crates/fuzzing/src/oracles.rs +++ b/crates/fuzzing/src/oracles.rs @@ -16,6 +16,7 @@ use crate::generators; use arbitrary::Arbitrary; use log::debug; use std::cell::Cell; +use std::convert::TryInto; use std::rc::Rc; use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; use std::sync::{Arc, Condvar, Mutex}; @@ -843,7 +844,14 @@ pub fn differential_spec_execution(wasm: &[u8], config: &generators::Config) -> (wasm_spec_interpreter::Value::F64(a), wasmtime::Val::F64(b)) => { f64_equal(*a as u64, *b) } - (_, _) => unreachable!("fuzzing non-scalar value types is still TODO"), + (wasm_spec_interpreter::Value::V128(a), wasmtime::Val::V128(b)) => { + assert_eq!(a.len(), 16); + let a_num = u128::from_le_bytes(a.as_slice().try_into().unwrap()); + a_num == *b + } + (_, _) => { + unreachable!("TODO: only fuzzing of scalar and vector value types is supported") + } } } diff --git a/crates/fuzzing/wasm-spec-interpreter/build.rs b/crates/fuzzing/wasm-spec-interpreter/build.rs index 61d5986c70..472ec0165c 100644 --- a/crates/fuzzing/wasm-spec-interpreter/build.rs +++ b/crates/fuzzing/wasm-spec-interpreter/build.rs @@ -12,7 +12,7 @@ const OCAML_DIR: &'static str = "ocaml"; const SPEC_DIR: &'static str = "ocaml/spec"; const SPEC_REPOSITORY: &'static str = "https://github.com/conrad-watt/spec"; const SPEC_REPOSITORY_BRANCH: &'static str = "wasmtime_fuzzing"; -const SPEC_REPOSITORY_REV: &'static str = "7485eb0084b74871f96f261b9f916864596d8f1d"; +const SPEC_REPOSITORY_REV: &'static str = "52851c8394ee4099fb8bdeaec6d60d92e787052f"; fn main() { if cfg!(feature = "build-libinterpret") { diff --git a/crates/fuzzing/wasm-spec-interpreter/ocaml/README.md b/crates/fuzzing/wasm-spec-interpreter/ocaml/README.md index 21cfb7c373..58888d97e4 100644 --- a/crates/fuzzing/wasm-spec-interpreter/ocaml/README.md +++ b/crates/fuzzing/wasm-spec-interpreter/ocaml/README.md @@ -1,7 +1,7 @@ This directory contains the necessary parts for building a library with FFI access to the Wasm spec interpreter. Its major parts: - `spec`: the Wasm spec code as a Git submodule (you may need to retrieve it: - `git clone https://github.com/conrad-watt/spec/tree/wasmtime_fuzzing). + `git clone -b wasmtime_fuzzing https://github.com/conrad-watt/spec`). - `interpret.ml`: a shim layer for calling the Wasm spec code and exposing it for FFI access - `Makefile`: the steps for gluing these pieces together into a static library diff --git a/crates/fuzzing/wasm-spec-interpreter/ocaml/interpret.ml b/crates/fuzzing/wasm-spec-interpreter/ocaml/interpret.ml index cda7ea2032..04098607e2 100644 --- a/crates/fuzzing/wasm-spec-interpreter/ocaml/interpret.ml +++ b/crates/fuzzing/wasm-spec-interpreter/ocaml/interpret.ml @@ -16,20 +16,23 @@ type ffi_value = | I64 of int64 | F32 of int32 | F64 of int64 + | V128 of Bytes.t (** Helper for converting the FFI values to their spec interpreter type. *) let convert_to_wasm (v: ffi_value) : v = match v with -| I32 n -> ConstInt32 (I32_impl_abs n) -| I64 n -> ConstInt64 (I64_impl_abs n) -| F32 n -> ConstFloat32 (F32.of_bits n) -| F64 n -> ConstFloat64 (F64.of_bits n) +| I32 n -> V_num (ConstInt32 (I32_impl_abs n)) +| I64 n -> V_num (ConstInt64 (I64_impl_abs n)) +| F32 n -> V_num (ConstFloat32 (F32.of_bits n)) +| F64 n -> V_num (ConstFloat64 (F64.of_bits n)) +| V128 n -> V_vec (ConstVec128 (V128.of_bits (Bytes.to_string n))) (** Helper for converting the spec interpreter values to their FFI type. *) let convert_from_wasm (v: v) : ffi_value = match v with -| (ConstInt32 (I32_impl_abs n)) -> I32 n -| (ConstInt64 (I64_impl_abs n)) -> I64 n -| (ConstFloat32 n) -> F32 (F32.to_bits n) -| (ConstFloat64 n) -> F64 (F64.to_bits n) +| V_num ((ConstInt32 (I32_impl_abs n))) -> I32 n +| V_num ((ConstInt64 (I64_impl_abs n))) -> I64 n +| V_num ((ConstFloat32 n)) -> F32 (F32.to_bits n) +| V_num ((ConstFloat64 n)) -> F64 (F64.to_bits n) +| V_vec ((ConstVec128 n)) -> V128 (Bytes.of_string (V128.to_bits n)) | _ -> failwith "Unknown type" (** Parse the given WebAssembly module binary into an Ast.module_. At some point in the future this diff --git a/crates/fuzzing/wasm-spec-interpreter/src/lib.rs b/crates/fuzzing/wasm-spec-interpreter/src/lib.rs index a2f46a3a9a..6a977f7f50 100644 --- a/crates/fuzzing/wasm-spec-interpreter/src/lib.rs +++ b/crates/fuzzing/wasm-spec-interpreter/src/lib.rs @@ -16,6 +16,7 @@ pub enum Value { I64(i64), F32(i32), F64(i64), + V128(Vec), } #[cfg(feature = "has-libinterpret")] diff --git a/crates/fuzzing/wasm-spec-interpreter/src/with_library.rs b/crates/fuzzing/wasm-spec-interpreter/src/with_library.rs index 9dadce4866..81806f61b3 100644 --- a/crates/fuzzing/wasm-spec-interpreter/src/with_library.rs +++ b/crates/fuzzing/wasm-spec-interpreter/src/with_library.rs @@ -59,6 +59,7 @@ mod ocaml_bindings { Value::I64(i: OCamlInt64), Value::F32(i: OCamlInt32), Value::F64(i: OCamlInt64), + Value::V128(i: OCamlBytes), } } @@ -103,4 +104,21 @@ mod tests { Err("Error(_, \"(Isabelle) trap: load\")".to_string()) ); } + + #[test] + fn simd_not() { + let module = wat::parse_file("tests/simd_not.wat").unwrap(); + + let parameters = Some(vec![Value::V128(vec![ + 0, 255, 0, 0, 255, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + ])]); + let results = interpret(&module, parameters.clone()).unwrap(); + + assert_eq!( + results, + vec![Value::V128(vec![ + 255, 0, 255, 255, 0, 255, 255, 255, 255, 0, 255, 255, 255, 255, 255, 255 + ])] + ); + } } diff --git a/crates/fuzzing/wasm-spec-interpreter/tests/simd_not.wat b/crates/fuzzing/wasm-spec-interpreter/tests/simd_not.wat new file mode 100644 index 0000000000..6ea48fa14d --- /dev/null +++ b/crates/fuzzing/wasm-spec-interpreter/tests/simd_not.wat @@ -0,0 +1,4 @@ +(module + (func (export "simd_not") (param $a v128) (result v128) + local.get $a + v128.not)) diff --git a/fuzz/fuzz_targets/differential_spec.rs b/fuzz/fuzz_targets/differential_spec.rs index 6ed13ff16c..1b9fe39c3d 100644 --- a/fuzz/fuzz_targets/differential_spec.rs +++ b/fuzz/fuzz_targets/differential_spec.rs @@ -23,6 +23,7 @@ fn run(data: &[u8]) -> Result<()> { // Enable features that the spec interpreter has implemented config.module_config.config.multi_value_enabled = false; + config.module_config.config.simd_enabled = true; // TODO: this is a best-effort attempt to avoid errors caused by the // generated module exporting no functions.