summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wasm-smith
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--third_party/rust/wasm-smith/.cargo-checksum.json2
-rw-r--r--third_party/rust/wasm-smith/Cargo.toml10
-rw-r--r--third_party/rust/wasm-smith/src/component.rs17
-rw-r--r--third_party/rust/wasm-smith/src/config.rs9
-rw-r--r--third_party/rust/wasm-smith/src/core.rs202
-rw-r--r--third_party/rust/wasm-smith/src/core/code_builder.rs77
-rw-r--r--third_party/rust/wasm-smith/src/core/code_builder/no_traps.rs10
-rw-r--r--third_party/rust/wasm-smith/src/core/terminate.rs1
-rw-r--r--third_party/rust/wasm-smith/src/lib.rs6
-rw-r--r--third_party/rust/wasm-smith/tests/common/mod.rs52
-rw-r--r--third_party/rust/wasm-smith/tests/component.rs8
-rw-r--r--third_party/rust/wasm-smith/tests/core.rs55
-rw-r--r--third_party/rust/wasm-smith/tests/exports.rs32
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)
)
"#;