Browse Source

Fix build of fact-valid-module fuzzer (#8418)

Closes #8413
pull/8444/head
Alex Crichton 7 months ago
committed by GitHub
parent
commit
57827a3cb1
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      .github/workflows/main.yml
  2. 6
      crates/environ/fuzz/Cargo.toml
  3. 98
      crates/environ/fuzz/fuzz_targets/fact-valid-module.rs

1
.github/workflows/main.yml

@ -464,6 +464,7 @@ jobs:
working-directory: ./fuzz working-directory: ./fuzz
- run: cargo fuzz build --dev -s none - run: cargo fuzz build --dev -s none
- run: cargo fuzz build --dev -s none --fuzz-dir ./cranelift/isle/fuzz - run: cargo fuzz build --dev -s none --fuzz-dir ./cranelift/isle/fuzz
- run: cargo fuzz build --dev -s none --fuzz-dir ./crates/environ/fuzz --features component-model
# Verify the "min platform" example still works. # Verify the "min platform" example still works.
# #

6
crates/environ/fuzz/Cargo.toml

@ -26,4 +26,8 @@ doc = false
required-features = ["component-model"] required-features = ["component-model"]
[features] [features]
component-model = ["wasmtime-environ/component-model", "dep:component-fuzz-util"] component-model = [
"wasmtime-environ/component-model",
"wasmtime-environ/compile",
"dep:component-fuzz-util",
]

98
crates/environ/fuzz/fuzz_targets/fact-valid-module.rs

@ -9,35 +9,79 @@
#![no_main] #![no_main]
use arbitrary::Arbitrary; use arbitrary::Unstructured;
use component_fuzz_util::TestCase; use component_fuzz_util::{TestCase, Type, MAX_TYPE_DEPTH};
use libfuzzer_sys::fuzz_target; use libfuzzer_sys::fuzz_target;
use wasmparser::types::ComponentAnyTypeId;
use wasmparser::{Parser, Payload, Validator, WasmFeatures}; use wasmparser::{Parser, Payload, Validator, WasmFeatures};
use wasmtime_environ::component::*; use wasmtime_environ::component::*;
use wasmtime_environ::fact::Module; use wasmtime_environ::fact::Module;
#[derive(Arbitrary, Debug)] const TYPE_COUNT: usize = 50;
struct GenAdapterModule { const MAX_ARITY: u32 = 5;
const TEST_CASE_COUNT: usize = 20;
#[derive(Debug)]
struct GenAdapterModule<'a> {
debug: bool, debug: bool,
adapters: Vec<GenAdapter>, adapters: Vec<GenAdapter<'a>>,
} }
#[derive(Arbitrary, Debug)] #[derive(Debug)]
struct GenAdapter { struct GenAdapter<'a> {
post_return: bool, post_return: bool,
lift_memory64: bool, lift_memory64: bool,
lower_memory64: bool, lower_memory64: bool,
test: TestCase, test: TestCase<'a>,
} }
fuzz_target!(|module: GenAdapterModule| { fuzz_target!(|data: &[u8]| {
target(module); let _ = target(data);
}); });
fn target(module: GenAdapterModule) { fn target(data: &[u8]) -> arbitrary::Result<()> {
drop(env_logger::try_init()); drop(env_logger::try_init());
let mut types = ComponentTypesBuilder::default(); let mut u = Unstructured::new(data);
// First generate a set of type to select from.
let mut type_fuel = 1000;
let mut types = Vec::new();
for _ in 0..u.int_in_range(1..=TYPE_COUNT)? {
// Only discount fuel if the generation was successful,
// otherwise we'll get more random data and try again.
types.push(Type::generate(&mut u, MAX_TYPE_DEPTH, &mut type_fuel)?);
}
// Next generate a set of static API test cases driven by the above
// types.
let mut ret = GenAdapterModule {
debug: u.arbitrary()?,
adapters: Vec::new(),
};
for _ in 0..u.int_in_range(1..=TEST_CASE_COUNT)? {
let mut params = Vec::new();
let mut results = Vec::new();
for _ in 0..u.int_in_range(0..=MAX_ARITY)? {
params.push(u.choose(&types)?);
}
for _ in 0..u.int_in_range(0..=MAX_ARITY)? {
results.push(u.choose(&types)?);
}
let test = TestCase {
params,
results,
encoding1: u.arbitrary()?,
encoding2: u.arbitrary()?,
};
ret.adapters.push(GenAdapter {
test,
post_return: u.arbitrary()?,
lift_memory64: u.arbitrary()?,
lower_memory64: u.arbitrary()?,
});
}
// Manufactures a unique `CoreDef` so all function imports get unique // Manufactures a unique `CoreDef` so all function imports get unique
// function imports. // function imports.
@ -72,9 +116,11 @@ fn target(module: GenAdapterModule) {
item: ExportItem::Name(String::new()), item: ExportItem::Name(String::new()),
} }
}; };
let mut validator = Validator::new();
let mut types = ComponentTypesBuilder::new(&validator);
let mut adapters = Vec::new(); let mut adapters = Vec::new();
for adapter in module.adapters.iter() { for adapter in ret.adapters.iter() {
let wat_decls = adapter.test.declarations(); let wat_decls = adapter.test.declarations();
let wat = format!( let wat = format!(
"(component "(component
@ -87,9 +133,7 @@ fn target(module: GenAdapterModule) {
); );
let wasm = wat::parse_str(&wat).unwrap(); let wasm = wat::parse_str(&wat).unwrap();
let mut validator = Validator::new(); let mut type_index = 0;
types.push_type_scope();
for payload in Parser::new(0).parse_all(&wasm) { for payload in Parser::new(0).parse_all(&wasm) {
let payload = payload.unwrap(); let payload = payload.unwrap();
validator.payload(&payload).unwrap(); validator.payload(&payload).unwrap();
@ -97,13 +141,17 @@ fn target(module: GenAdapterModule) {
Payload::ComponentTypeSection(s) => s, Payload::ComponentTypeSection(s) => s,
_ => continue, _ => continue,
}; };
for ty in section { for _ in section {
let ty = types.intern_component_type(&ty.unwrap()).unwrap(); let validator_types = validator.types(0).unwrap();
types.push_component_typedef(ty); let id = validator_types.component_any_type_at(type_index);
let ty = match ty { type_index += 1;
TypeDef::ComponentFunc(ty) => ty, let id = match id {
ComponentAnyTypeId::Func(id) => id,
_ => continue, _ => continue,
}; };
let ty = types
.convert_component_func_type(validator_types, id)
.unwrap();
adapters.push(Adapter { adapters.push(Adapter {
lift_ty: ty, lift_ty: ty,
lower_ty: ty, lower_ty: ty,
@ -137,10 +185,10 @@ fn target(module: GenAdapterModule) {
}); });
} }
} }
types.pop_type_scope(); validator.reset();
} }
let mut fact_module = Module::new(&types, module.debug); let mut fact_module = Module::new(&types, ret.debug);
for (i, adapter) in adapters.iter().enumerate() { for (i, adapter) in adapters.iter().enumerate() {
fact_module.adapt(&format!("adapter{i}"), adapter); fact_module.adapt(&format!("adapter{i}"), adapter);
} }
@ -149,11 +197,11 @@ fn target(module: GenAdapterModule) {
.validate_all(&wasm); .validate_all(&wasm);
let err = match result { let err = match result {
Ok(_) => return, Ok(_) => return Ok(()),
Err(e) => e, Err(e) => e,
}; };
eprintln!("invalid wasm module: {err:?}"); eprintln!("invalid wasm module: {err:?}");
for adapter in module.adapters.iter() { for adapter in ret.adapters.iter() {
eprintln!("adapter: {adapter:?}"); eprintln!("adapter: {adapter:?}");
} }
std::fs::write("invalid.wasm", &wasm).unwrap(); std::fs::write("invalid.wasm", &wasm).unwrap();

Loading…
Cancel
Save