From f2dd752d0d8cd1f9aabc632379645a150ac9d43a Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 4 May 2021 09:45:59 -0700 Subject: [PATCH 1/2] Handle WASI modules with no imports --- lib/engine/src/resolver.rs | 9 +++- lib/wasi/src/lib.rs | 13 ++--- tests/integration/cli/src/assets.rs | 3 +- tests/integration/cli/tests/compile.rs | 2 +- tests/integration/cli/tests/create_exe.rs | 2 +- tests/integration/cli/tests/run.rs | 59 +++++++++++++++++++++++ 6 files changed, 74 insertions(+), 14 deletions(-) create mode 100644 tests/integration/cli/tests/run.rs diff --git a/lib/engine/src/resolver.rs b/lib/engine/src/resolver.rs index a447899c3ea..a86db9ce84e 100644 --- a/lib/engine/src/resolver.rs +++ b/lib/engine/src/resolver.rs @@ -70,7 +70,14 @@ impl NamedResolver for Box { } } -/// `Resolver` implementation that always resolves to `None`. +impl NamedResolver for () { + /// Always returns `None`. + fn resolve_by_name(&self, _module: &str, _field: &str) -> Option { + None + } +} + +/// `Resolver` implementation that always resolves to `None`. Equivalent to `()`. pub struct NullResolver {} impl Resolver for NullResolver { diff --git a/lib/wasi/src/lib.rs b/lib/wasi/src/lib.rs index c0344018de9..fc83dd5e72d 100644 --- a/lib/wasi/src/lib.rs +++ b/lib/wasi/src/lib.rs @@ -88,16 +88,9 @@ impl WasiEnv { ) -> Result, WasiError> { let wasi_versions = get_wasi_versions(module, false).ok_or(WasiError::UnknownWasiVersion)?; - let mut version_iter = wasi_versions.iter(); - let mut resolver: Box = { - let version = version_iter.next().ok_or(WasiError::UnknownWasiVersion)?; - Box::new(generate_import_object_from_env( - module.store(), - self.clone(), - *version, - )) - }; - for version in version_iter { + + let mut resolver: Box = { Box::new(()) }; + for version in wasi_versions.iter() { let new_import_object = generate_import_object_from_env(module.store(), self.clone(), *version); resolver = Box::new(new_import_object.chain_front(resolver)); diff --git a/tests/integration/cli/src/assets.rs b/tests/integration/cli/src/assets.rs index f3ca082a6be..6af9cec29c2 100644 --- a/tests/integration/cli/src/assets.rs +++ b/tests/integration/cli/src/assets.rs @@ -1,10 +1,11 @@ use std::env; use std::path::PathBuf; -pub const ASSET_PATH: &str = concat!( +pub const C_ASSET_PATH: &str = concat!( env!("CARGO_MANIFEST_DIR"), "/../../../lib/c-api/tests/assets" ); +pub const ASSET_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../../../tests/examples"); pub const WASMER_INCLUDE_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../../../lib/c-api"); diff --git a/tests/integration/cli/tests/compile.rs b/tests/integration/cli/tests/compile.rs index fc74a4e0e11..b5b767dffc0 100644 --- a/tests/integration/cli/tests/compile.rs +++ b/tests/integration/cli/tests/compile.rs @@ -12,7 +12,7 @@ const OBJECT_FILE_ENGINE_TEST_C_SOURCE: &[u8] = include_bytes!("object_file_engine_test_c_source.c"); fn object_file_engine_test_wasm_path() -> String { - format!("{}/{}", ASSET_PATH, "qjs.wasm") + format!("{}/{}", C_ASSET_PATH, "qjs.wasm") } /// Data used to run the `wasmer compile` command. diff --git a/tests/integration/cli/tests/create_exe.rs b/tests/integration/cli/tests/create_exe.rs index b8302bccd5a..3669aed28f2 100644 --- a/tests/integration/cli/tests/create_exe.rs +++ b/tests/integration/cli/tests/create_exe.rs @@ -8,7 +8,7 @@ use std::process::Command; use wasmer_integration_tests_cli::*; fn create_exe_test_wasm_path() -> String { - format!("{}/{}", ASSET_PATH, "qjs.wasm") + format!("{}/{}", C_ASSET_PATH, "qjs.wasm") } const JS_TEST_SRC_CODE: &[u8] = b"function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));\n"; diff --git a/tests/integration/cli/tests/run.rs b/tests/integration/cli/tests/run.rs new file mode 100644 index 00000000000..b172c467296 --- /dev/null +++ b/tests/integration/cli/tests/run.rs @@ -0,0 +1,59 @@ +//! Basic tests for the `run` subcommand + +use anyhow::bail; +use std::process::Command; +use wasmer_integration_tests_cli::{ASSET_PATH, C_ASSET_PATH, WASMER_PATH}; + +fn wasi_test_wasm_path() -> String { + format!("{}/{}", C_ASSET_PATH, "qjs.wasm") +} + +fn wasi_test_empty_wat_path() -> String { + format!("{}/{}", ASSET_PATH, "fib.wat") +} + +#[test] +fn run_wasi_works() -> anyhow::Result<()> { + let output = Command::new(WASMER_PATH) + .arg("run") + .arg(wasi_test_wasm_path()) + .arg("--") + .arg("-e") + .arg("print(3 * (4 + 5))") + .output()?; + + if !output.status.success() { + bail!( + "linking failed with: stdout: {}\n\nstderr: {}", + std::str::from_utf8(&output.stdout) + .expect("stdout is not utf8! need to handle arbitrary bytes"), + std::str::from_utf8(&output.stderr) + .expect("stderr is not utf8! need to handle arbitrary bytes") + ); + } + + let stdout_output = std::str::from_utf8(&output.stdout).unwrap(); + assert_eq!(stdout_output, "27\n"); + + Ok(()) +} + +#[test] +fn run_empty_wasi_works() -> anyhow::Result<()> { + let output = Command::new(WASMER_PATH) + .arg("run") + .arg(wasi_test_empty_wat_path()) + .output()?; + + if !output.status.success() { + bail!( + "linking failed with: stdout: {}\n\nstderr: {}", + std::str::from_utf8(&output.stdout) + .expect("stdout is not utf8! need to handle arbitrary bytes"), + std::str::from_utf8(&output.stderr) + .expect("stderr is not utf8! need to handle arbitrary bytes") + ); + } + + Ok(()) +} From 5d41f998ac6ecd0da3dbb82255321f6b85093436 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 4 May 2021 11:20:10 -0700 Subject: [PATCH 2/2] Do not run Wasm with 0 imports as WASI in the CLI --- lib/cli/src/commands/run.rs | 62 ++++++++++++++++-------------- tests/integration/cli/tests/run.rs | 6 +-- 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/lib/cli/src/commands/run.rs b/lib/cli/src/commands/run.rs index 3e0904d44e2..a6c2dfefe62 100644 --- a/lib/cli/src/commands/run.rs +++ b/lib/cli/src/commands/run.rs @@ -156,37 +156,41 @@ impl Run { use wasmer_wasi::WasiVersion; let wasi_versions = Wasi::get_versions(&module); - if let Some(wasi_versions) = wasi_versions { - if wasi_versions.len() >= 2 { - let get_version_list = |versions: &BTreeSet| -> String { - versions - .iter() - .map(|v| format!("`{}`", v.get_namespace_str())) - .collect::>() - .join(", ") - }; - if self.wasi.deny_multiple_wasi_versions { - let version_list = get_version_list(&wasi_versions); - bail!("Found more than 1 WASI version in this module ({}) and `--deny-multiple-wasi-versions` is enabled.", version_list); - } else if !self.wasi.allow_multiple_wasi_versions { - let version_list = get_version_list(&wasi_versions); - warning!("Found more than 1 WASI version in this module ({}). If this is intentional, pass `--allow-multiple-wasi-versions` to suppress this warning.", version_list); + match wasi_versions { + Some(wasi_versions) if !wasi_versions.is_empty() => { + if wasi_versions.len() >= 2 { + let get_version_list = |versions: &BTreeSet| -> String { + versions + .iter() + .map(|v| format!("`{}`", v.get_namespace_str())) + .collect::>() + .join(", ") + }; + if self.wasi.deny_multiple_wasi_versions { + let version_list = get_version_list(&wasi_versions); + bail!("Found more than 1 WASI version in this module ({}) and `--deny-multiple-wasi-versions` is enabled.", version_list); + } else if !self.wasi.allow_multiple_wasi_versions { + let version_list = get_version_list(&wasi_versions); + warning!("Found more than 1 WASI version in this module ({}). If this is intentional, pass `--allow-multiple-wasi-versions` to suppress this warning.", version_list); + } } - } - let program_name = self - .command_name - .clone() - .or_else(|| { - self.path - .file_name() - .map(|f| f.to_string_lossy().to_string()) - }) - .unwrap_or_default(); - return self - .wasi - .execute(module, program_name, self.args.clone()) - .with_context(|| "WASI execution failed"); + let program_name = self + .command_name + .clone() + .or_else(|| { + self.path + .file_name() + .map(|f| f.to_string_lossy().to_string()) + }) + .unwrap_or_default(); + return self + .wasi + .execute(module, program_name, self.args.clone()) + .with_context(|| "WASI execution failed"); + } + // not WASI + _ => (), } } diff --git a/tests/integration/cli/tests/run.rs b/tests/integration/cli/tests/run.rs index b172c467296..7a2ed750eed 100644 --- a/tests/integration/cli/tests/run.rs +++ b/tests/integration/cli/tests/run.rs @@ -8,7 +8,7 @@ fn wasi_test_wasm_path() -> String { format!("{}/{}", C_ASSET_PATH, "qjs.wasm") } -fn wasi_test_empty_wat_path() -> String { +fn test_no_imports_wat_path() -> String { format!("{}/{}", ASSET_PATH, "fib.wat") } @@ -39,10 +39,10 @@ fn run_wasi_works() -> anyhow::Result<()> { } #[test] -fn run_empty_wasi_works() -> anyhow::Result<()> { +fn run_no_imports_wasm_works() -> anyhow::Result<()> { let output = Command::new(WASMER_PATH) .arg("run") - .arg(wasi_test_empty_wat_path()) + .arg(test_no_imports_wat_path()) .output()?; if !output.status.success() {