wasmer-wasix 0.702.0

WASI and WASIX implementation library for Wasmer WebAssembly runtime
use super::*;

mod call_dynamic;
mod callback_signal;
mod chdir;
mod closure_allocate;
mod closure_free;
mod closure_prepare;
mod context_create;
mod context_destroy;
mod context_switch;
mod dl_invalid_handle;
mod dlopen;
mod dlsym;
mod epoll_create;
mod epoll_ctl;
mod epoll_wait;
mod fd_dup2;
mod fd_fdflags_get;
mod fd_fdflags_set;
mod fd_pipe;
mod futex_wait;
mod futex_wake;
mod futex_wake_all;
mod getcwd;
mod path_open2;
mod port_addr_add;
mod port_addr_clear;
mod port_addr_list;
mod port_addr_remove;
mod port_bridge;
mod port_dhcp_acquire;
mod port_gateway_set;
mod port_mac;
mod port_route_add;
mod port_route_clear;
mod port_route_list;
mod port_route_remove;
mod port_unbridge;
mod proc_exec;
mod proc_exec2;
mod proc_exec3;
mod proc_exec4;
mod proc_exit2;
mod proc_fork;
mod proc_fork_env;
mod proc_id;
mod proc_join;
mod proc_parent;
mod proc_signal;
mod proc_signals_get;
mod proc_signals_sizes_get;
mod proc_snapshot;
mod proc_spawn;
mod proc_spawn2;
mod proc_spawn3;
mod reflect_signature;
mod resolve;
mod sched_yield;
mod sock_accept;
mod sock_addr_local;
mod sock_addr_peer;
mod sock_bind;
mod sock_connect;
mod sock_get_opt_flag;
mod sock_get_opt_size;
mod sock_get_opt_time;
mod sock_join_multicast_v4;
mod sock_join_multicast_v6;
mod sock_leave_multicast_v4;
mod sock_leave_multicast_v6;
mod sock_listen;
mod sock_open;
mod sock_pair;
mod sock_recv;
mod sock_recv_from;
mod sock_send;
mod sock_send_file;
mod sock_send_to;
mod sock_set_opt_flag;
mod sock_set_opt_size;
mod sock_set_opt_time;
mod sock_shutdown;
mod sock_status;
mod stack_checkpoint;
mod stack_restore;
mod thread_exit;
mod thread_id;
mod thread_join;
mod thread_parallelism;
mod thread_signal;
mod thread_sleep;
mod thread_spawn;
mod tty_get;
mod tty_set;

pub use call_dynamic::*;
pub use callback_signal::*;
pub use chdir::*;
pub use closure_allocate::*;
pub use closure_free::*;
pub use closure_prepare::*;
pub use context_create::*;
pub use context_destroy::*;
pub use context_switch::*;
pub use dl_invalid_handle::*;
pub use dlopen::*;
pub use dlsym::*;
pub use epoll_create::*;
pub use epoll_ctl::*;
pub use epoll_wait::*;
pub use fd_dup2::*;
pub use fd_fdflags_get::*;
pub use fd_fdflags_set::*;
pub use fd_pipe::*;
pub use futex_wait::*;
pub use futex_wake::*;
pub use futex_wake_all::*;
pub use getcwd::*;
pub use path_open2::*;
pub use port_addr_add::*;
pub use port_addr_clear::*;
pub use port_addr_list::*;
pub use port_addr_remove::*;
pub use port_bridge::*;
pub use port_dhcp_acquire::*;
pub use port_gateway_set::*;
pub use port_mac::*;
pub use port_route_add::*;
pub use port_route_clear::*;
pub use port_route_list::*;
pub use port_route_remove::*;
pub use port_unbridge::*;
pub use proc_exec::*;
pub use proc_exec2::*;
pub use proc_exec3::*;
pub use proc_exec4::*;
pub use proc_exit2::*;
pub use proc_fork::*;
pub use proc_fork_env::*;
pub use proc_id::*;
pub use proc_join::*;
pub use proc_parent::*;
pub use proc_signal::*;
pub use proc_signals_get::*;
pub use proc_signals_sizes_get::*;
pub use proc_snapshot::*;
pub use proc_spawn::*;
pub use proc_spawn2::*;
pub use proc_spawn3::*;
pub use reflect_signature::*;
pub use resolve::*;
pub use sched_yield::*;
pub use sock_accept::*;
pub use sock_addr_local::*;
pub use sock_addr_peer::*;
pub use sock_bind::*;
pub use sock_connect::*;
pub use sock_get_opt_flag::*;
pub use sock_get_opt_size::*;
pub use sock_get_opt_time::*;
pub use sock_join_multicast_v4::*;
pub use sock_join_multicast_v6::*;
pub use sock_leave_multicast_v4::*;
pub use sock_leave_multicast_v6::*;
pub use sock_listen::*;
pub use sock_open::*;
pub use sock_pair::*;
pub use sock_recv::*;
pub use sock_recv_from::*;
pub use sock_send::*;
pub use sock_send_file::*;
pub use sock_send_to::*;
pub use sock_set_opt_flag::*;
pub use sock_set_opt_size::*;
pub use sock_set_opt_time::*;
pub use sock_shutdown::*;
pub use sock_status::*;
pub use stack_checkpoint::*;
pub use stack_restore::*;
pub use thread_exit::*;
pub use thread_id::*;
pub use thread_join::*;
pub use thread_parallelism::*;
pub use thread_signal::*;
pub use thread_sleep::*;
pub use thread_spawn::*;
pub use tty_get::*;
pub use tty_set::*;

use tracing::{Span, debug_span, field, instrument, trace_span};
use wasmer::WasmRef;

pub(super) fn checked_sock_recv_size<'a, M: MemorySize + 'a>(
    iovs: impl IntoIterator<Item = WasmRef<'a, __wasi_iovec_t<M>>>,
    max_sock_recv_size: Option<u64>,
) -> Result<usize, Errno> {
    let mut max_size = 0usize;
    for iovs in iovs {
        let iovs = iovs.read().map_err(mem_error_to_wasi)?;
        let buf_len = from_offset::<M>(iovs.buf_len)?;
        max_size = max_size.checked_add(buf_len).ok_or(Errno::Overflow)?;
        if let Some(max) = max_sock_recv_size
            && (max_size as u64) > max
        {
            return Err(Errno::Inval);
        }
    }
    Ok(max_size)
}

#[cfg(all(test, not(target_arch = "wasm32")))]
mod tests {
    use super::checked_sock_recv_size;
    use crate::syscalls::types::{__wasi_iovec_t, wasi::Errno};
    use wasmer::{Memory, Memory64, MemoryType, Store, WasmRef};

    #[test]
    fn checked_sock_recv_size_catches_iovec_len_overflow() {
        let mut store = Store::default();
        let memory = Memory::new(&mut store, MemoryType::new(1, None, false)).unwrap();
        let view = memory.view(&store);

        let iovs = [
            __wasi_iovec_t::<Memory64> {
                buf: 0,
                buf_len: usize::MAX as u64,
            },
            __wasi_iovec_t::<Memory64> { buf: 0, buf_len: 1 },
        ];
        let first_iov = WasmRef::new(&view, 0);
        let second_iov = WasmRef::new(
            &view,
            std::mem::size_of::<__wasi_iovec_t<Memory64>>() as u64,
        );
        first_iov.write(iovs[0]).unwrap();
        second_iov.write(iovs[1]).unwrap();

        let err = checked_sock_recv_size::<Memory64>([first_iov, second_iov], Some(u64::MAX))
            .unwrap_err();

        assert_eq!(err, Errno::Overflow);
    }
}