diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:43:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:43:14 +0000 |
commit | 8dd16259287f58f9273002717ec4d27e97127719 (patch) | |
tree | 3863e62a53829a84037444beab3abd4ed9dfc7d0 /third_party/rust/wasm-smith | |
parent | Releasing progress-linux version 126.0.1-1~progress7.99u1. (diff) | |
download | firefox-8dd16259287f58f9273002717ec4d27e97127719.tar.xz firefox-8dd16259287f58f9273002717ec4d27e97127719.zip |
Merging upstream version 127.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/wasm-smith')
-rw-r--r-- | third_party/rust/wasm-smith/.cargo-checksum.json | 2 | ||||
-rw-r--r-- | third_party/rust/wasm-smith/Cargo.toml | 10 | ||||
-rw-r--r-- | third_party/rust/wasm-smith/src/component.rs | 17 | ||||
-rw-r--r-- | third_party/rust/wasm-smith/src/config.rs | 9 | ||||
-rw-r--r-- | third_party/rust/wasm-smith/src/core.rs | 202 | ||||
-rw-r--r-- | third_party/rust/wasm-smith/src/core/code_builder.rs | 77 | ||||
-rw-r--r-- | third_party/rust/wasm-smith/src/core/code_builder/no_traps.rs | 10 | ||||
-rw-r--r-- | third_party/rust/wasm-smith/src/core/terminate.rs | 1 | ||||
-rw-r--r-- | third_party/rust/wasm-smith/src/lib.rs | 6 | ||||
-rw-r--r-- | third_party/rust/wasm-smith/tests/common/mod.rs | 52 | ||||
-rw-r--r-- | third_party/rust/wasm-smith/tests/component.rs | 8 | ||||
-rw-r--r-- | third_party/rust/wasm-smith/tests/core.rs | 55 | ||||
-rw-r--r-- | third_party/rust/wasm-smith/tests/exports.rs | 32 |
13 files changed, 321 insertions, 160 deletions
diff --git a/third_party/rust/wasm-smith/.cargo-checksum.json b/third_party/rust/wasm-smith/.cargo-checksum.json index d61edb195b..fd68c5102e 100644 --- a/third_party/rust/wasm-smith/.cargo-checksum.json +++ b/third_party/rust/wasm-smith/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"b911aa53dc1f5c0cb04a77e15b43c31cee98893c7bcb98b6d73405aeca6b447c","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"e7b2a96cf39834aa19aed7cad8658e33445cdec7c4957658ba39e3b82cc4254b","benches/corpus.rs":"2df29556be0799f0cb1f32c8d0ae5ba0c4b9815cf4d59a8b71744d926c0693a0","src/component.rs":"253cf8d8abf785e4b5a5c614561a85b032e7f7bdec366f83d9db0702f73d2122","src/component/encode.rs":"5985e3f412595e07372a0787ec3db6c3018840df2bcfc638ab8798fd74b22778","src/config.rs":"e75d93c0a6a5ba07ff3ec1164a9b58601fadc0a0899149e14a77e8f0ab4595e4","src/core.rs":"35d3854c8caa1f61494b2f8e2b5e150d67cf88582243feeeb198e2aa93247339","src/core/code_builder.rs":"a8b27f652c8ae4b964e05933df313016ab7ffc297ca76005faca3da2792e3afc","src/core/code_builder/no_traps.rs":"2f36c548a32a6a003e6bb22a8fe7c75517b9be00c5a299212836a7e2431a8693","src/core/encode.rs":"77e1395c78ecf1b688a3c515a58be6efe1aa58d450a20a50d69598c54f7162de","src/core/terminate.rs":"c7c5f5618d393e5d9e44ae5e9bbde4b81bfa1ca3d2111d1eea875e2490f0f64b","src/lib.rs":"d393ae9daba211ba68a48dbdee545e0570cb8298e4c62319b8c8a8b9355cd6e3","tests/available_imports.rs":"6d4c1b111f35fefce55b668474ac9ba25edf7fc3e3decb88696b644aec13d603","tests/common/mod.rs":"9d0712a0b3e30030934b04785fb8632576bdcc31921ee8f524e0b2c903dee28d","tests/component.rs":"44684e990e832590a0b348ce33fadf39ee55dec52fdfa9353570edcbf65325ee","tests/core.rs":"408a50da4438be4e5343b116aa80f5ce344ba9508fad413cc5c32cd0aa2164fb","tests/exports.rs":"dcac4e18f277cbdb821f4ad7eda0a900bd73924e0818cf1b408700c9b7bba789"},"package":"61ff53a54a853f174b0df74cdb1553f1451e7bcdc23b26b1379f664ee1913d1a"}
\ No newline at end of file +{"files":{"Cargo.toml":"4efe2ea2adda65b88d8ebcc59c881faaa54aa0a259f705d5a387c5e0c4a5a5d6","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"e7b2a96cf39834aa19aed7cad8658e33445cdec7c4957658ba39e3b82cc4254b","benches/corpus.rs":"2df29556be0799f0cb1f32c8d0ae5ba0c4b9815cf4d59a8b71744d926c0693a0","src/component.rs":"7846fba1f588bb8cee539d4ae162c564332fd382abc54958ab72d31f5678e191","src/component/encode.rs":"5985e3f412595e07372a0787ec3db6c3018840df2bcfc638ab8798fd74b22778","src/config.rs":"207c1ed2535f11cfdc275b2388c03b2c9fe27b6f28d5c428c6c5cf6a81abe8af","src/core.rs":"b1ec6d747677dbf54ea1892e8b0928a68c641d6e56df4151cd8f9f9ae0f89a4f","src/core/code_builder.rs":"77d216064374edf0fcd273b2d6ddf3c4f90fd792be83f85c1e198bdea0138387","src/core/code_builder/no_traps.rs":"14dab911427934dd6394b36eea9761c8722c47611b3ebf9fde1d54bebd7c4e55","src/core/encode.rs":"77e1395c78ecf1b688a3c515a58be6efe1aa58d450a20a50d69598c54f7162de","src/core/terminate.rs":"e07fe450c1fee58726bace161c5747a6f01539e8b2937724064cc7370562555c","src/lib.rs":"21abe6dc08ab1fe40e6e9a063ee93c901318278c051a45f94519b8e4f402e2dc","tests/available_imports.rs":"6d4c1b111f35fefce55b668474ac9ba25edf7fc3e3decb88696b644aec13d603","tests/common/mod.rs":"815532619bf27593765c6238173644cdda33fbd0ba80e45fef165bbd9717934d","tests/component.rs":"bbde2e2d75680184724515a82babbe93b259e14c12c55c665d266967ede8b8f1","tests/core.rs":"4500bf8ec2a51c27a7cb01ef7c117c6e1acf12f1609579fd8761961c0d6c223a","tests/exports.rs":"518fea2a776cec51b059a31420908a73ddf7303aa143104afe32c52b09f88eda"},"package":"1218f393276f7a13f6c54467434633144b46c33ecbc3cbafdc938033f0315d1a"}
\ No newline at end of file diff --git a/third_party/rust/wasm-smith/Cargo.toml b/third_party/rust/wasm-smith/Cargo.toml index 3847409e33..3221e77872 100644 --- a/third_party/rust/wasm-smith/Cargo.toml +++ b/third_party/rust/wasm-smith/Cargo.toml @@ -12,7 +12,7 @@ [package] edition = "2021" name = "wasm-smith" -version = "0.201.0" +version = "0.205.0" authors = ["Nick Fitzgerald <fitzgen@gmail.com>"] exclude = ["/benches/corpus"] description = "A WebAssembly test case generator" @@ -61,14 +61,14 @@ version = "1.0.166" optional = true [dependencies.wasm-encoder] -version = "0.201.0" +version = "0.205.0" [dependencies.wasmparser] -version = "0.201.0" +version = "0.205.0" optional = true [dependencies.wat] -version = "1.201.0" +version = "1.205.0" optional = true [dev-dependencies.criterion] @@ -79,7 +79,7 @@ version = "0.8.4" features = ["small_rng"] [dev-dependencies.wasmparser] -version = "0.201.0" +version = "0.205.0" [features] _internal_cli = [ diff --git a/third_party/rust/wasm-smith/src/component.rs b/third_party/rust/wasm-smith/src/component.rs index 7a85b2bf10..35bf93231b 100644 --- a/third_party/rust/wasm-smith/src/component.rs +++ b/third_party/rust/wasm-smith/src/component.rs @@ -952,6 +952,7 @@ impl ComponentBuilder { Ok(crate::core::GlobalType { val_type: self.arbitrary_core_valtype(u)?, mutable: u.arbitrary()?, + shared: false, }) } @@ -1308,8 +1309,8 @@ impl ComponentBuilder { 6 => Ok(PrimitiveValType::U32), 7 => Ok(PrimitiveValType::S64), 8 => Ok(PrimitiveValType::U64), - 9 => Ok(PrimitiveValType::Float32), - 10 => Ok(PrimitiveValType::Float64), + 9 => Ok(PrimitiveValType::F32), + 10 => Ok(PrimitiveValType::F64), 11 => Ok(PrimitiveValType::Char), 12 => Ok(PrimitiveValType::String), _ => unreachable!(), @@ -1773,8 +1774,8 @@ fn canonical_abi_for(func_ty: &FuncType) -> Rc<crate::core::FuncType> { | PrimitiveValType::S32 | PrimitiveValType::U32 => ValType::I32, PrimitiveValType::S64 | PrimitiveValType::U64 => ValType::I64, - PrimitiveValType::Float32 => ValType::F32, - PrimitiveValType::Float64 => ValType::F64, + PrimitiveValType::F32 => ValType::F32, + PrimitiveValType::F64 => ValType::F64, PrimitiveValType::String => { unimplemented!("non-scalar types are not supported yet") } @@ -1819,8 +1820,8 @@ fn inverse_scalar_canonical_abi_for( ComponentValType::Primitive(PrimitiveValType::U64), ]) .cloned(), - ValType::F32 => Ok(ComponentValType::Primitive(PrimitiveValType::Float32)), - ValType::F64 => Ok(ComponentValType::Primitive(PrimitiveValType::Float64)), + ValType::F32 => Ok(ComponentValType::Primitive(PrimitiveValType::F32)), + ValType::F64 => Ok(ComponentValType::Primitive(PrimitiveValType::F64)), ValType::V128 | ValType::Ref(_) => { unreachable!("not used in canonical ABI") } @@ -2055,8 +2056,8 @@ fn is_scalar(ty: &ComponentValType) -> bool { | PrimitiveValType::U32 | PrimitiveValType::S64 | PrimitiveValType::U64 - | PrimitiveValType::Float32 - | PrimitiveValType::Float64 + | PrimitiveValType::F32 + | PrimitiveValType::F64 | PrimitiveValType::Char => true, PrimitiveValType::String => false, }, diff --git a/third_party/rust/wasm-smith/src/config.rs b/third_party/rust/wasm-smith/src/config.rs index 43dbecceb8..57bd25be24 100644 --- a/third_party/rust/wasm-smith/src/config.rs +++ b/third_party/rust/wasm-smith/src/config.rs @@ -313,6 +313,12 @@ define_config! { /// Defaults to `false`. pub gc_enabled: bool = false, + /// Determines whether the custom-page-sizes proposal is enabled when + /// generating a Wasm module. + /// + /// Defaults to `false`. + pub custom_page_sizes_enabled: bool = false, + /// Returns whether we should generate custom sections or not. Defaults /// to false. pub generate_custom_sections: bool = false, @@ -681,6 +687,7 @@ impl<'a> Arbitrary<'a> for Config { }, table_max_size_required: u.arbitrary()?, max_table_elements: u.int_in_range(0..=1_000_000)?, + disallow_traps: u.arbitrary()?, // These fields, unlike the ones above, are less useful to set. // They either make weird inputs or are for features not widely @@ -712,9 +719,9 @@ impl<'a> Arbitrary<'a> for Config { exports: None, threads_enabled: false, export_everything: false, - disallow_traps: false, tail_call_enabled: false, gc_enabled: false, + custom_page_sizes_enabled: false, generate_custom_sections: false, allow_invalid_funcs: false, }) diff --git a/third_party/rust/wasm-smith/src/core.rs b/third_party/rust/wasm-smith/src/core.rs index 194d2101ae..db9bb2e546 100644 --- a/third_party/rust/wasm-smith/src/core.rs +++ b/third_party/rust/wasm-smith/src/core.rs @@ -146,6 +146,11 @@ pub struct Module { /// What the maximum type index that can be referenced is. max_type_limit: MaxTypeLimit, + + /// Some known-interesting values, such as powers of two, values just before + /// or just after a memory size, etc... + interesting_values32: Vec<u32>, + interesting_values64: Vec<u64>, } impl<'a> Arbitrary<'a> for Module { @@ -232,16 +237,13 @@ impl Module { export_names: HashSet::new(), const_expr_choices: Vec::new(), max_type_limit: MaxTypeLimit::ModuleTypes, + interesting_values32: Vec::new(), + interesting_values64: Vec::new(), } } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub(crate) struct RecGroup { - pub(crate) types: Vec<SubType>, -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash)] pub(crate) struct SubType { pub(crate) is_final: bool, pub(crate) supertype: Option<u32>, @@ -494,6 +496,8 @@ impl Module { matches!(self.ty(b).composite_type, CompositeType::Func(_)) } + (HT::NoExn, HT::Exn) => true, + // Nothing else matches. (Avoid full wildcard matches so that // adding/modifying variants is easier in the future.) (HT::Concrete(_), _) @@ -506,11 +510,9 @@ impl Module { | (HT::Eq, _) | (HT::Struct, _) | (HT::Array, _) - | (HT::I31, _) => false, - - // TODO: `exn` probably will be its own type hierarchy and will - // probably get `noexn` as well. - (HT::Exn, _) => false, + | (HT::I31, _) + | (HT::Exn, _) + | (HT::NoExn, _) => false, } } @@ -779,7 +781,7 @@ impl Module { HT::Extern => { choices.push(HT::NoExtern); } - HT::Exn | HT::None | HT::NoExtern | HT::NoFunc => {} + HT::Exn | HT::NoExn | HT::None | HT::NoExtern | HT::NoFunc => {} } Ok(*u.choose(&choices)?) } @@ -858,6 +860,9 @@ impl Module { choices.extend(self.func_types.iter().copied().map(HT::Concrete)); choices.push(HT::Func); } + HT::NoExn => { + choices.push(HT::Exn); + } HT::Concrete(mut idx) => { match &self .types @@ -1422,6 +1427,7 @@ impl Module { Ok(GlobalType { val_type: self.arbitrary_valtype(u)?, mutable: u.arbitrary()?, + shared: false, }) } @@ -1645,6 +1651,7 @@ impl Module { wasmparser::HeapType::Array => HeapType::Array, wasmparser::HeapType::I31 => HeapType::I31, wasmparser::HeapType::Exn => HeapType::Exn, + wasmparser::HeapType::NoExn => HeapType::NoExn, } } @@ -1754,6 +1761,7 @@ impl Module { GlobalType { val_type: convert_val_type(&global_type.content_type), mutable: global_type.mutable, + shared: global_type.shared, }, u, )?, @@ -2039,6 +2047,8 @@ impl Module { } fn arbitrary_code(&mut self, u: &mut Unstructured) -> Result<()> { + self.compute_interesting_values(); + self.code.reserve(self.num_defined_funcs); let mut allocs = CodeBuilderAllocations::new(self, self.config.exports.is_some()); for (_, ty) in self.funcs[self.funcs.len() - self.num_defined_funcs..].iter() { @@ -2224,6 +2234,170 @@ impl Module { } }) } + + fn compute_interesting_values(&mut self) { + debug_assert!(self.interesting_values32.is_empty()); + debug_assert!(self.interesting_values64.is_empty()); + + let mut interesting_values32 = HashSet::new(); + let mut interesting_values64 = HashSet::new(); + + let mut interesting = |val: u64| { + interesting_values32.insert(val as u32); + interesting_values64.insert(val); + }; + + // Zero is always interesting. + interesting(0); + + // Max values are always interesting. + interesting(u8::MAX as _); + interesting(u16::MAX as _); + interesting(u32::MAX as _); + interesting(u64::MAX); + + // Min values are always interesting. + interesting(i8::MIN as _); + interesting(i16::MIN as _); + interesting(i32::MIN as _); + interesting(i64::MIN as _); + + for i in 0..64 { + // Powers of two. + interesting(1 << i); + + // Inverted powers of two. + interesting(!(1 << i)); + + // Powers of two minus one, AKA high bits unset and low bits set. + interesting((1 << i) - 1); + + // Negative powers of two, AKA high bits set and low bits unset. + interesting(((1_i64 << 63) >> i) as _); + } + + // Some repeating bit patterns. + for pattern in [0b01010101, 0b00010001, 0b00010001, 0b00000001] { + for b in [pattern, !pattern] { + interesting(u64::from_ne_bytes([b, b, b, b, b, b, b, b])); + } + } + + // Interesting float values. + let mut interesting_f64 = |x: f64| interesting(x.to_bits()); + interesting_f64(0.0); + interesting_f64(-0.0); + interesting_f64(f64::INFINITY); + interesting_f64(f64::NEG_INFINITY); + interesting_f64(f64::EPSILON); + interesting_f64(-f64::EPSILON); + interesting_f64(f64::MIN); + interesting_f64(f64::MIN_POSITIVE); + interesting_f64(f64::MAX); + interesting_f64(f64::NAN); + let mut interesting_f32 = |x: f32| interesting(x.to_bits() as _); + interesting_f32(0.0); + interesting_f32(-0.0); + interesting_f32(f32::INFINITY); + interesting_f32(f32::NEG_INFINITY); + interesting_f32(f32::EPSILON); + interesting_f32(-f32::EPSILON); + interesting_f32(f32::MIN); + interesting_f32(f32::MIN_POSITIVE); + interesting_f32(f32::MAX); + interesting_f32(f32::NAN); + + // Interesting values related to table bounds. + for t in self.tables.iter() { + interesting(t.minimum as _); + if let Some(x) = t.minimum.checked_add(1) { + interesting(x as _); + } + + if let Some(x) = t.maximum { + interesting(x as _); + if let Some(y) = x.checked_add(1) { + interesting(y as _); + } + } + } + + // Interesting values related to memory bounds. + for m in self.memories.iter() { + let min = m.minimum.saturating_mul(crate::page_size(m).into()); + interesting(min); + for i in 0..5 { + if let Some(x) = min.checked_add(1 << i) { + interesting(x); + } + if let Some(x) = min.checked_sub(1 << i) { + interesting(x); + } + } + + if let Some(max) = m.maximum { + let max = max.saturating_mul(crate::page_size(m).into()); + interesting(max); + for i in 0..5 { + if let Some(x) = max.checked_add(1 << i) { + interesting(x); + } + if let Some(x) = max.checked_sub(1 << i) { + interesting(x); + } + } + } + } + + self.interesting_values32.extend(interesting_values32); + self.interesting_values64.extend(interesting_values64); + + // Sort for determinism. + self.interesting_values32.sort(); + self.interesting_values64.sort(); + } + + fn arbitrary_const_instruction( + &self, + ty: ValType, + u: &mut Unstructured<'_>, + ) -> Result<Instruction> { + debug_assert!(self.interesting_values32.len() > 0); + debug_assert!(self.interesting_values64.len() > 0); + match ty { + ValType::I32 => Ok(Instruction::I32Const(if u.arbitrary()? { + *u.choose(&self.interesting_values32)? as i32 + } else { + u.arbitrary()? + })), + ValType::I64 => Ok(Instruction::I64Const(if u.arbitrary()? { + *u.choose(&self.interesting_values64)? as i64 + } else { + u.arbitrary()? + })), + ValType::F32 => Ok(Instruction::F32Const(if u.arbitrary()? { + f32::from_bits(*u.choose(&self.interesting_values32)?) + } else { + u.arbitrary()? + })), + ValType::F64 => Ok(Instruction::F64Const(if u.arbitrary()? { + f64::from_bits(*u.choose(&self.interesting_values64)?) + } else { + u.arbitrary()? + })), + ValType::V128 => Ok(Instruction::V128Const(if u.arbitrary()? { + let upper = (*u.choose(&self.interesting_values64)? as i128) << 64; + let lower = *u.choose(&self.interesting_values64)? as i128; + upper | lower + } else { + u.arbitrary()? + })), + ValType::Ref(ty) => { + assert!(ty.nullable); + Ok(Instruction::RefNull(ty.heap_type)) + } + } + } } pub(crate) fn arbitrary_limits32( @@ -2344,6 +2518,11 @@ pub(crate) fn arbitrary_memtype(u: &mut Unstructured, config: &Config) -> Result // We want to favor memories <= 1gb in size, allocate at most 16k pages, // depending on the maximum number of memories. let memory64 = config.memory64_enabled && u.arbitrary()?; + let page_size = if config.custom_page_sizes_enabled && u.arbitrary()? { + Some(1 << u.int_in_range(0..=16)?) + } else { + None + }; let max_inbounds = 16 * 1024 / u64::try_from(config.max_memories).unwrap(); let min_pages = if config.disallow_traps { Some(1) } else { None }; let max_pages = min_pages.unwrap_or(0).max(if memory64 { @@ -2363,6 +2542,7 @@ pub(crate) fn arbitrary_memtype(u: &mut Unstructured, config: &Config) -> Result maximum, memory64, shared, + page_size_log2: page_size, }) } diff --git a/third_party/rust/wasm-smith/src/core/code_builder.rs b/third_party/rust/wasm-smith/src/core/code_builder.rs index a55c5aafda..150572d930 100644 --- a/third_party/rust/wasm-smith/src/core/code_builder.rs +++ b/third_party/rust/wasm-smith/src/core/code_builder.rs @@ -870,6 +870,7 @@ impl CodeBuilderAllocations { module.globals.push(GlobalType { val_type: ty, mutable: true, + shared: false, }); module.defined_globals.push((global_idx, init)); @@ -1435,7 +1436,7 @@ impl CodeBuilder<'_> { } operands = &[]; } - instructions.push(arbitrary_val(*expected, u)); + instructions.push(module.arbitrary_const_instruction(*expected, u)?); } Ok(()) } @@ -1544,20 +1545,6 @@ impl CodeBuilder<'_> { } } -fn arbitrary_val(ty: ValType, u: &mut Unstructured<'_>) -> Instruction { - match ty { - ValType::I32 => Instruction::I32Const(u.arbitrary().unwrap_or(0)), - ValType::I64 => Instruction::I64Const(u.arbitrary().unwrap_or(0)), - ValType::F32 => Instruction::F32Const(u.arbitrary().unwrap_or(0.0)), - ValType::F64 => Instruction::F64Const(u.arbitrary().unwrap_or(0.0)), - ValType::V128 => Instruction::V128Const(u.arbitrary().unwrap_or(0)), - ValType::Ref(ty) => { - assert!(ty.nullable); - Instruction::RefNull(ty.heap_type) - } - } -} - #[inline] fn unreachable_valid(module: &Module, _: &mut CodeBuilder) -> bool { !module.config.disallow_traps @@ -1617,13 +1604,24 @@ fn try_table( let i = i as u32; let label_types = ctrl.label_types(); + + // Empty labels are candidates for a `catch_all` since nothing is + // pushed in that case. if label_types.is_empty() { catch_options.push(Box::new(move |_, _| Ok(Catch::All { label: i }))); } + + // Labels with just an `externref` are suitable for `catch_all_refs`, + // which first pushes nothing since there's no tag and then pushes + // the caught exception value. if label_types == [ValType::EXNREF] { catch_options.push(Box::new(move |_, _| Ok(Catch::AllRef { label: i }))); } + // If there is a tag which exactly matches the types of the label we're + // looking at then that tag can be used as part of a `catch` branch. + // That tag's parameters, which are the except values, are pushed + // for the label. if builder.allocs.tags.contains_key(label_types) { let label_types = label_types.to_vec(); catch_options.push(Box::new(move |u, builder| { @@ -1634,15 +1632,20 @@ fn try_table( })); } - let mut label_types_with_exnref = label_types.to_vec(); - label_types_with_exnref.push(ValType::EXNREF); - if builder.allocs.tags.contains_key(&label_types_with_exnref) { - catch_options.push(Box::new(move |u, builder| { - Ok(Catch::OneRef { - tag: *u.choose(&builder.allocs.tags[&label_types_with_exnref])?, - label: i, - }) - })); + // And finally the last type of catch label, `catch_ref`. If the label + // ends with `exnref`, then use everything except the last `exnref` to + // see if there's a matching tag. If so then `catch_ref` can be used + // with that tag when branching to this label. + if let Some((&ValType::EXNREF, rest)) = label_types.split_last() { + if builder.allocs.tags.contains_key(rest) { + let rest = rest.to_vec(); + catch_options.push(Box::new(move |u, builder| { + Ok(Catch::OneRef { + tag: *u.choose(&builder.allocs.tags[&rest])?, + label: i, + }) + })); + } } } @@ -3403,49 +3406,45 @@ fn data_drop( fn i32_const( u: &mut Unstructured, - _module: &Module, + module: &Module, builder: &mut CodeBuilder, instructions: &mut Vec<Instruction>, ) -> Result<()> { - let x = u.arbitrary()?; builder.push_operands(&[ValType::I32]); - instructions.push(Instruction::I32Const(x)); + instructions.push(module.arbitrary_const_instruction(ValType::I32, u)?); Ok(()) } fn i64_const( u: &mut Unstructured, - _module: &Module, + module: &Module, builder: &mut CodeBuilder, instructions: &mut Vec<Instruction>, ) -> Result<()> { - let x = u.arbitrary()?; builder.push_operands(&[ValType::I64]); - instructions.push(Instruction::I64Const(x)); + instructions.push(module.arbitrary_const_instruction(ValType::I64, u)?); Ok(()) } fn f32_const( u: &mut Unstructured, - _module: &Module, + module: &Module, builder: &mut CodeBuilder, instructions: &mut Vec<Instruction>, ) -> Result<()> { - let x = u.arbitrary()?; builder.push_operands(&[ValType::F32]); - instructions.push(Instruction::F32Const(x)); + instructions.push(module.arbitrary_const_instruction(ValType::F32, u)?); Ok(()) } fn f64_const( u: &mut Unstructured, - _module: &Module, + module: &Module, builder: &mut CodeBuilder, instructions: &mut Vec<Instruction>, ) -> Result<()> { - let x = u.arbitrary()?; builder.push_operands(&[ValType::F64]); - instructions.push(Instruction::F64Const(x)); + instructions.push(module.arbitrary_const_instruction(ValType::F64, u)?); Ok(()) } @@ -5204,10 +5203,12 @@ fn memory_offset(u: &mut Unstructured, module: &Module, memory_index: u32) -> Re assert!(a + b + c != 0); let memory_type = &module.memories[memory_index as usize]; - let min = memory_type.minimum.saturating_mul(65536); + let min = memory_type + .minimum + .saturating_mul(crate::page_size(memory_type).into()); let max = memory_type .maximum - .map(|max| max.saturating_mul(65536)) + .map(|max| max.saturating_mul(crate::page_size(memory_type).into())) .unwrap_or(u64::MAX); let (min, max, true_max) = match (memory_type.memory64, module.config.disallow_traps) { diff --git a/third_party/rust/wasm-smith/src/core/code_builder/no_traps.rs b/third_party/rust/wasm-smith/src/core/code_builder/no_traps.rs index 4f8b31ca9f..5ced1fa391 100644 --- a/third_party/rust/wasm-smith/src/core/code_builder/no_traps.rs +++ b/third_party/rust/wasm-smith/src/core/code_builder/no_traps.rs @@ -37,7 +37,10 @@ pub(crate) fn load<'a>( // [] insts.push(Instruction::MemorySize(memarg.memory_index)); // [mem_size_in_pages:address_type] - insts.push(int_const_inst(address_type, 65_536)); + insts.push(int_const_inst( + address_type, + crate::page_size(memory).into(), + )); // [mem_size_in_pages:address_type wasm_page_size:address_type] insts.push(int_mul_inst(address_type)); // [mem_size_in_bytes:address_type] @@ -116,7 +119,10 @@ pub(crate) fn store<'a>( // [] insts.push(Instruction::MemorySize(memarg.memory_index)); // [mem_size_in_pages:address_type] - insts.push(int_const_inst(address_type, 65_536)); + insts.push(int_const_inst( + address_type, + crate::page_size(memory).into(), + )); // [mem_size_in_pages:address_type wasm_page_size:address_type] insts.push(int_mul_inst(address_type)); // [mem_size_in_bytes:address_type] diff --git a/third_party/rust/wasm-smith/src/core/terminate.rs b/third_party/rust/wasm-smith/src/core/terminate.rs index 7983c35be6..33aff2639c 100644 --- a/third_party/rust/wasm-smith/src/core/terminate.rs +++ b/third_party/rust/wasm-smith/src/core/terminate.rs @@ -23,6 +23,7 @@ impl Module { self.globals.push(GlobalType { val_type: ValType::I32, mutable: true, + shared: false, }); self.defined_globals .push((fuel_global, ConstExpr::i32_const(default_fuel as i32))); diff --git a/third_party/rust/wasm-smith/src/lib.rs b/third_party/rust/wasm-smith/src/lib.rs index b985791aae..59d4ddb640 100644 --- a/third_party/rust/wasm-smith/src/lib.rs +++ b/third_party/rust/wasm-smith/src/lib.rs @@ -63,10 +63,16 @@ use arbitrary::{Result, Unstructured}; pub use component::Component; pub use config::{Config, MemoryOffsetChoices}; use std::{collections::HashSet, fmt::Write, str}; +use wasm_encoder::MemoryType; #[cfg(feature = "_internal_cli")] pub use config::InternalOptionalConfig; +pub(crate) fn page_size(mem: &MemoryType) -> u32 { + const DEFAULT_WASM_PAGE_SIZE: u32 = 65_536; + mem.page_size_log2.unwrap_or(DEFAULT_WASM_PAGE_SIZE) +} + /// Do something an arbitrary number of times. /// /// The callback can return `false` to exit the loop early. diff --git a/third_party/rust/wasm-smith/tests/common/mod.rs b/third_party/rust/wasm-smith/tests/common/mod.rs index cc24eed278..8a238776d6 100644 --- a/third_party/rust/wasm-smith/tests/common/mod.rs +++ b/third_party/rust/wasm-smith/tests/common/mod.rs @@ -2,30 +2,34 @@ use wasm_smith::Config; use wasmparser::{types::Types, Validator, WasmFeatures}; pub 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, - function_references: config.gc_enabled, - gc: config.gc_enabled, - - threads: false, - floats: true, - extended_const: false, - component_model: false, - memory_control: false, - component_model_values: false, - component_model_nested_names: false, - } + let mut features = WasmFeatures::MUTABLE_GLOBAL | WasmFeatures::FLOATS; + features.set( + WasmFeatures::SATURATING_FLOAT_TO_INT, + config.saturating_float_to_int_enabled, + ); + features.set( + WasmFeatures::SIGN_EXTENSION, + config.sign_extension_ops_enabled, + ); + features.set( + WasmFeatures::REFERENCE_TYPES, + config.reference_types_enabled, + ); + features.set(WasmFeatures::MULTI_VALUE, config.multi_value_enabled); + features.set(WasmFeatures::BULK_MEMORY, config.bulk_memory_enabled); + features.set(WasmFeatures::SIMD, config.simd_enabled); + features.set(WasmFeatures::RELAXED_SIMD, config.relaxed_simd_enabled); + features.set(WasmFeatures::MULTI_MEMORY, config.max_memories > 1); + features.set(WasmFeatures::EXCEPTIONS, config.exceptions_enabled); + features.set(WasmFeatures::MEMORY64, config.memory64_enabled); + features.set(WasmFeatures::TAIL_CALL, config.tail_call_enabled); + features.set(WasmFeatures::FUNCTION_REFERENCES, config.gc_enabled); + features.set(WasmFeatures::GC, config.gc_enabled); + features.set( + WasmFeatures::CUSTOM_PAGE_SIZES, + config.custom_page_sizes_enabled, + ); + features } pub fn validate(validator: &mut Validator, bytes: &[u8]) -> Types { diff --git a/third_party/rust/wasm-smith/tests/component.rs b/third_party/rust/wasm-smith/tests/component.rs index 7d5a40159c..89fdebffaa 100644 --- a/third_party/rust/wasm-smith/tests/component.rs +++ b/third_party/rust/wasm-smith/tests/component.rs @@ -18,11 +18,9 @@ fn smoke_test_component() { ok_count += 1; let component = component.to_bytes(); - let mut validator = - wasmparser::Validator::new_with_features(wasmparser::WasmFeatures { - component_model: true, - ..Default::default() - }); + let mut validator = wasmparser::Validator::new_with_features( + wasmparser::WasmFeatures::default() | wasmparser::WasmFeatures::COMPONENT_MODEL, + ); if let Err(e) = validator.validate_all(&component) { std::fs::write("component.wasm", &component).unwrap(); panic!( diff --git a/third_party/rust/wasm-smith/tests/core.rs b/third_party/rust/wasm-smith/tests/core.rs index 7286952dc6..9b18fcdeaf 100644 --- a/third_party/rust/wasm-smith/tests/core.rs +++ b/third_party/rust/wasm-smith/tests/core.rs @@ -3,6 +3,9 @@ use rand::{rngs::SmallRng, RngCore, SeedableRng}; use wasm_smith::{Config, Module}; use wasmparser::{Validator, WasmFeatures}; +mod common; +use common::{parser_features_from_config, validate}; + #[test] fn smoke_test_module() { let mut rng = SmallRng::seed_from_u64(0); @@ -66,7 +69,7 @@ fn multi_value_disabled() { if let Ok(module) = Module::new(cfg, &mut u) { let wasm_bytes = module.to_bytes(); let mut features = wasm_features(); - features.multi_value = false; + features.remove(WasmFeatures::MULTI_VALUE); let mut validator = Validator::new_with_features(features); validate(&mut validator, &wasm_bytes); } @@ -140,53 +143,5 @@ fn smoke_test_wasm_gc() { } 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); + WasmFeatures::all() } diff --git a/third_party/rust/wasm-smith/tests/exports.rs b/third_party/rust/wasm-smith/tests/exports.rs index ff1dac0cbe..6d3e4451a2 100644 --- a/third_party/rust/wasm-smith/tests/exports.rs +++ b/third_party/rust/wasm-smith/tests/exports.rs @@ -1,3 +1,5 @@ +#![cfg(feature = "wasmparser")] + use arbitrary::{Arbitrary, Unstructured}; use rand::{rngs::SmallRng, RngCore, SeedableRng}; use wasm_smith::{Config, Module}; @@ -18,9 +20,9 @@ enum ExportType { fn smoke_test_single_export() { let test = r#" (module - (func (export "foo") (param i32) (result i64) - unreachable - ) + (func (export "foo") (param i32) (result i64) + unreachable + ) ) "#; smoke_test_exports(test, 11) @@ -30,15 +32,15 @@ fn smoke_test_single_export() { fn smoke_test_multiple_exports() { let test = r#" (module - (func (export "a") (param i32) (result i64) - unreachable - ) - (func (export "b") - unreachable - ) - (func (export "c") - unreachable - ) + (func (export "a") (param i32) (result i64) + unreachable + ) + (func (export "b") + unreachable + ) + (func (export "c") + unreachable + ) ) "#; smoke_test_exports(test, 12) @@ -48,9 +50,9 @@ fn smoke_test_multiple_exports() { fn smoke_test_exported_global() { let test = r#" (module - (func (export "a") (param i32 i32 f32 f64) (result f32) - unreachable - ) + (func (export "a") (param i32 i32 f32 f64) (result f32) + unreachable + ) (global (export "glob") f64 f64.const 0) ) "#; |