wasm_interp: ensure WASI argv[0] is the .wasm executable

This commit is contained in:
Brian Carroll 2022-12-05 21:45:18 +00:00
parent aa76634751
commit dfbee7b916
No known key found for this signature in database
GPG key ID: 5C7B2EC4101703C0
2 changed files with 13 additions and 8 deletions

View file

@ -153,7 +153,11 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> {
) -> Result<Option<Value>, String> { ) -> Result<Option<Value>, String> {
let arg_type_bytes = self.prepare_to_call_export(module, fn_name)?; let arg_type_bytes = self.prepare_to_call_export(module, fn_name)?;
for (value_str, type_byte) in arg_strings.into_iter().zip(arg_type_bytes.iter().copied()) { for (value_str, type_byte) in arg_strings
.into_iter()
.skip(1) // first string is the .wasm filename
.zip(arg_type_bytes.iter().copied())
{
use ValueType::*; use ValueType::*;
let value = match ValueType::from(type_byte) { let value = match ValueType::from(type_byte) {
I32 => Value::I32(value_str.parse::<i32>().map_err(|e| e.to_string())?), I32 => Value::I32(value_str.parse::<i32>().map_err(|e| e.to_string())?),

View file

@ -1,9 +1,9 @@
use bumpalo::{collections::Vec, Bump}; use bumpalo::{collections::Vec, Bump};
use clap::ArgAction; use clap::ArgAction;
use clap::{Arg, Command}; use clap::{Arg, Command};
use std::ffi::OsString;
use std::fs; use std::fs;
use std::io; use std::io;
use std::iter::once;
use std::process; use std::process;
use roc_wasm_interp::{DefaultImportDispatcher, Instance}; use roc_wasm_interp::{DefaultImportDispatcher, Instance};
@ -16,6 +16,8 @@ pub const WASM_FILE: &str = "WASM_FILE";
pub const ARGS_FOR_APP: &str = "ARGS_FOR_APP"; pub const ARGS_FOR_APP: &str = "ARGS_FOR_APP";
fn main() -> io::Result<()> { fn main() -> io::Result<()> {
let arena = Bump::new();
// Define the command line arguments // Define the command line arguments
let flag_function = Arg::new(FLAG_FUNCTION) let flag_function = Arg::new(FLAG_FUNCTION)
@ -38,7 +40,6 @@ fn main() -> io::Result<()> {
let wasm_file_to_run = Arg::new(WASM_FILE) let wasm_file_to_run = Arg::new(WASM_FILE)
.help("The .wasm file to run") .help("The .wasm file to run")
.allow_invalid_utf8(true)
.required(true); .required(true);
let args_for_app = Arg::new(ARGS_FOR_APP) let args_for_app = Arg::new(ARGS_FOR_APP)
@ -62,15 +63,16 @@ fn main() -> io::Result<()> {
let is_debug_mode = matches.get_flag(FLAG_DEBUG); let is_debug_mode = matches.get_flag(FLAG_DEBUG);
let is_hex_format = matches.get_flag(FLAG_HEX); let is_hex_format = matches.get_flag(FLAG_HEX);
let start_arg_strings = matches.get_many::<String>(ARGS_FOR_APP).unwrap_or_default(); let start_arg_strings = matches.get_many::<String>(ARGS_FOR_APP).unwrap_or_default();
let wasm_path = matches.get_one::<String>(WASM_FILE).unwrap();
// WASI expects the .wasm file to be argv[0]
let wasi_argv = Vec::from_iter_in(once(wasm_path).chain(start_arg_strings), &arena);
// Load the WebAssembly binary file // Load the WebAssembly binary file
let wasm_path = matches.get_one::<OsString>(WASM_FILE).unwrap();
let module_bytes = fs::read(wasm_path)?; let module_bytes = fs::read(wasm_path)?;
// Parse the binary data // Parse the binary data
let arena = Bump::new();
let require_relocatable = false; let require_relocatable = false;
let module = match WasmModule::preload(&arena, &module_bytes, require_relocatable) { let module = match WasmModule::preload(&arena, &module_bytes, require_relocatable) {
Ok(m) => m, Ok(m) => m,
@ -84,8 +86,7 @@ fn main() -> io::Result<()> {
// Create an execution instance // Create an execution instance
let args = Vec::from_iter_in(start_arg_strings, &arena); let dispatcher = DefaultImportDispatcher::new(&wasi_argv);
let dispatcher = DefaultImportDispatcher::new(&args);
let mut inst = let mut inst =
Instance::for_module(&arena, &module, dispatcher, is_debug_mode).unwrap_or_else(|e| { Instance::for_module(&arena, &module, dispatcher, is_debug_mode).unwrap_or_else(|e| {
eprintln!("{}", e); eprintln!("{}", e);
@ -94,7 +95,7 @@ fn main() -> io::Result<()> {
// Run // Run
let result = inst.call_export_from_cli(&module, start_fn_name, &args); let result = inst.call_export_from_cli(&module, start_fn_name, &wasi_argv);
// Print out return value, if any // Print out return value, if any