diff --git a/src/hostcalls.rs b/src/hostcalls.rs index 3be889e244..6726d3e369 100644 --- a/src/hostcalls.rs +++ b/src/hostcalls.rs @@ -42,7 +42,7 @@ pub fn args_get( let arg_bytes = arg.as_bytes_with_nul(); let arg_ptr = argv_buf + argv_buf_offset; - if let Err(e) = unsafe { enc_slice_of(memory, arg_bytes, arg_ptr) } { + if let Err(e) = enc_slice_of(memory, arg_bytes, arg_ptr) { return enc_errno(e); } @@ -58,11 +58,9 @@ pub fn args_get( } } - unsafe { - enc_slice_of(memory, argv.as_slice(), argv_ptr) - .map(|_| wasm32::__WASI_ESUCCESS) - .unwrap_or_else(|e| e) - } + enc_slice_of(memory, argv.as_slice(), argv_ptr) + .map(|_| wasm32::__WASI_ESUCCESS) + .unwrap_or_else(|e| e) } pub fn args_sizes_get( @@ -78,13 +76,11 @@ pub fn args_sizes_get( .map(|arg| arg.as_bytes_with_nul().len()) .sum(); - unsafe { - if let Err(e) = enc_usize_byref(memory, argc_ptr, argc) { - return enc_errno(e); - } - if let Err(e) = enc_usize_byref(memory, argv_buf_size_ptr, argv_size) { - return enc_errno(e); - } + if let Err(e) = enc_usize_byref(memory, argc_ptr, argc) { + return enc_errno(e); + } + if let Err(e) = enc_usize_byref(memory, argv_buf_size_ptr, argv_size) { + return enc_errno(e); } wasm32::__WASI_ESUCCESS } @@ -115,20 +111,17 @@ pub fn clock_res_get( (timespec.tv_sec as host::__wasi_timestamp_t) .checked_mul(1_000_000_000) .and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as host::__wasi_timestamp_t)) - .map(|resolution| { + .map_or(wasm32::__WASI_EOVERFLOW, |resolution| { // a supported clock can never return zero; this case will probably never get hit, but // make sure we follow the spec if resolution == 0 { wasm32::__WASI_EINVAL } else { - unsafe { - enc_timestamp_byref(memory, resolution_ptr, resolution) - .map(|_| wasm32::__WASI_ESUCCESS) - .unwrap_or_else(|e| e) - } + enc_timestamp_byref(memory, resolution_ptr, resolution) + .map(|_| wasm32::__WASI_ESUCCESS) + .unwrap_or_else(|e| e) } }) - .unwrap_or(wasm32::__WASI_EOVERFLOW) } pub fn clock_time_get( @@ -160,12 +153,11 @@ pub fn clock_time_get( (timespec.tv_sec as host::__wasi_timestamp_t) .checked_mul(1_000_000_000) .and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as host::__wasi_timestamp_t)) - .map(|time| unsafe { + .map_or(wasm32::__WASI_EOVERFLOW, |time| { enc_timestamp_byref(memory, time_ptr, time) .map(|_| wasm32::__WASI_ESUCCESS) .unwrap_or_else(|e| e) }) - .unwrap_or(wasm32::__WASI_EOVERFLOW) } pub fn environ_get( @@ -181,7 +173,7 @@ pub fn environ_get( let env_bytes = pair.as_bytes_with_nul(); let env_ptr = environ_buf + environ_buf_offset; - if let Err(e) = unsafe { enc_slice_of(memory, env_bytes, env_ptr) } { + if let Err(e) = enc_slice_of(memory, env_bytes, env_ptr) { return enc_errno(e); } @@ -197,11 +189,9 @@ pub fn environ_get( } } - unsafe { - enc_slice_of(memory, environ.as_slice(), environ_ptr) - .map(|_| wasm32::__WASI_ESUCCESS) - .unwrap_or_else(|e| e) - } + enc_slice_of(memory, environ.as_slice(), environ_ptr) + .map(|_| wasm32::__WASI_ESUCCESS) + .unwrap_or_else(|e| e) } pub fn environ_sizes_get( @@ -214,13 +204,11 @@ pub fn environ_sizes_get( if let Some(environ_size) = wasi_ctx.env.iter().try_fold(0, |acc: u32, pair| { acc.checked_add(pair.as_bytes_with_nul().len() as u32) }) { - unsafe { - if let Err(e) = enc_usize_byref(memory, environ_count_ptr, environ_count) { - return enc_errno(e); - } - if let Err(e) = enc_usize_byref(memory, environ_size_ptr, environ_size as usize) { - return enc_errno(e); - } + if let Err(e) = enc_usize_byref(memory, environ_count_ptr, environ_count) { + return enc_errno(e); + } + if let Err(e) = enc_usize_byref(memory, environ_size_ptr, environ_size as usize) { + return enc_errno(e); } wasm32::__WASI_ESUCCESS } else { @@ -254,7 +242,7 @@ pub fn fd_fdstat_get( fdstat_ptr: wasm32::uintptr_t, // *mut wasm32::__wasi_fdstat_t ) -> wasm32::__wasi_errno_t { let host_fd = dec_fd(fd); - let mut host_fdstat = match unsafe { dec_fdstat_byref(memory, fdstat_ptr) } { + let mut host_fdstat = match dec_fdstat_byref(memory, fdstat_ptr) { Ok(host_fdstat) => host_fdstat, Err(e) => return enc_errno(e), }; @@ -275,10 +263,8 @@ pub fn fd_fdstat_get( wasm32::__WASI_EBADF }; - unsafe { - enc_fdstat_byref(memory, fdstat_ptr, host_fdstat) - .expect("can write back into the pointer we read from"); - } + enc_fdstat_byref(memory, fdstat_ptr, host_fdstat) + .expect("can write back into the pointer we read from"); errno } @@ -337,11 +323,9 @@ pub fn fd_seek( } }; - unsafe { - enc_filesize_byref(memory, newoffset, host_newoffset as u64) - .map(|_| wasm32::__WASI_ESUCCESS) - .unwrap_or_else(|e| e) - } + enc_filesize_byref(memory, newoffset, host_newoffset as u64) + .map(|_| wasm32::__WASI_ESUCCESS) + .unwrap_or_else(|e| e) } pub fn fd_prestat_get( @@ -358,23 +342,20 @@ pub fn fd_prestat_get( if fe.fd_object.ty != host::__WASI_FILETYPE_DIRECTORY { return wasm32::__WASI_ENOTDIR; } - unsafe { - enc_prestat_byref( - memory, - prestat_ptr, - host::__wasi_prestat_t { - pr_type: host::__WASI_PREOPENTYPE_DIR, - u: host::__wasi_prestat_t___wasi_prestat_u { - dir: - host::__wasi_prestat_t___wasi_prestat_u___wasi_prestat_u_dir_t { - pr_name_len: po_path.as_os_str().as_bytes().len(), - }, + enc_prestat_byref( + memory, + prestat_ptr, + host::__wasi_prestat_t { + pr_type: host::__WASI_PREOPENTYPE_DIR, + u: host::__wasi_prestat_t___wasi_prestat_u { + dir: host::__wasi_prestat_t___wasi_prestat_u___wasi_prestat_u_dir_t { + pr_name_len: po_path.as_os_str().as_bytes().len(), }, }, - ) - .map(|_| wasm32::__WASI_ESUCCESS) - .unwrap_or_else(|e| e) - } + }, + ) + .map(|_| wasm32::__WASI_ESUCCESS) + .unwrap_or_else(|e| e) } else { wasm32::__WASI_ENOTSUP } @@ -402,11 +383,9 @@ pub fn fd_prestat_dir_name( if path_bytes.len() > dec_usize(path_len) { return wasm32::__WASI_ENAMETOOLONG; } - unsafe { - enc_slice_of(memory, path_bytes, path_ptr) - .map(|_| wasm32::__WASI_ESUCCESS) - .unwrap_or_else(|e| e) - } + enc_slice_of(memory, path_bytes, path_ptr) + .map(|_| wasm32::__WASI_ESUCCESS) + .unwrap_or_else(|e| e) } else { wasm32::__WASI_ENOTSUP } @@ -426,7 +405,7 @@ pub fn fd_read( use nix::sys::uio::{readv, IoVec}; let fd = dec_fd(fd); - let mut iovs = match unsafe { dec_ciovec_slice(memory, iovs_ptr, iovs_len) } { + let mut iovs = match dec_ciovec_slice(memory, iovs_ptr, iovs_len) { Ok(iovs) => iovs, Err(e) => return enc_errno(e), }; @@ -452,11 +431,9 @@ pub fn fd_read( fe.fd_object.needs_close = false; } - unsafe { - enc_usize_byref(memory, nread, host_nread) - .map(|_| wasm32::__WASI_ESUCCESS) - .unwrap_or_else(|e| e) - } + enc_usize_byref(memory, nread, host_nread) + .map(|_| wasm32::__WASI_ESUCCESS) + .unwrap_or_else(|e| e) } pub fn fd_write( @@ -470,7 +447,7 @@ pub fn fd_write( use nix::sys::uio::{writev, IoVec}; let fd = dec_fd(fd); - let iovs = match unsafe { dec_ciovec_slice(memory, iovs_ptr, iovs_len) } { + let iovs = match dec_ciovec_slice(memory, iovs_ptr, iovs_len) { Ok(iovs) => iovs, Err(e) => return enc_errno(e), }; @@ -490,11 +467,9 @@ pub fn fd_write( Err(e) => return wasm32::errno_from_nix(e.as_errno().unwrap()), }; - unsafe { - enc_usize_byref(memory, nwritten, host_nwritten) - .map(|_| wasm32::__WASI_ESUCCESS) - .unwrap_or_else(|e| e) - } + enc_usize_byref(memory, nwritten, host_nwritten) + .map(|_| wasm32::__WASI_ESUCCESS) + .unwrap_or_else(|e| e) } pub fn path_open( @@ -564,7 +539,7 @@ pub fn path_open( needed_inheriting |= host::__WASI_RIGHT_FD_SYNC; } - let path = match unsafe { dec_slice_of::(memory, path_ptr, path_len) } { + let path = match dec_slice_of::(memory, path_ptr, path_len) { Ok((ptr, len)) => OsStr::from_bytes(unsafe { std::slice::from_raw_parts(ptr, len) }), Err(e) => return enc_errno(e), }; @@ -630,11 +605,9 @@ pub fn path_open( } }; - unsafe { - enc_fd_byref(memory, fd_out_ptr, guest_fd) - .map(|_| wasm32::__WASI_ESUCCESS) - .unwrap_or_else(|e| e) - } + enc_fd_byref(memory, fd_out_ptr, guest_fd) + .map(|_| wasm32::__WASI_ESUCCESS) + .unwrap_or_else(|e| e) } pub fn random_get( @@ -645,7 +618,7 @@ pub fn random_get( use rand::{thread_rng, RngCore}; let buf_len = dec_usize(buf_len); - let buf_ptr = match unsafe { dec_ptr(memory, buf_ptr, buf_len) } { + let buf_ptr = match dec_ptr(memory, buf_ptr, buf_len) { Ok(ptr) => ptr, Err(e) => return enc_errno(e), }; @@ -667,14 +640,13 @@ pub fn poll_oneoff( if nsubscriptions as u64 > wasm32::__wasi_filesize_t::max_value() { return wasm32::__WASI_EINVAL; } - unsafe { enc_pointee(memory, nevents, 0) }.unwrap(); + enc_pointee(memory, nevents, 0).unwrap(); let input_slice_ = - unsafe { dec_slice_of::(memory, input, nsubscriptions) } - .unwrap(); + dec_slice_of::(memory, input, nsubscriptions).unwrap(); let input_slice = unsafe { slice::from_raw_parts(input_slice_.0, input_slice_.1) }; let output_slice_ = - unsafe { dec_slice_of::(memory, output, nsubscriptions) }.unwrap(); + dec_slice_of::(memory, output, nsubscriptions).unwrap(); let output_slice = unsafe { slice::from_raw_parts_mut(output_slice_.0, output_slice_.1) }; let input: Vec<_> = input_slice.iter().map(|x| dec_subscription(x)).collect(); @@ -727,7 +699,7 @@ pub fn poll_oneoff( delay: cmp::min(delay, c_int::max_value() as u128), userdata, }); - let poll_timeout = timeout.map(|timeout| timeout.delay as c_int).unwrap_or(-1); + let poll_timeout = timeout.map_or(-1, |timeout| timeout.delay as c_int); let ready = loop { match nix::poll::poll(&mut poll_fds, poll_timeout) { Err(_) => { @@ -761,10 +733,8 @@ pub fn fd_filestat_get( Err(e) => wasm32::errno_from_nix(e.as_errno().unwrap()), Ok(filestat) => { let host_filestat = host::filestat_from_nix(filestat); - unsafe { - enc_filestat_byref(memory, filestat_ptr, host_filestat) - .expect("can write into the pointer"); - } + enc_filestat_byref(memory, filestat_ptr, host_filestat) + .expect("can write into the pointer"); wasm32::__WASI_ESUCCESS } } @@ -788,7 +758,7 @@ pub fn path_filestat_get( let dirfd = dec_fd(dirfd); let dirflags = dec_lookupflags(dirflags); - let path = match unsafe { dec_slice_of::(memory, path_ptr, path_len) } { + let path = match dec_slice_of::(memory, path_ptr, path_len) { Ok((ptr, len)) => OsStr::from_bytes(unsafe { std::slice::from_raw_parts(ptr, len) }), Err(e) => return enc_errno(e), }; @@ -813,10 +783,8 @@ pub fn path_filestat_get( Err(e) => wasm32::errno_from_nix(e.as_errno().unwrap()), Ok(filestat) => { let host_filestat = host::filestat_from_nix(filestat); - unsafe { - enc_filestat_byref(memory, filestat_ptr, host_filestat) - .expect("can write into the pointer"); - } + enc_filestat_byref(memory, filestat_ptr, host_filestat) + .expect("can write into the pointer"); wasm32::__WASI_ESUCCESS } } @@ -833,7 +801,7 @@ pub fn path_create_directory( use nix::libc::mkdirat; let dirfd = dec_fd(dirfd); - let path = match unsafe { dec_slice_of::(memory, path_ptr, path_len) } { + let path = match dec_slice_of::(memory, path_ptr, path_len) { Ok((ptr, len)) => OsStr::from_bytes(unsafe { std::slice::from_raw_parts(ptr, len) }), Err(e) => return enc_errno(e), }; @@ -872,7 +840,7 @@ pub fn path_unlink_file( use nix::libc::unlinkat; let dirfd = dec_fd(dirfd); - let path = match unsafe { dec_slice_of::(memory, path_ptr, path_len) } { + let path = match dec_slice_of::(memory, path_ptr, path_len) { Ok((ptr, len)) => OsStr::from_bytes(unsafe { std::slice::from_raw_parts(ptr, len) }), Err(e) => return enc_errno(e), }; @@ -1191,12 +1159,12 @@ fn poll_oneoff_handle_timeout_event( }, }; output_slice[0] = enc_event(output_event); - if let Err(e) = unsafe { enc_pointee(memory, nevents, 1) } { + if let Err(e) = enc_pointee(memory, nevents, 1) { return enc_errno(e); } } else { // shouldn't happen - if let Err(e) = unsafe { enc_pointee(memory, nevents, 0) } { + if let Err(e) = enc_pointee(memory, nevents, 0) { return enc_errno(e); } } @@ -1280,7 +1248,7 @@ fn poll_oneoff_handle_fd_event<'t>( *output_slice_cur.next().unwrap() = enc_event(output_event); revents_count += 1; } - if let Err(e) = unsafe { enc_pointee(memory, nevents, revents_count) } { + if let Err(e) = enc_pointee(memory, nevents, revents_count) { return enc_errno(e); } wasm32::__WASI_ESUCCESS diff --git a/src/memory.rs b/src/memory.rs index 2c283fd0aa..5a2f6b6512 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -14,6 +14,7 @@ use crate::{host, wasm32}; use cast; use cast::From as _0; use std::mem::{align_of, size_of}; +use std::ptr; use std::slice; macro_rules! bail_errno { @@ -22,56 +23,53 @@ macro_rules! bail_errno { }; } -pub unsafe fn dec_ptr( +pub fn dec_ptr( memory: &mut [u8], ptr: wasm32::uintptr_t, len: usize, ) -> Result<*mut u8, host::__wasi_errno_t> { - // check that `len` fits in the wasm32 address space - if len > wasm32::UINTPTR_MAX as usize { - bail_errno!(__WASI_EOVERFLOW); - } - - // check that `ptr` and `ptr + len` are both within the guest heap - if ptr as usize > memory.len() || ptr as usize + len > memory.len() { - bail_errno!(__WASI_EFAULT); - } + // check for overflow + let checked_len = (ptr as usize).checked_add(len).ok_or(host::__WASI_EFAULT)?; // translate the pointer - Ok(memory.as_mut_ptr().offset(ptr as isize)) + memory + .get_mut(ptr as usize..checked_len) + .ok_or(host::__WASI_EFAULT) + .map(|mem| mem.as_mut_ptr()) } -pub unsafe fn dec_ptr_to( - memory: &mut [u8], +pub fn dec_ptr_to<'memory, T>( + memory: &'memory mut [u8], ptr: wasm32::uintptr_t, -) -> Result<*mut T, host::__wasi_errno_t> { +) -> Result<&'memory mut T, host::__wasi_errno_t> { // check that the ptr is aligned if ptr as usize % align_of::() != 0 { bail_errno!(__WASI_EINVAL); } - dec_ptr(memory, ptr, size_of::()).map(|p| p as *mut T) + + dec_ptr(memory, ptr, size_of::()).map(|p| unsafe { &mut *(p as *mut T) }) } -pub unsafe fn dec_pointee( +pub fn dec_pointee( memory: &mut [u8], ptr: wasm32::uintptr_t, ) -> Result { - dec_ptr_to::(memory, ptr).map(|p| p.read()) + dec_ptr_to::(memory, ptr).map(|p| unsafe { ptr::read(p) }) } -pub unsafe fn enc_pointee( +pub fn enc_pointee( memory: &mut [u8], ptr: wasm32::uintptr_t, t: T, ) -> Result<(), host::__wasi_errno_t> { - dec_ptr_to::(memory, ptr).map(|p| p.write(t)) + dec_ptr_to::(memory, ptr).map(|p| unsafe { ptr::write(p, t) }) } -pub unsafe fn dec_slice_of( - memory: &mut [u8], +pub fn dec_slice_of<'memory, T>( + memory: &'memory mut [u8], ptr: wasm32::uintptr_t, len: wasm32::size_t, -) -> Result<(*mut T, usize), host::__wasi_errno_t> { +) -> Result<(&'memory mut T, usize), host::__wasi_errno_t> { // check alignment, and that length doesn't overflow if ptr as usize % align_of::() != 0 { return Err(host::__WASI_EINVAL); @@ -84,11 +82,10 @@ pub unsafe fn dec_slice_of( }; let ptr = dec_ptr(memory, ptr, len_bytes)? as *mut T; - - Ok((ptr, len)) + Ok((unsafe { &mut *ptr }, len)) } -pub unsafe fn enc_slice_of( +pub fn enc_slice_of( memory: &mut [u8], slice: &[T], ptr: wasm32::uintptr_t, @@ -106,7 +103,9 @@ pub unsafe fn enc_slice_of( // get the pointer into guest memory, and copy the bytes let ptr = dec_ptr(memory, ptr, len_bytes)? as *mut libc::c_void; - libc::memcpy(ptr, slice.as_ptr() as *const libc::c_void, len_bytes); + unsafe { + libc::memcpy(ptr, slice.as_ptr() as *const libc::c_void, len_bytes); + } Ok(()) } @@ -117,7 +116,7 @@ macro_rules! dec_enc_scalar { host::$ty::from_le(x) } - pub unsafe fn $dec_byref( + pub fn $dec_byref( memory: &mut [u8], ptr: wasm32::uintptr_t, ) -> Result { @@ -128,7 +127,7 @@ macro_rules! dec_enc_scalar { x.to_le() } - pub unsafe fn $enc_byref( + pub fn $enc_byref( memory: &mut [u8], ptr: wasm32::uintptr_t, x: host::$ty, @@ -138,7 +137,7 @@ macro_rules! dec_enc_scalar { }; } -pub unsafe fn dec_ciovec( +pub fn dec_ciovec( memory: &mut [u8], ciovec: &wasm32::__wasi_ciovec_t, ) -> Result { @@ -149,13 +148,13 @@ pub unsafe fn dec_ciovec( }) } -pub unsafe fn dec_ciovec_slice( +pub fn dec_ciovec_slice( memory: &mut [u8], ptr: wasm32::uintptr_t, len: wasm32::size_t, ) -> Result, host::__wasi_errno_t> { let slice = dec_slice_of::(memory, ptr, len)?; - let slice = slice::from_raw_parts(slice.0, slice.1); + let slice = unsafe { slice::from_raw_parts(slice.0, slice.1) }; slice.iter().map(|iov| dec_ciovec(memory, iov)).collect() } @@ -223,7 +222,7 @@ pub fn dec_filestat(filestat: wasm32::__wasi_filestat_t) -> host::__wasi_filesta } } -pub unsafe fn dec_filestat_byref( +pub fn dec_filestat_byref( memory: &mut [u8], filestat_ptr: wasm32::uintptr_t, ) -> Result { @@ -243,7 +242,7 @@ pub fn enc_filestat(filestat: host::__wasi_filestat_t) -> wasm32::__wasi_filesta } } -pub unsafe fn enc_filestat_byref( +pub fn enc_filestat_byref( memory: &mut [u8], filestat_ptr: wasm32::uintptr_t, host_filestat: host::__wasi_filestat_t, @@ -261,7 +260,7 @@ pub fn dec_fdstat(fdstat: wasm32::__wasi_fdstat_t) -> host::__wasi_fdstat_t { } } -pub unsafe fn dec_fdstat_byref( +pub fn dec_fdstat_byref( memory: &mut [u8], fdstat_ptr: wasm32::uintptr_t, ) -> Result { @@ -278,7 +277,7 @@ pub fn enc_fdstat(fdstat: host::__wasi_fdstat_t) -> wasm32::__wasi_fdstat_t { } } -pub unsafe fn enc_fdstat_byref( +pub fn enc_fdstat_byref( memory: &mut [u8], fdstat_ptr: wasm32::uintptr_t, host_fdstat: host::__wasi_fdstat_t, @@ -345,7 +344,7 @@ pub fn dec_prestat( } } -pub unsafe fn dec_prestat_byref( +pub fn dec_prestat_byref( memory: &mut [u8], prestat_ptr: wasm32::uintptr_t, ) -> Result { @@ -371,7 +370,7 @@ pub fn enc_prestat( } } -pub unsafe fn enc_prestat_byref( +pub fn enc_prestat_byref( memory: &mut [u8], prestat_ptr: wasm32::uintptr_t, host_prestat: host::__wasi_prestat_t, @@ -403,7 +402,7 @@ pub fn enc_usize(size: usize) -> wasm32::size_t { wasm32::size_t::cast(size).unwrap() } -pub unsafe fn enc_usize_byref( +pub fn enc_usize_byref( memory: &mut [u8], usize_ptr: wasm32::uintptr_t, host_usize: usize,