use arbitrary::{Arbitrary, Unstructured}; use rand::{rngs::SmallRng, RngCore, SeedableRng}; use wasm_smith::{Config, Module}; use wasmparser::{Validator, WasmFeatures}; #[test] fn smoke_test_module() { let mut rng = SmallRng::seed_from_u64(0); let mut buf = vec![0; 2048]; for _ in 0..1024 { rng.fill_bytes(&mut buf); let u = Unstructured::new(&buf); if let Ok(module) = Module::arbitrary_take_rest(u) { let wasm_bytes = module.to_bytes(); let mut validator = Validator::new_with_features(wasm_features()); validate(&mut validator, &wasm_bytes); } } } #[test] fn smoke_test_ensure_termination() { let mut rng = SmallRng::seed_from_u64(0); let mut buf = vec![0; 2048]; for _ in 0..1024 { rng.fill_bytes(&mut buf); let u = Unstructured::new(&buf); if let Ok(mut module) = Module::arbitrary_take_rest(u) { module.ensure_termination(10); let wasm_bytes = module.to_bytes(); let mut validator = Validator::new_with_features(wasm_features()); validate(&mut validator, &wasm_bytes); } } } #[test] fn smoke_test_swarm_config() { let mut rng = SmallRng::seed_from_u64(0); let mut buf = vec![0; 2048]; for _ in 0..1024 { rng.fill_bytes(&mut buf); let mut u = Unstructured::new(&buf); if let Ok(config) = Config::arbitrary(&mut u) { if let Ok(module) = Module::new(config, &mut u) { let wasm_bytes = module.to_bytes(); let mut validator = Validator::new_with_features(wasm_features()); validate(&mut validator, &wasm_bytes); } } } } #[test] fn multi_value_disabled() { let mut rng = SmallRng::seed_from_u64(42); let mut buf = vec![0; 2048]; for _ in 0..10 { rng.fill_bytes(&mut buf); let mut u = Unstructured::new(&buf); let mut cfg = Config::arbitrary(&mut u).unwrap(); cfg.multi_value_enabled = false; if let Ok(module) = Module::new(cfg, &mut u) { let wasm_bytes = module.to_bytes(); let mut features = wasm_features(); features.multi_value = false; let mut validator = Validator::new_with_features(features); validate(&mut validator, &wasm_bytes); } } } #[test] fn smoke_can_smith_valid_webassembly_one_point_oh() { let mut rng = SmallRng::seed_from_u64(42); let mut buf = vec![0; 10240]; for _ in 0..100 { rng.fill_bytes(&mut buf); let mut u = Unstructured::new(&buf); let mut cfg = Config::arbitrary(&mut u).unwrap(); cfg.sign_extension_ops_enabled = false; cfg.saturating_float_to_int_enabled = false; cfg.reference_types_enabled = false; cfg.multi_value_enabled = false; cfg.bulk_memory_enabled = false; cfg.simd_enabled = false; cfg.relaxed_simd_enabled = false; cfg.exceptions_enabled = false; cfg.memory64_enabled = false; cfg.max_memories = 1; cfg.max_tables = 1; let features = parser_features_from_config(&cfg); if let Ok(module) = Module::new(cfg, &mut u) { let wasm_bytes = module.to_bytes(); // This table should set to `true` only features specified in wasm-core-1 spec. let mut validator = Validator::new_with_features(features); validate(&mut validator, &wasm_bytes); } } } #[test] fn smoke_test_no_trapping_mode() { let mut rng = SmallRng::seed_from_u64(0); let mut buf = vec![0; 2048]; for _ in 0..1024 { rng.fill_bytes(&mut buf); let mut u = Unstructured::new(&buf); let mut cfg = Config::arbitrary(&mut u).unwrap(); cfg.disallow_traps = true; if let Ok(module) = Module::new(cfg, &mut u) { let wasm_bytes = module.to_bytes(); let mut validator = Validator::new_with_features(wasm_features()); validate(&mut validator, &wasm_bytes); } } } #[test] fn smoke_test_wasm_gc() { let mut rng = SmallRng::seed_from_u64(0); let mut buf = vec![0; 2048]; for _ in 0..1024 { rng.fill_bytes(&mut buf); let mut u = Unstructured::new(&buf); let config = Config { gc_enabled: true, ..Config::default() }; if let Ok(module) = Module::new(config, &mut u) { let wasm_bytes = module.to_bytes(); let mut validator = Validator::new_with_features(wasm_features()); validate(&mut validator, &wasm_bytes); } } } fn wasm_features() -> WasmFeatures { WasmFeatures { multi_memory: true, relaxed_simd: true, memory64: true, exceptions: true, tail_call: true, function_references: true, gc: true, ..WasmFeatures::default() } } fn parser_features_from_config(config: &Config) -> WasmFeatures { WasmFeatures { mutable_global: true, saturating_float_to_int: config.saturating_float_to_int_enabled, sign_extension: config.sign_extension_ops_enabled, reference_types: config.reference_types_enabled, multi_value: config.multi_value_enabled, bulk_memory: config.bulk_memory_enabled, simd: config.simd_enabled, relaxed_simd: config.relaxed_simd_enabled, multi_memory: config.max_memories > 1, exceptions: config.exceptions_enabled, memory64: config.memory64_enabled, tail_call: config.tail_call_enabled, threads: false, floats: true, extended_const: false, component_model: false, function_references: false, memory_control: false, gc: false, component_model_values: false, component_model_nested_names: false, } } fn validate(validator: &mut Validator, bytes: &[u8]) { let err = match validator.validate_all(bytes) { Ok(_) => return, Err(e) => e, }; drop(std::fs::write("test.wasm", &bytes)); if let Ok(text) = wasmprinter::print_bytes(bytes) { drop(std::fs::write("test.wat", &text)); } panic!("wasm failed to validate: {}", err); }