Skip to content

Commit 46dccb9

Browse files
GentleGentlefitzgen
authored
add option for reference-types (#124)
* add option for reference_types only enables the wasmtime feature, which allows initializing Modules that were compiled with newer llvm versions but don't actually use reference_types Disabled by default * Update src/lib.rs Co-authored-by: Nick Fitzgerald <[email protected]> * reject reference-types related instructions * add setter for wasm_reference_types * bail instead of unreachable * tests for reference-types still rejecting tyble modifying instructions * better error messages * test indirect call with reference_types enabled * same docstring for library and cli * (hopefully) actually use the new call_indirect --------- Co-authored-by: Gentle <[email protected]> Co-authored-by: Nick Fitzgerald <[email protected]>
1 parent e860c76 commit 46dccb9

File tree

2 files changed

+155
-3
lines changed

2 files changed

+155
-3
lines changed

src/lib.rs

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ const DEFAULT_WASM_MULTI_VALUE: bool = true;
4242
const DEFAULT_WASM_MULTI_MEMORY: bool = true;
4343
const DEFAULT_WASM_BULK_MEMORY: bool = false;
4444
const DEFAULT_WASM_SIMD: bool = true;
45+
const DEFAULT_WASM_REFERENCE_TYPES: bool = false;
4546

4647
/// The type of data that is stored in the `wasmtime::Store` during
4748
/// initialization.
@@ -249,6 +250,16 @@ pub struct Wizer {
249250
/// Enabled by default.
250251
#[cfg_attr(feature = "structopt", structopt(long, value_name = "true|false"))]
251252
wasm_simd: Option<bool>,
253+
254+
/// Enable or disable the Wasm reference-types proposal.
255+
///
256+
/// Currently does not implement snapshotting or the use of references,
257+
/// but enables initializing Wasm modules that use encodings introduced
258+
/// in the reference-types proposal.
259+
///
260+
/// Disabled by default.
261+
#[cfg_attr(feature = "structopt", structopt(long, value_name = "true|false"))]
262+
wasm_reference_types: Option<bool>,
252263
}
253264

254265
impl std::fmt::Debug for Wizer {
@@ -269,6 +280,7 @@ impl std::fmt::Debug for Wizer {
269280
wasm_multi_value,
270281
wasm_bulk_memory,
271282
wasm_simd,
283+
wasm_reference_types,
272284
} = self;
273285
f.debug_struct("Wizer")
274286
.field("init_func", &init_func)
@@ -286,6 +298,7 @@ impl std::fmt::Debug for Wizer {
286298
.field("wasm_multi_value", &wasm_multi_value)
287299
.field("wasm_bulk_memory", &wasm_bulk_memory)
288300
.field("wasm_simd", &wasm_simd)
301+
.field("wasm_reference_types", &wasm_reference_types)
289302
.finish()
290303
}
291304
}
@@ -350,6 +363,7 @@ impl Wizer {
350363
wasm_multi_value: None,
351364
wasm_bulk_memory: None,
352365
wasm_simd: None,
366+
wasm_reference_types: None,
353367
}
354368
}
355369

@@ -556,6 +570,18 @@ impl Wizer {
556570
self
557571
}
558572

573+
/// Enable or disable the Wasm reference-types proposal.
574+
///
575+
/// Currently does not implement snapshotting or the use of references,
576+
/// but enables initializing Wasm modules that use encodings introduced
577+
/// in the reference-types proposal.
578+
///
579+
/// Defaults to `false`.
580+
pub fn wasm_reference_types(&mut self, enable: bool) -> &mut Self {
581+
self.wasm_reference_types = Some(enable);
582+
self
583+
}
584+
559585
/// Initialize the given Wasm, snapshot it, and return the serialized
560586
/// snapshot as a new, pre-initialized Wasm module.
561587
pub fn run(&self, wasm: &[u8]) -> anyhow::Result<Vec<u8>> {
@@ -632,8 +658,14 @@ impl Wizer {
632658

633659
config.wasm_simd(self.wasm_simd.unwrap_or(DEFAULT_WASM_SIMD));
634660

661+
// Note that reference_types are not actually supported,
662+
// but many compilers now enable them by default
663+
config.wasm_reference_types(
664+
self.wasm_reference_types
665+
.unwrap_or(DEFAULT_WASM_REFERENCE_TYPES),
666+
);
667+
635668
// Proposals that we should add support for.
636-
config.wasm_reference_types(false);
637669
config.wasm_threads(false);
638670

639671
Ok(config)
@@ -654,7 +686,9 @@ impl Wizer {
654686
multi_value: self.wasm_multi_value.unwrap_or(DEFAULT_WASM_MULTI_VALUE),
655687

656688
// Proposals that we should add support for.
657-
reference_types: false,
689+
reference_types: self
690+
.wasm_reference_types
691+
.unwrap_or(DEFAULT_WASM_REFERENCE_TYPES),
658692
simd: self.wasm_simd.unwrap_or(DEFAULT_WASM_SIMD),
659693
threads: false,
660694
tail_call: false,
@@ -730,7 +764,31 @@ impl Wizer {
730764
anyhow::bail!("unsupported `data.drop` instruction")
731765
}
732766
wasmparser::Operator::TableSet { .. } => {
733-
unreachable!("part of reference types")
767+
anyhow::bail!("unsupported `table.set` instruction")
768+
}
769+
wasmparser::Operator::TableGet { .. } => {
770+
anyhow::bail!("unsupported `table.get` instruction")
771+
}
772+
wasmparser::Operator::RefNull { .. } => {
773+
anyhow::bail!("unsupported `ref.null` instruction")
774+
}
775+
wasmparser::Operator::RefIsNull => {
776+
anyhow::bail!("unsupported `ref.is_null` instruction")
777+
}
778+
wasmparser::Operator::TypedSelect { .. } => {
779+
anyhow::bail!("unsupported typed `select` instruction")
780+
}
781+
wasmparser::Operator::RefFunc { .. } => {
782+
anyhow::bail!("unsupported `ref.func` instruction")
783+
}
784+
wasmparser::Operator::TableSize { .. } => {
785+
anyhow::bail!("unsupported `table.size` instruction")
786+
}
787+
wasmparser::Operator::TableGrow { .. } => {
788+
anyhow::bail!("unsupported `table.grow` instruction")
789+
}
790+
wasmparser::Operator::TableFill { .. } => {
791+
anyhow::bail!("unsupported `table.fill` instruction")
734792
}
735793
_ => continue,
736794
}

tests/tests.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,100 @@ fn reject_table_get_set() -> Result<()> {
269269
Ok(())
270270
}
271271

272+
#[test]
273+
fn reject_table_get_set_with_reference_types_enabled() -> Result<()> {
274+
let wat = r#"
275+
(module
276+
(table 3 funcref)
277+
278+
(func $f (result i32) (i32.const 0))
279+
(func $g (result i32) (i32.const 0))
280+
(func $h (result i32) (i32.const 0))
281+
282+
(func (export "main")
283+
i32.const 0
284+
i32.const 1
285+
table.get
286+
table.set)
287+
288+
(elem (i32.const 0) $f $g $h)
289+
)"#;
290+
291+
let _ = env_logger::try_init();
292+
let mut wizer = Wizer::new();
293+
wizer.wasm_reference_types(true);
294+
295+
let wasm = wat_to_wasm(wat)?;
296+
let result = wizen_and_run_wasm(&[], 42, &wasm, wizer);
297+
298+
assert!(result.is_err());
299+
300+
let err = result.unwrap_err();
301+
assert!(err
302+
.to_string()
303+
.contains("unsupported `table.get` instruction"),);
304+
305+
Ok(())
306+
}
307+
308+
#[test]
309+
fn reject_table_grow_with_reference_types_enabled() -> anyhow::Result<()> {
310+
let wat = r#"
311+
(module
312+
(elem declare func $f)
313+
(func $f)
314+
(table 0 funcref)
315+
(func (export "_initialize") (result i32)
316+
ref.func $f
317+
i32.const 1
318+
table.grow
319+
)
320+
)"#;
321+
322+
let _ = env_logger::try_init();
323+
let mut wizer = Wizer::new();
324+
wizer.wasm_reference_types(true);
325+
326+
let wasm = wat_to_wasm(wat)?;
327+
let result = wizen_and_run_wasm(&[], 42, &wasm, wizer);
328+
329+
assert!(result.is_err());
330+
331+
let err = result.unwrap_err();
332+
assert!(err
333+
.to_string()
334+
.contains("unsupported `ref.func` instruction"));
335+
336+
Ok(())
337+
}
338+
339+
#[test]
340+
fn indirect_call_with_reference_types() -> anyhow::Result<()> {
341+
let wat = r#"
342+
(module
343+
(type $sig (func (result i32)))
344+
(table 0 funcref)
345+
(table $table1 1 funcref)
346+
(elem (table $table1) (i32.const 0) func $f)
347+
(func $f (type $sig)
348+
i32.const 42
349+
)
350+
(func (export "wizer.initialize"))
351+
(func (export "run") (result i32)
352+
i32.const 0
353+
call_indirect $table1 (type $sig)
354+
)
355+
)"#;
356+
357+
let _ = env_logger::try_init();
358+
let mut wizer = Wizer::new();
359+
wizer.wasm_reference_types(true);
360+
wizer.wasm_bulk_memory(true);
361+
362+
let wasm = wat_to_wasm(wat)?;
363+
wizen_and_run_wasm(&[], 42, &wasm, wizer)
364+
}
365+
272366
#[test]
273367
fn reject_table_init() -> Result<()> {
274368
let result = run_wat(

0 commit comments

Comments
 (0)