diff --git a/lib/wasi/src/lib.rs b/lib/wasi/src/lib.rs index ba91b2aa6..c6908988c 100644 --- a/lib/wasi/src/lib.rs +++ b/lib/wasi/src/lib.rs @@ -1,6 +1,8 @@ #[macro_use] extern crate log; +#[macro_use] +mod macros; mod ptr; mod state; mod syscalls; diff --git a/lib/wasi/src/macros.rs b/lib/wasi/src/macros.rs new file mode 100644 index 000000000..0e00e77b3 --- /dev/null +++ b/lib/wasi/src/macros.rs @@ -0,0 +1,13 @@ +macro_rules! wasi_try { + ($expr:expr) => {{ + let res: Result<_, crate::syscalls::types::__wasi_errno_t> = $expr; + match res { + Ok(val) => val, + Err(err) => return err, + } + }}; + ($expr:expr; $e:expr) => {{ + let opt: Option<_> = $expr; + wasi_try!(opt.ok_or($e)) + }}; +} diff --git a/lib/wasi/src/ptr.rs b/lib/wasi/src/ptr.rs index b4fc7a9a5..56abb3b2d 100644 --- a/lib/wasi/src/ptr.rs +++ b/lib/wasi/src/ptr.rs @@ -1,3 +1,4 @@ +use crate::syscalls::types::{__wasi_errno_t, __WASI_EFAULT}; use std::{cell::Cell, fmt, marker::PhantomData, mem}; use wasmer_runtime_core::{ memory::Memory, @@ -30,27 +31,32 @@ impl WasmPtr { impl WasmPtr { #[inline] - pub fn deref<'a>(self, memory: &'a Memory) -> Option<&'a Cell> { + pub fn deref<'a>(self, memory: &'a Memory) -> Result<&'a Cell, __wasi_errno_t> { if (self.offset as usize) + mem::size_of::() >= memory.size().bytes().0 { - return None; + return Err(__WASI_EFAULT); } unsafe { let cell_ptr = memory .view::() .get_unchecked((self.offset() as usize) / mem::size_of::()) as *const _; - Some(&*cell_ptr) + Ok(&*cell_ptr) } } } impl WasmPtr { #[inline] - pub fn deref<'a>(self, memory: &'a Memory, index: u32, length: u32) -> Option<&'a [Cell]> { + pub fn deref<'a>( + self, + memory: &'a Memory, + index: u32, + length: u32, + ) -> Result<&'a [Cell], __wasi_errno_t> { if (self.offset as usize) + (mem::size_of::() * ((index + length) as usize)) >= memory.size().bytes().0 { - return None; + return Err(__WASI_EFAULT); } unsafe { @@ -59,7 +65,7 @@ impl WasmPtr { ..((self.offset() as usize) / mem::size_of::()) + ((index + length) as usize), ) as *const _; - Some(&*cell_ptrs) + Ok(&*cell_ptrs) } } } diff --git a/lib/wasi/src/state.rs b/lib/wasi/src/state.rs index df1c751b4..ce4139e01 100644 --- a/lib/wasi/src/state.rs +++ b/lib/wasi/src/state.rs @@ -166,31 +166,19 @@ impl WasiFs { path: &str, ) -> Result<__wasi_filestat_t, __wasi_errno_t> { warn!("Should use preopned_fd: {}", preopened_fd); - let inode = if let Some(inode) = self.get_inode(path) { - inode - } else { - return Err(__WASI_EINVAL); - }; + let inode = self.get_inode(path).ok_or(__WASI_EINVAL)?; self.filestat_inode(inode, flags) } pub fn filestat_fd(&self, fd: __wasi_fd_t) -> Result<__wasi_filestat_t, __wasi_errno_t> { - let fd = if let Some(fd) = self.fd_map.get(&fd) { - fd - } else { - return Err(__WASI_EBADF); - }; + let fd = self.fd_map.get(&fd).ok_or(__WASI_EBADF)?; Ok(self.inodes[fd.inode].stat) } pub fn fdstat(&self, fd: __wasi_fd_t) -> Result<__wasi_fdstat_t, __wasi_errno_t> { - let fd = if let Some(fd) = self.fd_map.get(&fd) { - fd - } else { - return Err(__WASI_EBADF); - }; + let fd = self.fd_map.get(&fd).ok_or(__WASI_EBADF)?; Ok(__wasi_fdstat_t { fs_filetype: match self.inodes[fd.inode].kind { diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index 551bc4d62..184856358 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -31,23 +31,13 @@ fn write_buffer_array( ptr_buffer: WasmPtr, Array>, buffer: WasmPtr, ) -> __wasi_errno_t { - let ptrs = if let Some(cells) = ptr_buffer.deref(memory, 0, from.len() as u32) { - cells - } else { - return __WASI_EOVERFLOW; - }; + let ptrs = wasi_try!(ptr_buffer.deref(memory, 0, from.len() as u32)); let mut current_buffer_offset = 0; for ((i, sub_buffer), ptr) in from.iter().enumerate().zip(ptrs.iter()) { ptr.set(WasmPtr::new(buffer.offset() + current_buffer_offset)); - let cells = if let Some(cells) = - buffer.deref(memory, current_buffer_offset, sub_buffer.len() as u32) - { - cells - } else { - return __WASI_EOVERFLOW; - }; + let cells = wasi_try!(buffer.deref(memory, current_buffer_offset, sub_buffer.len() as u32)); for (cell, &byte) in cells.iter().zip(sub_buffer.iter()) { cell.set(byte); @@ -92,16 +82,15 @@ pub fn args_sizes_get( ) -> __wasi_errno_t { let memory = ctx.memory(0); - if let (Some(argc), Some(argv_buf_size)) = (argc.deref(memory), argv_buf_size.deref(memory)) { - let state = get_wasi_state(ctx); + let argc = wasi_try!(argc.deref(memory)); + let argv_buf_size = wasi_try!(argv_buf_size.deref(memory)); - argc.set(state.args.len() as u32); - argv_buf_size.set(state.args.iter().map(|v| v.len() as u32).sum()); + let state = get_wasi_state(ctx); - __WASI_ESUCCESS - } else { - __WASI_EOVERFLOW - } + argc.set(state.args.len() as u32); + argv_buf_size.set(state.args.iter().map(|v| v.len() as u32).sum()); + + __WASI_ESUCCESS } /// ### `clock_res_get()` @@ -119,11 +108,8 @@ pub fn clock_res_get( ) -> __wasi_errno_t { let memory = ctx.memory(0); - if let Some(out_addr) = resolution.deref(memory) { - platform_clock_res_get(clock_id, out_addr) - } else { - __WASI_EFAULT - } + let out_addr = wasi_try!(resolution.deref(memory)); + platform_clock_res_get(clock_id, out_addr) } /// ### `clock_time_get()` @@ -144,11 +130,8 @@ pub fn clock_time_get( ) -> __wasi_errno_t { let memory = ctx.memory(0); - if let Some(out_addr) = time.deref(memory) { - platform_clock_time_get(clock_id, precision, out_addr) - } else { - __WASI_EFAULT - } + let out_addr = wasi_try!(time.deref(memory)); + platform_clock_time_get(clock_id, precision, out_addr) } /// ### `environ_get()` @@ -184,18 +167,15 @@ pub fn environ_sizes_get( ) -> __wasi_errno_t { let memory = ctx.memory(0); - if let (Some(environ_count), Some(environ_buf_size)) = - (environ_count.deref(memory), environ_buf_size.deref(memory)) - { - let state = get_wasi_state(ctx); + let environ_count = wasi_try!(environ_count.deref(memory)); + let environ_buf_size = wasi_try!(environ_buf_size.deref(memory)); - environ_count.set(state.envs.len() as u32); - environ_buf_size.set(state.envs.iter().map(|v| v.len() as u32).sum()); + let state = get_wasi_state(ctx); - __WASI_ESUCCESS - } else { - __WASI_EOVERFLOW - } + environ_count.set(state.envs.len() as u32); + environ_buf_size.set(state.envs.iter().map(|v| v.len() as u32).sum()); + + __WASI_EOVERFLOW } /// ### `fd_advise()` @@ -282,17 +262,12 @@ pub fn fd_fdstat_get( let mut state = get_wasi_state(ctx); let memory = ctx.memory(0); - let stat = match state.fs.fdstat(fd) { - Ok(stat) => stat, - Err(errno) => return errno, - }; + let stat = wasi_try!(state.fs.fdstat(fd)); - if let Some(buf) = buf.deref(memory) { - buf.set(stat); - __WASI_ESUCCESS - } else { - __WASI_EFAULT - } + let buf = wasi_try!(buf.deref(memory)); + buf.set(stat); + + __WASI_EFAULT } /// ### `fd_fdstat_set_flags()` @@ -344,17 +319,12 @@ pub fn fd_filestat_get( let mut state = get_wasi_state(ctx); let memory = ctx.memory(0); - let stat = match state.fs.filestat_fd(fd) { - Ok(stat) => stat, - Err(errno) => return errno, - }; + let stat = wasi_try!(state.fs.filestat_fd(fd)); - if let Some(buf) = buf.deref(memory) { - buf.set(stat); - __WASI_ESUCCESS - } else { - __WASI_EFAULT - } + let buf = wasi_try!(buf.deref(memory)); + buf.set(stat); + + __WASI_ESUCCESS } pub fn fd_filestat_set_size( @@ -384,7 +354,7 @@ pub fn fd_pread( ) -> __wasi_errno_t { let memory = ctx.memory(0); - if let ((Some(iov_cells), Some(nread_cell))) = + if let ((Ok(iov_cells), Ok(nread_cell))) = (iovs.deref(memory, 0, iovs_len), nread.deref(memory)) { platform_fd_pread(fd, iov_cells, iovs_len, offset, nread_cell) @@ -400,7 +370,7 @@ pub fn fd_prestat_get( ) -> __wasi_errno_t { let memory = ctx.memory(0); - if let Some(prestat_ptr) = buf.deref(memory) { + if let Ok(prestat_ptr) = buf.deref(memory) { // open fd // write info to prestat_ptr __WASI_ESUCCESS @@ -417,7 +387,7 @@ pub fn fd_prestat_dir_name( ) -> __wasi_errno_t { let memory = ctx.memory(0); - if let Some(path_chars) = path.deref(memory, 0, path_len) { + if let Ok(path_chars) = path.deref(memory, 0, path_len) { if true /* check if dir */ { @@ -467,7 +437,7 @@ pub fn fd_read( // check __WASI_RIGHT_FD_READ - if let (Some(iovs_arr_cell), Some(nwritten_cell)) = + if let (Ok(iovs_arr_cell), Ok(nwritten_cell)) = (iovs.deref(memory, 0, iovs_len), nread.deref(memory)) { unimplemented!() @@ -501,7 +471,7 @@ pub fn fd_readdir( ) -> __wasi_errno_t { let memory = ctx.memory(0); - if let (Some(buf_arr_cell), Some(bufused_cell)) = + if let (Ok(buf_arr_cell), Ok(bufused_cell)) = (buf.deref(memory, 0, buf_len), bufused.deref(memory)) { unimplemented!() @@ -543,7 +513,7 @@ pub fn fd_seek( let memory = ctx.memory(0); // TODO: check __WASI_RIGHT_FD_SEEK // TODO: handle directory input - if let Some(new_offset_cell) = newoffset.deref(memory) { + if let Ok(new_offset_cell) = newoffset.deref(memory) { unimplemented!() } else { __WASI_EFAULT @@ -605,7 +575,7 @@ pub fn fd_write( let memory = ctx.memory(0); // TODO: check __WASI_RIGHT_FD_WRITE // return __WASI_EISDIR if dir (probably) - if let (Some(iovs_arr_cell), Some(nwritten_cell)) = + if let (Ok(iovs_arr_cell), Ok(nwritten_cell)) = (iovs.deref(memory, 0, iovs_len), nwritten.deref(memory)) { unimplemented!() @@ -659,6 +629,9 @@ pub fn path_filestat_get( path_len: u32, buf: WasmPtr<__wasi_filestat_t>, ) -> __wasi_errno_t { + let mut state = get_wasi_state(ctx); + let memory = ctx.memory(0); + // check __WASI_RIGHT_PATH_FILESTAT_GET unimplemented!() } @@ -768,7 +741,7 @@ pub fn path_open( // check for __WASI_RIGHT_PATH_OPEN somewhere, probably via dirfd - if let (Some(fd_cell), Some(path_cell)) = (fd.deref(memory), path.deref(memory, 0, path_len)) { + if let (Ok(fd_cell), Ok(path_cell)) = (fd.deref(memory), path.deref(memory, 0, path_len)) { // o_flags: // - __WASI_O_FLAG_CREAT (create if it does not exist) // - __WASI_O_DIRECTORY (fail if not dir) @@ -860,7 +833,7 @@ pub fn random_get(ctx: &mut Ctx, buf: WasmPtr, buf_len: u32) -> __was let mut rng = thread_rng(); let memory = ctx.memory(0); - if let Some(buf) = buf.deref(memory, 0, buf_len) { + if let Ok(buf) = buf.deref(memory, 0, buf_len) { for i in 0..(buf_len as usize) { let random_byte = rng.gen::(); buf[i].set(random_byte);