Implement the allow-unknown-exports option for the run command.

This commit implements the `--allow-unknown-exports` option to the CLI run
command that will ignore unknown exports in a command module rather than
return an error.

Fixes #2587.
This commit is contained in:
Peter Huene
2021-05-06 14:19:14 -07:00
parent 6a1a169c62
commit 91f64d40d4
3 changed files with 53 additions and 1 deletions

View File

@@ -37,6 +37,7 @@ pub struct Linker {
strings: Vec<Rc<str>>,
map: HashMap<ImportKey, Extern>,
allow_shadowing: bool,
allow_unknown_exports: bool,
}
#[derive(Hash, PartialEq, Eq)]
@@ -69,6 +70,7 @@ impl Linker {
string2idx: HashMap::new(),
strings: Vec::new(),
allow_shadowing: false,
allow_unknown_exports: false,
}
}
@@ -102,6 +104,32 @@ impl Linker {
self
}
/// Configures whether this [`Linker`] will allow unknown exports from
/// command modules.
///
/// By default a [`Linker`] will error when unknown exports are encountered
/// in a command module while using [`Linker::module`].
///
/// This method can be used to allow unknown exports from command modules.
///
/// # Examples
///
/// ```
/// # use wasmtime::*;
/// # fn main() -> anyhow::Result<()> {
/// # let store = Store::default();
/// # let module = Module::new(store.engine(), "(module)")?;
/// let mut linker = Linker::new(&store);
/// linker.allow_unknown_exports(true);
/// linker.module("mod", &module)?;
/// # Ok(())
/// # }
/// ```
pub fn allow_unknown_exports(&mut self, allow: bool) -> &mut Linker {
self.allow_unknown_exports = allow;
self
}
/// Defines a new item in this [`Linker`].
///
/// This method will add a new definition, by name, to this instance of
@@ -469,7 +497,7 @@ impl Linker {
// Allow an exported "__rtti_base" memory for compatibility with
// AssemblyScript.
warn!("command module exporting '__rtti_base' is deprecated; pass `--runtime half` to the AssemblyScript compiler");
} else {
} else if !self.allow_unknown_exports {
bail!("command export '{}' is not a function", export.name());
}
}

View File

@@ -81,6 +81,10 @@ pub struct RunCommand {
#[structopt(flatten)]
common: CommonOptions,
/// Allow unknown exports when running commands.
#[structopt(long = "allow-unknown-exports")]
allow_unknown_exports: bool,
/// Grant access to the given host directory
#[structopt(long = "dir", number_of_values = 1, value_name = "DIRECTORY")]
dirs: Vec<String>,
@@ -146,6 +150,8 @@ impl RunCommand {
let argv = self.compute_argv();
let mut linker = Linker::new(&store);
linker.allow_unknown_exports(self.allow_unknown_exports);
populate_with_wasi(
&mut linker,
preopen_dirs,

View File

@@ -162,6 +162,24 @@ fn module_interposition() -> Result<()> {
Ok(())
}
#[test]
fn allow_unknown_exports() -> Result<()> {
let store = Store::default();
let mut linker = Linker::new(&store);
let module = Module::new(
store.engine(),
r#"(module (func (export "_start")) (global (export "g") i32 (i32.const 0)))"#,
)?;
assert!(linker.module("module", &module).is_err());
let mut linker = Linker::new(&store);
linker.allow_unknown_exports(true);
linker.module("module", &module)?;
Ok(())
}
#[test]
fn no_leak() -> Result<()> {
struct DropMe(Rc<Cell<bool>>);