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

Add a feature for disabling GC types #1731

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/wasm-smith/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use wasm_smith::Config;
use wasmparser::{types::Types, Validator, WasmFeatures};

pub fn parser_features_from_config(config: &Config) -> WasmFeatures {
let mut features = WasmFeatures::MUTABLE_GLOBAL | WasmFeatures::FLOATS;
let mut features = WasmFeatures::MUTABLE_GLOBAL | WasmFeatures::wasm1();
features.set(
WasmFeatures::SATURATING_FLOAT_TO_INT,
config.saturating_float_to_int_enabled,
Expand Down
19 changes: 18 additions & 1 deletion crates/wasmparser/src/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,14 +157,31 @@ define_wasm_features! {
/// Support this feature as long as all leading browsers also support it
/// https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/legacy/Exceptions.md
pub legacy_exceptions: LEGACY_EXCEPTIONS(1 << 25) = false;
/// Whether or not gc types are enabled.
///
/// This feature does not correspond to any WebAssembly proposal nor
/// concept in the specification itself. This is intended to assist
/// embedders in disabling support for GC types at validation time. For
/// example if an engine wants to support all of WebAssembly except
/// a runtime garbage collector it could disable this feature.
///
/// This features is enabled by default and is used to gate types such
/// as `externref` or `anyref`. Note that the requisite WebAssembly
/// proposal must also be enabled for types like `externref`, meaning
/// that it requires both `REFERENCE_TYPES` and `GC_TYPE` to be enabled.
///
/// Note that the `funcref` and `exnref` types are not gated by this
/// feature. Those are expected to not require a full garbage collector
/// so are not gated by this.
pub gc_types: GC_TYPES(1 << 26) = true;
}
}

impl WasmFeatures {
/// Returns the feature set associated with the 1.0 version of the
/// WebAssembly specification or the "MVP" feature set.
pub fn wasm1() -> WasmFeatures {
WasmFeatures::FLOATS
WasmFeatures::FLOATS | WasmFeatures::GC_TYPES
}

/// Returns the feature set associated with the 2.0 version of the
Expand Down
13 changes: 13 additions & 0 deletions crates/wasmparser/src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,12 @@ impl WasmFeatures {
}
match r.heap_type() {
HeapType::Concrete(_) => {
// Note that `self.gc_types()` is not checked here because
// concrete pointers to function types are allowed. GC types
// are disallowed by instead rejecting the definition of
// array/struct types and only allowing the definition of
// function types.

// Indexed types require either the function-references or gc
// proposal as gc implies function references here.
if self.function_references() || self.gc() {
Expand All @@ -266,6 +272,13 @@ impl WasmFeatures {
"shared reference types require the shared-everything-threads proposal",
);
}

// Apply the "gc-types" feature which disallows all heap types
// except exnref/funcref.
if !self.gc_types() && ty != Func && ty != Exn {
return Err("gc types are disallowed but found type which requires gc");
}

match (ty, r.is_nullable()) {
// funcref/externref only require `reference-types`.
(Func, true) | (Extern, true) => Ok(()),
Expand Down
20 changes: 16 additions & 4 deletions crates/wasmparser/src/validator/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -699,10 +699,16 @@ impl Module {
}
CompositeInnerType::Array(t) => {
if !features.gc() {
return Err(BinaryReaderError::new(
bail!(
offset,
"array indexed types not supported without the gc feature",
);
}
if !features.gc_types() {
bail!(
offset,
));
"cannot define array types when gc types are disabled",
);
}
match &t.0.element_type {
StorageType::I8 | StorageType::I16 => {
Expand All @@ -713,10 +719,16 @@ impl Module {
}
CompositeInnerType::Struct(t) => {
if !features.gc() {
return Err(BinaryReaderError::new(
bail!(
offset,
"struct indexed types not supported without the gc feature",
);
}
if !features.gc_types() {
bail!(
offset,
));
"cannot define struct types when gc types are disabled",
);
}
for ft in t.fields.iter() {
match &ft.element_type {
Expand Down
2 changes: 1 addition & 1 deletion tests/cli/validate-unknown-features.wat.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: invalid value 'unknown' for '--features <FEATURES>': unknown feature `unknown`
Valid features: mutable-global, saturating-float-to-int, sign-extension, reference-types, multi-value, bulk-memory, simd, relaxed-simd, threads, shared-everything-threads, tail-call, floats, multi-memory, exceptions, memory64, extended-const, component-model, function-references, memory-control, gc, custom-page-sizes, component-model-values, component-model-nested-names, component-model-more-flags, component-model-multiple-returns, legacy-exceptions
Valid features: mutable-global, saturating-float-to-int, sign-extension, reference-types, multi-value, bulk-memory, simd, relaxed-simd, threads, shared-everything-threads, tail-call, floats, multi-memory, exceptions, memory64, extended-const, component-model, function-references, memory-control, gc, custom-page-sizes, component-model-values, component-model-nested-names, component-model-more-flags, component-model-multiple-returns, legacy-exceptions, gc-types

For more information, try '--help'.
32 changes: 32 additions & 0 deletions tests/local/missing-features/gc/gc-types-disabled.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
(assert_invalid
(module
(type (func (result externref)))
)
"gc types are disallowed")

(assert_invalid
(module
(type (func (result (ref any))))
)
"gc types are disallowed")

(module
(table 1 funcref)
)

(module
(type $t (func))
(table 1 (ref null $t))
)

(assert_invalid
(module
(type (array i8))
)
"cannot define array types")

(assert_invalid
(module
(type (struct))
)
"cannot define struct types")
4 changes: 3 additions & 1 deletion tests/roundtrip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -609,9 +609,11 @@ impl TestState {
features.remove(WasmFeatures::THREADS);
}
"missing-features" => {
features = WasmFeatures::empty() | WasmFeatures::FLOATS;
features =
WasmFeatures::empty() | WasmFeatures::FLOATS | WasmFeatures::GC_TYPES;
}
"floats-disabled.wast" => features.remove(WasmFeatures::FLOATS),
"gc-types-disabled.wast" => features.remove(WasmFeatures::GC_TYPES),
"threads" => {
features.insert(WasmFeatures::THREADS);
features.remove(WasmFeatures::BULK_MEMORY);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"source_filename": "tests/local/missing-features/gc/gc-types-disabled.wast",
"commands": [
{
"type": "assert_invalid",
"line": 2,
"filename": "gc-types-disabled.0.wasm",
"text": "gc types are disallowed",
"module_type": "binary"
},
{
"type": "assert_invalid",
"line": 8,
"filename": "gc-types-disabled.1.wasm",
"text": "gc types are disallowed",
"module_type": "binary"
},
{
"type": "module",
"line": 13,
"filename": "gc-types-disabled.2.wasm"
},
{
"type": "module",
"line": 17,
"filename": "gc-types-disabled.3.wasm"
},
{
"type": "assert_invalid",
"line": 23,
"filename": "gc-types-disabled.4.wasm",
"text": "cannot define array types",
"module_type": "binary"
},
{
"type": "assert_invalid",
"line": 29,
"filename": "gc-types-disabled.5.wasm",
"text": "cannot define struct types",
"module_type": "binary"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
(module
(table (;0;) 1 funcref)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(module
(type $t (;0;) (func))
(table (;0;) 1 (ref null $t))
)