Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/environ/fuzz/fuzz_targets/fact-valid-module.rs
1693 views
1
//! A simple fuzzer for FACT
2
//!
3
//! This is an intentionally small fuzzer which is intended to only really be
4
//! used during the development of FACT itself when generating adapter modules.
5
//! This creates arbitrary adapter signatures and then generates the required
6
//! trampoline for that adapter ensuring that the final output wasm module is a
7
//! valid wasm module. This doesn't actually validate anything about the
8
//! correctness of the trampoline, only that it's valid wasm.
9
10
#![no_main]
11
12
use arbitrary::Unstructured;
13
use libfuzzer_sys::fuzz_target;
14
use wasmtime_environ::{ScopeVec, Tunables, component::*};
15
use wasmtime_test_util::component_fuzz::{MAX_TYPE_DEPTH, TestCase, Type};
16
17
const TYPE_COUNT: usize = 50;
18
const MAX_ARITY: u32 = 5;
19
20
#[derive(Debug)]
21
struct GenAdapter<'a> {
22
test: TestCase<'a>,
23
// TODO: Add these arbitrary options and thread them into
24
// `Declarations::make_component`, or alternatively pass an `Unstructured`
25
// into that method to make arbitrary choices for these things.
26
//
27
// post_return: bool,
28
// lift_memory64: bool,
29
// lower_memory64: bool,
30
}
31
32
fuzz_target!(|data: &[u8]| {
33
let _ = target(data);
34
});
35
36
fn target(data: &[u8]) -> arbitrary::Result<()> {
37
drop(env_logger::try_init());
38
39
let mut u = Unstructured::new(data);
40
41
// First generate a set of type to select from.
42
let mut type_fuel = 1000;
43
let mut types = Vec::new();
44
for _ in 0..u.int_in_range(1..=TYPE_COUNT)? {
45
// Only discount fuel if the generation was successful,
46
// otherwise we'll get more random data and try again.
47
types.push(Type::generate(&mut u, MAX_TYPE_DEPTH, &mut type_fuel)?);
48
}
49
50
// Next generate a static API test case driven by the above types.
51
let mut params = Vec::new();
52
let mut result = None;
53
for _ in 0..u.int_in_range(0..=MAX_ARITY)? {
54
params.push(u.choose(&types)?);
55
}
56
if u.arbitrary()? {
57
result = Some(u.choose(&types)?);
58
}
59
60
let test = TestCase {
61
params,
62
result,
63
encoding1: u.arbitrary()?,
64
encoding2: u.arbitrary()?,
65
};
66
let adapter = GenAdapter { test };
67
68
let wat_decls = adapter.test.declarations();
69
let component = wat_decls.make_component();
70
let component = wat::parse_str(&component).unwrap();
71
72
let mut tunables = Tunables::default_host();
73
tunables.debug_adapter_modules = u.arbitrary()?;
74
75
let mut validator = wasmparser::Validator::new_with_features(wasmparser::WasmFeatures::all());
76
let mut component_types = ComponentTypesBuilder::new(&validator);
77
let adapters = ScopeVec::new();
78
79
Translator::new(&tunables, &mut validator, &mut component_types, &adapters)
80
.translate(&component)
81
.expect("should never generate an invalid component");
82
83
let adapters = adapters.into_iter();
84
assert!(adapters.len() >= 1);
85
for wasm in adapters {
86
validator.reset();
87
if let Err(err) = validator.validate_all(&wasm) {
88
eprintln!("invalid wasm module: {err:?}");
89
eprintln!("adapter: {adapter:?}");
90
std::fs::write("invalid.wasm", &wasm).unwrap();
91
match wasmprinter::print_bytes(&wasm) {
92
Ok(s) => std::fs::write("invalid.wat", &s).unwrap(),
93
Err(_) => drop(std::fs::remove_file("invalid.wat")),
94
}
95
panic!("invalid adapter: {err:?}")
96
}
97
}
98
99
Ok(())
100
}
101
102