diff --git a/lib/runtime-c-api/src/import.rs b/lib/runtime-c-api/src/import.rs index abd35c9d0..bdbc1bea3 100644 --- a/lib/runtime-c-api/src/import.rs +++ b/lib/runtime-c-api/src/import.rs @@ -54,6 +54,7 @@ pub unsafe extern "C" fn wasmer_import_object_new() -> *mut wasmer_import_object #[cfg(feature = "wasi")] mod wasi { use super::*; + use crate::get_slice_checked; use std::path::PathBuf; /// Opens a directory that's visible to the WASI module as `alias` but @@ -76,7 +77,11 @@ mod wasi { } } - /// Creates a WASI import object + /// Creates a WASI import object. + /// + /// This function treats null pointers as empty collections. + /// For example, passing null for a string in `args`, will lead to a zero + /// length argument in that position. #[no_mangle] pub unsafe extern "C" fn wasmer_wasi_generate_import_object( args: *const wasmer_byte_array, @@ -88,11 +93,10 @@ mod wasi { mapped_dirs: *const wasmer_wasi_map_dir_entry_t, mapped_dirs_len: c_uint, ) -> *mut wasmer_import_object_t { - let arg_list = std::slice::from_raw_parts(args, args_len as usize); - let env_list = std::slice::from_raw_parts(envs, envs_len as usize); - let preopened_file_list = - std::slice::from_raw_parts(preopened_files, preopened_files_len as usize); - let mapped_dir_list = std::slice::from_raw_parts(mapped_dirs, mapped_dirs_len as usize); + let arg_list = get_slice_checked(args, args_len as usize); + let env_list = get_slice_checked(envs, envs_len as usize); + let preopened_file_list = get_slice_checked(preopened_files, preopened_files_len as usize); + let mapped_dir_list = get_slice_checked(mapped_dirs, mapped_dirs_len as usize); wasmer_wasi_generate_import_object_inner( arg_list, diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index a2433afa2..17e96a4c3 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -133,7 +133,7 @@ pub struct wasmer_byte_array { impl wasmer_byte_array { /// Get the data as a slice pub unsafe fn as_slice<'a>(&self) -> &'a [u8] { - std::slice::from_raw_parts(self.bytes, self.bytes_len as usize) + get_slice_checked(self.bytes, self.bytes_len as usize) } /// Copy the data into an owned Vec @@ -149,3 +149,14 @@ impl wasmer_byte_array { std::str::from_utf8(self.as_slice()) } } + +/// Gets a slice from a pointer and a length, returning an empty slice if the +/// pointer is null +#[inline] +pub(crate) unsafe fn get_slice_checked<'a, T>(ptr: *const T, len: usize) -> &'a [T] { + if ptr.is_null() { + &[] + } else { + std::slice::from_raw_parts(ptr, len) + } +} diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index a13a40c92..23caa54cc 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -781,7 +781,11 @@ bool wasmer_validate(const uint8_t *wasm_bytes, uint32_t wasm_bytes_len); wasmer_import_object_t *wasmer_wasi_generate_default_import_object(void); /** - * Creates a WASI import object + * Creates a WASI import object. + * + * This function treats null pointers as empty collections. + * For example, passing null for a string in `args`, will lead to a zero + * length argument in that position. */ wasmer_import_object_t *wasmer_wasi_generate_import_object(const wasmer_byte_array *args, unsigned int args_len, diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 51cdaa5c9..da8e39118 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -606,7 +606,11 @@ bool wasmer_validate(const uint8_t *wasm_bytes, uint32_t wasm_bytes_len); /// empty values. wasmer_import_object_t *wasmer_wasi_generate_default_import_object(); -/// Creates a WASI import object +/// Creates a WASI import object. +/// +/// This function treats null pointers as empty collections. +/// For example, passing null for a string in `args`, will lead to a zero +/// length argument in that position. wasmer_import_object_t *wasmer_wasi_generate_import_object(const wasmer_byte_array *args, unsigned int args_len, const wasmer_byte_array *envs,