repl_wasm: Graceful handling of invalid Wasm code gen

This commit is contained in:
Brian Carroll 2022-02-25 23:54:40 +00:00
parent 203fdab209
commit 7719f0646e
2 changed files with 33 additions and 10 deletions

View file

@ -59,8 +59,8 @@ struct ReplState {
output: Option<String>, output: Option<String>,
} }
fn wasmer_create_app(app_bytes_ptr: u32, app_bytes_len: u32) { fn wasmer_create_app(app_bytes_ptr: u32, app_bytes_len: u32) -> u32 {
let app = { let app: Instance = {
let memory = COMPILER.exports.get_memory("memory").unwrap(); let memory = COMPILER.exports.get_memory("memory").unwrap();
let memory_bytes: &[u8] = unsafe { memory.data_unchecked() }; let memory_bytes: &[u8] = unsafe { memory.data_unchecked() };
@ -71,7 +71,18 @@ fn wasmer_create_app(app_bytes_ptr: u32, app_bytes_len: u32) {
// Parse the bytes into a Wasmer module // Parse the bytes into a Wasmer module
let store = Store::default(); let store = Store::default();
let wasmer_module = Module::new(&store, app_module_bytes).unwrap(); let wasmer_module = match Module::new(&store, app_module_bytes) {
Ok(m) => m,
Err(e) => {
let path = "/tmp/roc_repl_test_invalid_app.wasm";
fs::write(path, app_module_bytes).unwrap();
println!(
"Failed to create Wasm module\nWrote invalid wasm to {}\n{:?}",
path, e
);
return false.into();
}
};
// Get the WASI imports for the app // Get the WASI imports for the app
let mut wasi_env = WasiState::new("hello").finalize().unwrap(); let mut wasi_env = WasiState::new("hello").finalize().unwrap();
@ -79,8 +90,14 @@ fn wasmer_create_app(app_bytes_ptr: u32, app_bytes_len: u32) {
.import_object(&wasmer_module) .import_object(&wasmer_module)
.unwrap_or_else(|_| imports!()); .unwrap_or_else(|_| imports!());
// Create an executable instance. (Give it a stack & heap, etc. If this was ELF, it would be the OS's job.) // Create an executable instance
Instance::new(&wasmer_module, &import_object).unwrap() match Instance::new(&wasmer_module, &import_object) {
Ok(instance) => instance,
Err(e) => {
println!("Failed to create Wasm instance {:?}", e);
return false.into();
}
}
}; };
REPL_STATE.with(|f| { REPL_STATE.with(|f| {
@ -90,6 +107,8 @@ fn wasmer_create_app(app_bytes_ptr: u32, app_bytes_len: u32) {
unreachable!() unreachable!()
} }
}); });
return true.into();
} }
fn wasmer_run_app() -> u32 { fn wasmer_run_app() -> u32 {
@ -224,7 +243,9 @@ fn run(src: &'static str) -> (bool, String) {
let wasm_ok: i32 = entrypoint.call(&[src_len]).unwrap().deref()[0].unwrap_i32(); let wasm_ok: i32 = entrypoint.call(&[src_len]).unwrap().deref()[0].unwrap_i32();
wasm_ok != 0 wasm_ok != 0
} else { } else {
panic!("Failed to acquire test mutex") panic!(
"Failed to acquire test mutex! A previous test must have panicked while holding it, running Wasm"
)
}; };
let final_state: ReplState = REPL_STATE.with(|rs| rs.take()).unwrap(); let final_state: ReplState = REPL_STATE.with(|rs| rs.take()).unwrap();

View file

@ -1,7 +1,7 @@
use futures::executor; use futures::executor;
extern "C" { extern "C" {
fn wasmer_create_app(app_bytes_ptr: *const u8, app_bytes_len: usize); fn wasmer_create_app(app_bytes_ptr: *const u8, app_bytes_len: usize) -> u32;
fn wasmer_run_app() -> usize; fn wasmer_run_app() -> usize;
fn wasmer_get_result_and_memory(buffer_alloc_addr: *mut u8) -> usize; fn wasmer_get_result_and_memory(buffer_alloc_addr: *mut u8) -> usize;
fn wasmer_copy_input_string(src_buffer_addr: *mut u8); fn wasmer_copy_input_string(src_buffer_addr: *mut u8);
@ -10,10 +10,12 @@ extern "C" {
/// Async wrapper to match the equivalent JS function /// Async wrapper to match the equivalent JS function
pub async fn js_create_app(wasm_module_bytes: &[u8]) -> Result<(), String> { pub async fn js_create_app(wasm_module_bytes: &[u8]) -> Result<(), String> {
unsafe { let ok = unsafe { wasmer_create_app(wasm_module_bytes.as_ptr(), wasm_module_bytes.len()) } != 0;
wasmer_create_app(wasm_module_bytes.as_ptr(), wasm_module_bytes.len()); if ok {
Ok(())
} else {
Err("Compiler generated an invalid Wasm module".to_string())
} }
Ok(())
} }
pub fn js_run_app() -> usize { pub fn js_run_app() -> usize {