Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wasmparser: Implement missing WasmFeatures configs #482

Merged
3 changes: 3 additions & 0 deletions crates/wasm-shrink/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,9 @@ impl WasmShrink {
memory64: true,
relaxed_simd: true,
extended_const: true,
mutable_global: true,
saturating_float_to_int: true,
sign_extension: true,

// We'll never enable this here.
deterministic_only: false,
Expand Down
3 changes: 3 additions & 0 deletions crates/wasmparser/benches/benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,9 @@ fn validate_benchmark(c: &mut Criterion) {
memory64: true,
extended_const: true,
deterministic_only: false,
mutable_global: true,
saturating_float_to_int: true,
sign_extension: true,
});
return ret;
}
Expand Down
30 changes: 30 additions & 0 deletions crates/wasmparser/src/operators_validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1180,27 +1180,57 @@ impl OperatorValidator {
self.push_operand(Type::F64)?;
}
Operator::I32TruncSatF32S | Operator::I32TruncSatF32U => {
if !self.features.saturating_float_to_int {
return Err(OperatorValidatorError::new(
"saturating float to int conversions support is not enabled",
));
}
self.pop_operand(Some(Type::F32))?;
self.push_operand(Type::I32)?;
}
Operator::I32TruncSatF64S | Operator::I32TruncSatF64U => {
if !self.features.saturating_float_to_int {
return Err(OperatorValidatorError::new(
"saturating float to int conversions support is not enabled",
));
}
self.pop_operand(Some(Type::F64))?;
self.push_operand(Type::I32)?;
}
Operator::I64TruncSatF32S | Operator::I64TruncSatF32U => {
if !self.features.saturating_float_to_int {
return Err(OperatorValidatorError::new(
"saturating float to int conversions support is not enabled",
));
}
self.pop_operand(Some(Type::F32))?;
self.push_operand(Type::I64)?;
}
Operator::I64TruncSatF64S | Operator::I64TruncSatF64U => {
if !self.features.saturating_float_to_int {
return Err(OperatorValidatorError::new(
"saturating float to int conversions support is not enabled",
));
}
self.pop_operand(Some(Type::F64))?;
self.push_operand(Type::I64)?;
}
Operator::I32Extend16S | Operator::I32Extend8S => {
if !self.features.sign_extension {
return Err(OperatorValidatorError::new(
"sign extension operations support is not enabled",
));
}
self.pop_operand(Some(Type::I32))?;
self.push_operand(Type::I32)?;
}

Operator::I64Extend32S | Operator::I64Extend16S | Operator::I64Extend8S => {
if !self.features.sign_extension {
return Err(OperatorValidatorError::new(
"sign extension operations support is not enabled",
));
}
self.pop_operand(Some(Type::I64))?;
self.push_operand(Type::I64)?;
}
Expand Down
19 changes: 19 additions & 0 deletions crates/wasmparser/src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,12 @@ struct ModuleState {
/// Flags for features that are enabled for validation.
#[derive(Hash, Debug, Copy, Clone)]
pub struct WasmFeatures {
/// The WebAssembly `mutable-global` proposal (enabled by default)
pub mutable_global: bool,
/// The WebAssembly `nontrapping-float-to-int-conversions` proposal (enabled by default)
pub saturating_float_to_int: bool,
/// The WebAssembly `sign-extension-ops` proposal (enabled by default)
pub sign_extension: bool,
/// The WebAssembly reference types proposal (enabled by default)
pub reference_types: bool,
/// The WebAssembly multi-value proposal (enabled by default)
Expand Down Expand Up @@ -200,6 +206,9 @@ impl Default for WasmFeatures {
deterministic_only: cfg!(feature = "deterministic"),

// on-by-default features
mutable_global: true,
saturating_float_to_int: true,
sign_extension: true,
bulk_memory: true,
multi_value: true,
reference_types: true,
Expand Down Expand Up @@ -819,6 +828,9 @@ impl Validator {
(state.tags.len(), MAX_WASM_TAGS, "tags")
}
ImportSectionEntryType::Global(ty) => {
if !self.features.mutable_global && ty.mutable {
return self.create_error("mutable global support is not enabled");
}
state.globals.push(ty);
state.num_imported_globals += 1;
(state.globals.len(), MAX_WASM_GLOBALS, "globals")
Expand Down Expand Up @@ -1325,6 +1337,13 @@ impl Validator {
return me.create_error("cannot export types");
}
let ty = me.check_external_kind("exported", e.kind, e.index)?;
if !me.features.mutable_global {
if let EntityType::Global(global_type) = ty {
if global_type.mutable {
return me.create_error("mutable global support is not enabled");
}
}
}
let state = me.cur.state.assert_mut();
state
.exports
Expand Down
3 changes: 3 additions & 0 deletions fuzz/fuzz_targets/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ fuzz_target!(|data: &[u8]| {
exceptions: (byte2 & 0b0000_0100) != 0,
relaxed_simd: (byte2 & 0b0000_1000) != 0,
extended_const: (byte2 & 0b0001_0000) != 0,
mutable_global: (byte2 & 0b0010_0000) != 0,
saturating_float_to_int: (byte2 & 0b0100_0000) != 0,
sign_extension: (byte2 & 0b1000_0000) != 0,
});

drop(validator.validate_all(&data[2..]));
Expand Down
3 changes: 3 additions & 0 deletions src/bin/wasm-tools/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ fn parse_features(arg: &str) -> Result<WasmFeatures> {
("memory64", |f| &mut f.memory64),
("extended-const", |f| &mut f.extended_const),
("deterministic", |f| &mut f.deterministic_only),
("saturating-float-to-int", |f| &mut f.saturating_float_to_int),
("sign-extension", |f| &mut f.sign_extension),
("mutable-global", |f| &mut f.mutable_global),
];

for part in arg.split(',').map(|s| s.trim()).filter(|s| !s.is_empty()) {
Expand Down
14 changes: 14 additions & 0 deletions tests/local/missing-features/mutable-global-disabled.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
(assert_invalid
(module
(import "m0" "g0" (global (mut i32)))
)
"mutable global support is not enabled"
)

(assert_invalid
(module
(global $g0 (mut i32) (i32.const 0))
(export "g0" (global $g0))
)
"mutable global support is not enabled"
)
79 changes: 79 additions & 0 deletions tests/local/missing-features/saturating-float-to-int-disabled.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
(assert_invalid
(module
(func (param f32) (result i32)
local.get 0
i32.trunc_sat_f32_s
)
)
"saturating float to int conversions support is not enabled"
)

(assert_invalid
(module
(func (param f32) (result i32)
local.get 0
i32.trunc_sat_f32_u
)
)
"saturating float to int conversions support is not enabled"
)

(assert_invalid
(module
(func (param f64) (result i32)
local.get 0
i32.trunc_sat_f64_s
)
)
"saturating float to int conversions support is not enabled"
)

(assert_invalid
(module
(func (param f64) (result i32)
local.get 0
i32.trunc_sat_f64_u
)
)
"saturating float to int conversions support is not enabled"
)

(assert_invalid
(module
(func (param f32) (result i64)
local.get 0
i64.trunc_sat_f32_s
)
)
"saturating float to int conversions support is not enabled"
)

(assert_invalid
(module
(func (param f32) (result i64)
local.get 0
i64.trunc_sat_f32_u
)
)
"saturating float to int conversions support is not enabled"
)

(assert_invalid
(module
(func (param f64) (result i64)
local.get 0
i64.trunc_sat_f64_s
)
)
"saturating float to int conversions support is not enabled"
)

(assert_invalid
(module
(func (param f64) (result i64)
local.get 0
i64.trunc_sat_f64_u
)
)
"saturating float to int conversions support is not enabled"
)
49 changes: 49 additions & 0 deletions tests/local/missing-features/sign-extension-disabled.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
(assert_invalid
(module
(func (param i32) (result i32)
local.get 0
i32.extend8_s
)
)
"sign extension operations support is not enabled"
)

(assert_invalid
(module
(func (param i32) (result i32)
local.get 0
i32.extend16_s
)
)
"sign extension operations support is not enabled"
)

(assert_invalid
(module
(func (param i64) (result i64)
local.get 0
i64.extend8_s
)
)
"sign extension operations support is not enabled"
)

(assert_invalid
(module
(func (param i64) (result i64)
local.get 0
i64.extend16_s
)
)
"sign extension operations support is not enabled"
)

(assert_invalid
(module
(func (param i64) (result i64)
local.get 0
i64.extend32_s
)
)
"sign extension operations support is not enabled"
)
6 changes: 6 additions & 0 deletions tests/roundtrip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,9 @@ impl TestState {
multi_memory: true,
memory64: true,
extended_const: true,
saturating_float_to_int: true,
sign_extension: true,
mutable_global: true,
};
for part in test.iter().filter_map(|t| t.to_str()) {
match part {
Expand All @@ -567,6 +570,9 @@ impl TestState {
features.simd = false;
features.reference_types = false;
features.multi_value = false;
features.sign_extension = false;
features.saturating_float_to_int = false;
features.mutable_global = false;
}
"threads" => {
features.threads = true;
Expand Down