From 8d47e8bf7bc795d1e689b22638986c251263d87e Mon Sep 17 00:00:00 2001 From: cjihrig Date: Sun, 3 May 2020 23:04:08 -0400 Subject: [PATCH] deps: update to uvwasi 0.0.9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Notable changes: - A `DEBUG()` macro and `UVWASI_DEBUG_LOG` build option have been added to improve debugging. - Path length restrictions have been removed across the codebase. - Initial support for `poll_oneoff()` has been added on all platforms. The implementation is based on `uv_poll_t`'s. - A new `uvwasi_size_t` has been introduced across the WASI system call API. This provides consistent 32-bit `size_t`'s. - The cmake test targets are now only generated if uvwasi is the root project to avoid conflicts with targets from embedders. - `uv.h` has been removed from the public headers. - A serialization/deserialization API has been added to simplify the process of working with WASM memory. This also hides many WASI <--> WASM interfacing implementation details from embedders. - A memory corruption bug on Windows related to path resolution has been fixed. PR-URL: https://github.com/nodejs/node/pull/33445 Fixes: https://github.com/nodejs/node/issues/33403 Reviewed-By: Michaƫl Zasso Reviewed-By: Jiawen Geng --- deps/uvwasi/include/uvwasi.h | 106 ++-- deps/uvwasi/include/wasi_serdes.h | 145 ++++++ deps/uvwasi/include/wasi_types.h | 8 +- deps/uvwasi/src/debug.h | 13 + deps/uvwasi/src/fd_table.c | 26 +- deps/uvwasi/{include => src}/fd_table.h | 0 deps/uvwasi/src/path_resolver.c | 52 +- deps/uvwasi/src/path_resolver.h | 19 +- deps/uvwasi/src/poll_oneoff.c | 267 ++++++++++ deps/uvwasi/src/poll_oneoff.h | 60 +++ deps/uvwasi/src/uvwasi.c | 661 +++++++++++++++++++----- deps/uvwasi/src/wasi_serdes.c | 259 ++++++++++ deps/uvwasi/uvwasi.gyp | 2 + src/node_wasi.cc | 585 +++++++++------------ 14 files changed, 1619 insertions(+), 584 deletions(-) create mode 100644 deps/uvwasi/include/wasi_serdes.h create mode 100644 deps/uvwasi/src/debug.h rename deps/uvwasi/{include => src}/fd_table.h (100%) create mode 100644 deps/uvwasi/src/poll_oneoff.c create mode 100644 deps/uvwasi/src/poll_oneoff.h create mode 100644 deps/uvwasi/src/wasi_serdes.c diff --git a/deps/uvwasi/include/uvwasi.h b/deps/uvwasi/include/uvwasi.h index f2d2d1a9fd8945..0090313c8af2eb 100644 --- a/deps/uvwasi/include/uvwasi.h +++ b/deps/uvwasi/include/uvwasi.h @@ -5,13 +5,12 @@ extern "C" { #endif -#include "uv.h" +#include "wasi_serdes.h" #include "wasi_types.h" -#include "fd_table.h" #define UVWASI_VERSION_MAJOR 0 #define UVWASI_VERSION_MINOR 0 -#define UVWASI_VERSION_PATCH 8 +#define UVWASI_VERSION_PATCH 9 #define UVWASI_VERSION_HEX ((UVWASI_VERSION_MAJOR << 16) | \ (UVWASI_VERSION_MINOR << 8) | \ (UVWASI_VERSION_PATCH)) @@ -35,16 +34,18 @@ typedef struct uvwasi_mem_s { uvwasi_realloc realloc; } uvwasi_mem_t; +struct uvwasi_fd_table_t; + typedef struct uvwasi_s { - struct uvwasi_fd_table_t fds; - size_t argc; + struct uvwasi_fd_table_t* fds; + uvwasi_size_t argc; char** argv; char* argv_buf; - size_t argv_buf_size; - size_t envc; + uvwasi_size_t argv_buf_size; + uvwasi_size_t envc; char** env; char* env_buf; - size_t env_buf_size; + uvwasi_size_t env_buf_size; const uvwasi_mem_t* allocator; } uvwasi_t; @@ -54,12 +55,12 @@ typedef struct uvwasi_preopen_s { } uvwasi_preopen_t; typedef struct uvwasi_options_s { - size_t fd_table_size; - size_t preopenc; + uvwasi_size_t fd_table_size; + uvwasi_size_t preopenc; uvwasi_preopen_t* preopens; - size_t argc; - char** argv; - char** envp; + uvwasi_size_t argc; + const char** argv; + const char** envp; uvwasi_fd_t in; uvwasi_fd_t out; uvwasi_fd_t err; @@ -69,17 +70,18 @@ typedef struct uvwasi_options_s { /* Embedder API. */ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, uvwasi_options_t* options); void uvwasi_destroy(uvwasi_t* uvwasi); +/* Use int instead of uv_file to avoid needing uv.h */ uvwasi_errno_t uvwasi_embedder_remap_fd(uvwasi_t* uvwasi, const uvwasi_fd_t fd, - uv_file new_host_fd); + int new_host_fd); const char* uvwasi_embedder_err_code_to_string(uvwasi_errno_t code); /* WASI system call API. */ uvwasi_errno_t uvwasi_args_get(uvwasi_t* uvwasi, char** argv, char* argv_buf); uvwasi_errno_t uvwasi_args_sizes_get(uvwasi_t* uvwasi, - size_t* argc, - size_t* argv_buf_size); + uvwasi_size_t* argc, + uvwasi_size_t* argv_buf_size); uvwasi_errno_t uvwasi_clock_res_get(uvwasi_t* uvwasi, uvwasi_clockid_t clock_id, uvwasi_timestamp_t* resolution); @@ -91,8 +93,8 @@ uvwasi_errno_t uvwasi_environ_get(uvwasi_t* uvwasi, char** environment, char* environ_buf); uvwasi_errno_t uvwasi_environ_sizes_get(uvwasi_t* uvwasi, - size_t* environ_count, - size_t* environ_buf_size); + uvwasi_size_t* environ_count, + uvwasi_size_t* environ_buf_size); uvwasi_errno_t uvwasi_fd_advise(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_filesize_t offset, @@ -129,33 +131,33 @@ uvwasi_errno_t uvwasi_fd_filestat_set_times(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_pread(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_iovec_t* iovs, - size_t iovs_len, + uvwasi_size_t iovs_len, uvwasi_filesize_t offset, - size_t* nread); + uvwasi_size_t* nread); uvwasi_errno_t uvwasi_fd_prestat_get(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_prestat_t* buf); uvwasi_errno_t uvwasi_fd_prestat_dir_name(uvwasi_t* uvwasi, uvwasi_fd_t fd, char* path, - size_t path_len); + uvwasi_size_t path_len); uvwasi_errno_t uvwasi_fd_pwrite(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_ciovec_t* iovs, - size_t iovs_len, + uvwasi_size_t iovs_len, uvwasi_filesize_t offset, - size_t* nwritten); + uvwasi_size_t* nwritten); uvwasi_errno_t uvwasi_fd_read(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_iovec_t* iovs, - size_t iovs_len, - size_t* nread); + uvwasi_size_t iovs_len, + uvwasi_size_t* nread); uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi, uvwasi_fd_t fd, void* buf, - size_t buf_len, + uvwasi_size_t buf_len, uvwasi_dircookie_t cookie, - size_t* bufused); + uvwasi_size_t* bufused); uvwasi_errno_t uvwasi_fd_renumber(uvwasi_t* uvwasi, uvwasi_fd_t from, uvwasi_fd_t to); @@ -171,23 +173,23 @@ uvwasi_errno_t uvwasi_fd_tell(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_write(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_ciovec_t* iovs, - size_t iovs_len, - size_t* nwritten); + uvwasi_size_t iovs_len, + uvwasi_size_t* nwritten); uvwasi_errno_t uvwasi_path_create_directory(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, - size_t path_len); + uvwasi_size_t path_len); uvwasi_errno_t uvwasi_path_filestat_get(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_lookupflags_t flags, const char* path, - size_t path_len, + uvwasi_size_t path_len, uvwasi_filestat_t* buf); uvwasi_errno_t uvwasi_path_filestat_set_times(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_lookupflags_t flags, const char* path, - size_t path_len, + uvwasi_size_t path_len, uvwasi_timestamp_t st_atim, uvwasi_timestamp_t st_mtim, uvwasi_fstflags_t fst_flags); @@ -195,15 +197,15 @@ uvwasi_errno_t uvwasi_path_link(uvwasi_t* uvwasi, uvwasi_fd_t old_fd, uvwasi_lookupflags_t old_flags, const char* old_path, - size_t old_path_len, + uvwasi_size_t old_path_len, uvwasi_fd_t new_fd, const char* new_path, - size_t new_path_len); + uvwasi_size_t new_path_len); uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, uvwasi_fd_t dirfd, uvwasi_lookupflags_t dirflags, const char* path, - size_t path_len, + uvwasi_size_t path_len, uvwasi_oflags_t o_flags, uvwasi_rights_t fs_rights_base, uvwasi_rights_t fs_rights_inheriting, @@ -212,53 +214,55 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, - size_t path_len, + uvwasi_size_t path_len, char* buf, - size_t buf_len, - size_t* bufused); + uvwasi_size_t buf_len, + uvwasi_size_t* bufused); uvwasi_errno_t uvwasi_path_remove_directory(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, - size_t path_len); + uvwasi_size_t path_len); uvwasi_errno_t uvwasi_path_rename(uvwasi_t* uvwasi, uvwasi_fd_t old_fd, const char* old_path, - size_t old_path_len, + uvwasi_size_t old_path_len, uvwasi_fd_t new_fd, const char* new_path, - size_t new_path_len); + uvwasi_size_t new_path_len); uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi, const char* old_path, - size_t old_path_len, + uvwasi_size_t old_path_len, uvwasi_fd_t fd, const char* new_path, - size_t new_path_len); + uvwasi_size_t new_path_len); uvwasi_errno_t uvwasi_path_unlink_file(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, - size_t path_len); + uvwasi_size_t path_len); uvwasi_errno_t uvwasi_poll_oneoff(uvwasi_t* uvwasi, const uvwasi_subscription_t* in, uvwasi_event_t* out, - size_t nsubscriptions, - size_t* nevents); + uvwasi_size_t nsubscriptions, + uvwasi_size_t* nevents); uvwasi_errno_t uvwasi_proc_exit(uvwasi_t* uvwasi, uvwasi_exitcode_t rval); uvwasi_errno_t uvwasi_proc_raise(uvwasi_t* uvwasi, uvwasi_signal_t sig); -uvwasi_errno_t uvwasi_random_get(uvwasi_t* uvwasi, void* buf, size_t buf_len); +uvwasi_errno_t uvwasi_random_get(uvwasi_t* uvwasi, + void* buf, + uvwasi_size_t buf_len); uvwasi_errno_t uvwasi_sched_yield(uvwasi_t* uvwasi); uvwasi_errno_t uvwasi_sock_recv(uvwasi_t* uvwasi, uvwasi_fd_t sock, const uvwasi_iovec_t* ri_data, - size_t ri_data_len, + uvwasi_size_t ri_data_len, uvwasi_riflags_t ri_flags, - size_t* ro_datalen, + uvwasi_size_t* ro_datalen, uvwasi_roflags_t* ro_flags); uvwasi_errno_t uvwasi_sock_send(uvwasi_t* uvwasi, uvwasi_fd_t sock, const uvwasi_ciovec_t* si_data, - size_t si_data_len, + uvwasi_size_t si_data_len, uvwasi_siflags_t si_flags, - size_t* so_datalen); + uvwasi_size_t* so_datalen); uvwasi_errno_t uvwasi_sock_shutdown(uvwasi_t* uvwasi, uvwasi_fd_t sock, uvwasi_sdflags_t how); diff --git a/deps/uvwasi/include/wasi_serdes.h b/deps/uvwasi/include/wasi_serdes.h new file mode 100644 index 00000000000000..f927b82bac9cbc --- /dev/null +++ b/deps/uvwasi/include/wasi_serdes.h @@ -0,0 +1,145 @@ +#ifndef __UVWASI_SERDES_H__ +#define __UVWASI_SERDES_H__ + +#include "wasi_types.h" + +/* Basic uint{8,16,32,64}_t read/write functions. */ + +#define BASIC_TYPE_(name, type) \ + void uvwasi_serdes_write_##name(void* ptr, size_t offset, type value); \ + type uvwasi_serdes_read_##name(const void* ptr, size_t offset); \ + +#define BASIC_TYPE(type) BASIC_TYPE_(type, type) +#define BASIC_TYPE_UVWASI(type) BASIC_TYPE_(type, uvwasi_##type) + +#define UVWASI_SERDES_SIZE_uint8_t sizeof(uint8_t) +BASIC_TYPE(uint8_t) +#define UVWASI_SERDES_SIZE_uint16_t sizeof(uint16_t) +BASIC_TYPE(uint16_t) +#define UVWASI_SERDES_SIZE_uint32_t sizeof(uint32_t) +BASIC_TYPE(uint32_t) +#define UVWASI_SERDES_SIZE_uint64_t sizeof(uint64_t) +BASIC_TYPE(uint64_t) + +#define UVWASI_SERDES_SIZE_advice_t sizeof(uvwasi_advice_t) +BASIC_TYPE_UVWASI(advice_t) +#define UVWASI_SERDES_SIZE_clockid_t sizeof(uvwasi_clockid_t) +BASIC_TYPE_UVWASI(clockid_t) +#define UVWASI_SERDES_SIZE_device_t sizeof(uvwasi_device_t) +BASIC_TYPE_UVWASI(device_t) +#define UVWASI_SERDES_SIZE_dircookie_t sizeof(uvwasi_dircookie_t) +BASIC_TYPE_UVWASI(dircookie_t) +#define UVWASI_SERDES_SIZE_eventrwflags_t sizeof(uvwasi_eventrwflags_t) +BASIC_TYPE_UVWASI(eventrwflags_t) +#define UVWASI_SERDES_SIZE_eventtype_t sizeof(uvwasi_eventtype_t) +BASIC_TYPE_UVWASI(eventtype_t) +#define UVWASI_SERDES_SIZE_exitcode_t sizeof(uvwasi_exitcode_t) +BASIC_TYPE_UVWASI(exitcode_t) +#define UVWASI_SERDES_SIZE_fd_t sizeof(uvwasi_fd_t) +BASIC_TYPE_UVWASI(fd_t) +#define UVWASI_SERDES_SIZE_fdflags_t sizeof(uvwasi_fdflags_t) +BASIC_TYPE_UVWASI(fdflags_t) +#define UVWASI_SERDES_SIZE_filesize_t sizeof(uvwasi_filesize_t) +BASIC_TYPE_UVWASI(filesize_t) +#define UVWASI_SERDES_SIZE_fstflags_t sizeof(uvwasi_fstflags_t) +BASIC_TYPE_UVWASI(fstflags_t) +#define UVWASI_SERDES_SIZE_inode_t sizeof(uvwasi_inode_t) +BASIC_TYPE_UVWASI(inode_t) +#define UVWASI_SERDES_SIZE_linkcount_t sizeof(uvwasi_linkcount_t) +BASIC_TYPE_UVWASI(linkcount_t) +#define UVWASI_SERDES_SIZE_lookupflags_t sizeof(uvwasi_lookupflags_t) +BASIC_TYPE_UVWASI(lookupflags_t) +#define UVWASI_SERDES_SIZE_oflags_t sizeof(uvwasi_oflags_t) +BASIC_TYPE_UVWASI(oflags_t) +#define UVWASI_SERDES_SIZE_preopentype_t sizeof(uvwasi_preopentype_t) +BASIC_TYPE_UVWASI(preopentype_t) +#define UVWASI_SERDES_SIZE_riflags_t sizeof(uvwasi_riflags_t) +BASIC_TYPE_UVWASI(riflags_t) +#define UVWASI_SERDES_SIZE_rights_t sizeof(uvwasi_rights_t) +BASIC_TYPE_UVWASI(rights_t) +#define UVWASI_SERDES_SIZE_roflags_t sizeof(uvwasi_roflags_t) +BASIC_TYPE_UVWASI(roflags_t) +#define UVWASI_SERDES_SIZE_sdflags_t sizeof(uvwasi_sdflags_t) +BASIC_TYPE_UVWASI(sdflags_t) +#define UVWASI_SERDES_SIZE_siflags_t sizeof(uvwasi_siflags_t) +BASIC_TYPE_UVWASI(siflags_t) +#define UVWASI_SERDES_SIZE_size_t sizeof(uvwasi_size_t) +BASIC_TYPE_UVWASI(size_t) +#define UVWASI_SERDES_SIZE_inode_t sizeof(uvwasi_inode_t) +BASIC_TYPE_UVWASI(inode_t) +#define UVWASI_SERDES_SIZE_signal_t sizeof(uvwasi_signal_t) +BASIC_TYPE_UVWASI(signal_t) +#define UVWASI_SERDES_SIZE_subclockflags_t sizeof(uvwasi_subclockflags_t) +BASIC_TYPE_UVWASI(subclockflags_t) +#define UVWASI_SERDES_SIZE_timestamp_t sizeof(uvwasi_timestamp_t) +BASIC_TYPE_UVWASI(timestamp_t) +#define UVWASI_SERDES_SIZE_userdata_t sizeof(uvwasi_userdata_t) +BASIC_TYPE_UVWASI(userdata_t) +#define UVWASI_SERDES_SIZE_whence_t sizeof(uvwasi_whence_t) +BASIC_TYPE_UVWASI(whence_t) + +#undef BASIC_TYPE_UVWASI +#undef BASIC_TYPE +#undef BASIC_TYPE_ + +/* WASI structure read/write functions. */ + +#define STRUCT(name) \ + void uvwasi_serdes_write_##name(void* ptr, \ + size_t offset, \ + const uvwasi_##name* value); \ + void uvwasi_serdes_read_##name(const void* ptr, \ + size_t offset, \ + uvwasi_##name* value); + +/* iovs currently only need to be read from WASM memory. */ +#define IOVS_STRUCT(name) \ + uvwasi_errno_t uvwasi_serdes_read_##name(const void* ptr, \ + size_t end, \ + size_t offset, \ + uvwasi_##name* value); + +#define UVWASI_SERDES_SIZE_ciovec_t 8 +IOVS_STRUCT(ciovec_t) + +#define UVWASI_SERDES_SIZE_iovec_t 8 +IOVS_STRUCT(iovec_t) + +#define UVWASI_SERDES_SIZE_fdstat_t 24 +STRUCT(fdstat_t) + +#define UVWASI_SERDES_SIZE_filestat_t 64 +STRUCT(filestat_t) + +#define UVWASI_SERDES_SIZE_prestat_t 8 +STRUCT(prestat_t) + +#define UVWASI_SERDES_SIZE_event_t 32 +STRUCT(event_t) + +#define UVWASI_SERDES_SIZE_subscription_t 48 +STRUCT(subscription_t) + +#undef STRUCT +#undef IOVS_STRUCT + +uvwasi_errno_t uvwasi_serdes_readv_ciovec_t(const void* ptr, + size_t end, + size_t offset, + uvwasi_ciovec_t* iovs, + uvwasi_size_t iovs_len); + +uvwasi_errno_t uvwasi_serdes_readv_iovec_t(const void* ptr, + size_t end, + size_t offset, + uvwasi_iovec_t* iovs, + uvwasi_size_t iovs_len); + +/* Helper functions for memory bounds checking. */ +int uvwasi_serdes_check_bounds(size_t offset, size_t end, size_t size); +int uvwasi_serdes_check_array_bounds(size_t offset, + size_t end, + size_t size, + size_t count); + +#endif /* __UVWASI_SERDES_H__ */ diff --git a/deps/uvwasi/include/wasi_types.h b/deps/uvwasi/include/wasi_types.h index 2f93b412624c06..57c2dd2f3ce589 100644 --- a/deps/uvwasi/include/wasi_types.h +++ b/deps/uvwasi/include/wasi_types.h @@ -6,6 +6,8 @@ /* API: https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/docs.md */ +typedef uint32_t uvwasi_size_t; + typedef uint8_t uvwasi_advice_t; #define UVWASI_ADVICE_NORMAL 0 #define UVWASI_ADVICE_SEQUENTIAL 1 @@ -16,7 +18,7 @@ typedef uint8_t uvwasi_advice_t; typedef struct uvwasi_ciovec_s { const void* buf; - size_t buf_len; + uvwasi_size_t buf_len; } uvwasi_ciovec_t; typedef uint32_t uvwasi_clockid_t; @@ -152,7 +154,7 @@ typedef uint64_t uvwasi_inode_t; typedef struct uvwasi_iovec_s { void* buf; - size_t buf_len; + uvwasi_size_t buf_len; } uvwasi_iovec_t; typedef uint64_t uvwasi_linkcount_t; @@ -173,7 +175,7 @@ typedef struct uvwasi_prestat_s { uvwasi_preopentype_t pr_type; union uvwasi_prestat_u { struct uvwasi_prestat_dir_t { - size_t pr_name_len; + uvwasi_size_t pr_name_len; } dir; } u; } uvwasi_prestat_t; diff --git a/deps/uvwasi/src/debug.h b/deps/uvwasi/src/debug.h new file mode 100644 index 00000000000000..16bc2732ec90cd --- /dev/null +++ b/deps/uvwasi/src/debug.h @@ -0,0 +1,13 @@ +#ifndef __UVWASI_DEBUG_H__ +#define __UVWASI_DEBUG_H__ + +#ifdef UVWASI_DEBUG_LOG +# define __STDC_FORMAT_MACROS +# include +# define DEBUG(fmt, ...) \ + do { fprintf(stderr, fmt, __VA_ARGS__); } while (0) +#else +# define DEBUG(fmt, ...) +#endif + +#endif /* __UVWASI_DEBUG_H__ */ diff --git a/deps/uvwasi/src/fd_table.c b/deps/uvwasi/src/fd_table.c index 3d134e3b7e5e2e..877faf4ca19cd0 100644 --- a/deps/uvwasi/src/fd_table.c +++ b/deps/uvwasi/src/fd_table.c @@ -181,26 +181,25 @@ uvwasi_errno_t uvwasi_fd_table_init(uvwasi_t* uvwasi, if (uvwasi == NULL || options == NULL || options->fd_table_size < 3) return UVWASI_EINVAL; - table = &uvwasi->fds; - table->fds = NULL; + table = uvwasi__malloc(uvwasi, sizeof(*table)); + if (table == NULL) + return UVWASI_ENOMEM; + table->used = 0; table->size = options->fd_table_size; table->fds = uvwasi__calloc(uvwasi, options->fd_table_size, sizeof(struct uvwasi_fd_wrap_t*)); - - if (table->fds == NULL) + if (table->fds == NULL) { + uvwasi__free(uvwasi, table); return UVWASI_ENOMEM; + } r = uv_rwlock_init(&table->rwlock); if (r != 0) { err = uvwasi__translate_uv_error(r); - /* Free table->fds and set it to NULL here. This is done explicitly instead - of jumping to error_exit because uvwasi_fd_table_free() relies on fds - being NULL to know whether or not to destroy the rwlock. - */ uvwasi__free(uvwasi, table->fds); - table->fds = NULL; + uvwasi__free(uvwasi, table); return err; } @@ -217,6 +216,7 @@ uvwasi_errno_t uvwasi_fd_table_init(uvwasi_t* uvwasi, if (err != UVWASI_ESUCCESS) goto error_exit; + uvwasi->fds = table; return UVWASI_ESUCCESS; error_exit: uvwasi_fd_table_free(uvwasi, table); @@ -228,12 +228,14 @@ void uvwasi_fd_table_free(uvwasi_t* uvwasi, struct uvwasi_fd_table_t* table) { struct uvwasi_fd_wrap_t* entry; uint32_t i; - if (table == NULL) + if (uvwasi == NULL || table == NULL) return; for (i = 0; i < table->size; i++) { entry = table->fds[i]; - if (entry == NULL) continue; + + if (entry == NULL) + continue; uv_mutex_destroy(&entry->mutex); uvwasi__free(uvwasi, entry); @@ -246,6 +248,8 @@ void uvwasi_fd_table_free(uvwasi_t* uvwasi, struct uvwasi_fd_table_t* table) { table->used = 0; uv_rwlock_destroy(&table->rwlock); } + + uvwasi__free(uvwasi, table); } diff --git a/deps/uvwasi/include/fd_table.h b/deps/uvwasi/src/fd_table.h similarity index 100% rename from deps/uvwasi/include/fd_table.h rename to deps/uvwasi/src/fd_table.h diff --git a/deps/uvwasi/src/path_resolver.c b/deps/uvwasi/src/path_resolver.c index ee0e60f7e8f4ea..af13c1553ca874 100644 --- a/deps/uvwasi/src/path_resolver.c +++ b/deps/uvwasi/src/path_resolver.c @@ -15,7 +15,7 @@ #endif /* _WIN32 */ -static int uvwasi__is_absolute_path(const char* path, size_t path_len) { +static int uvwasi__is_absolute_path(const char* path, uvwasi_size_t path_len) { /* It's expected that only Unix style paths will be generated by WASI. */ return path != NULL && path_len > 0 && path[0] == '/'; } @@ -33,9 +33,9 @@ static char* uvwasi__strchr_slash(const char* s) { uvwasi_errno_t uvwasi__normalize_path(const char* path, - size_t path_len, + uvwasi_size_t path_len, char* normalized_path, - size_t normalized_len) { + uvwasi_size_t normalized_len) { const char* cur; char* ptr; char* next; @@ -125,9 +125,9 @@ uvwasi_errno_t uvwasi__normalize_path(const char* path, static int uvwasi__is_path_sandboxed(const char* path, - size_t path_len, + uvwasi_size_t path_len, const char* fd_path, - size_t fd_path_len) { + uvwasi_size_t fd_path_len) { char* ptr; int remaining_len; @@ -173,9 +173,9 @@ static uvwasi_errno_t uvwasi__normalize_absolute_path( const uvwasi_t* uvwasi, const struct uvwasi_fd_wrap_t* fd, const char* path, - size_t path_len, + uvwasi_size_t path_len, char** normalized_path, - size_t* normalized_len + uvwasi_size_t* normalized_len ) { /* This function resolves an absolute path to the provided file descriptor. If the file descriptor's path is relative, then this operation will fail @@ -224,9 +224,9 @@ static uvwasi_errno_t uvwasi__normalize_relative_path( const uvwasi_t* uvwasi, const struct uvwasi_fd_wrap_t* fd, const char* path, - size_t path_len, + uvwasi_size_t path_len, char** normalized_path, - size_t* normalized_len + uvwasi_size_t* normalized_len ) { /* This function resolves a relative path to the provided file descriptor. The relative path is concatenated to the file descriptor's path, and then @@ -298,9 +298,9 @@ static uvwasi_errno_t uvwasi__resolve_path_to_host( const uvwasi_t* uvwasi, const struct uvwasi_fd_wrap_t* fd, const char* path, - size_t path_len, + uvwasi_size_t path_len, char** resolved_path, - size_t* resolved_len + uvwasi_size_t* resolved_len ) { /* Return the normalized path, but resolved to the host's real path. */ char* res_path; @@ -309,7 +309,7 @@ static uvwasi_errno_t uvwasi__resolve_path_to_host( int fake_path_len; int stripped_len; #ifdef _WIN32 - size_t i; + uvwasi_size_t i; #endif /* _WIN32 */ real_path_len = strlen(fd->real_path); @@ -351,6 +351,7 @@ static uvwasi_errno_t uvwasi__resolve_path_to_host( #ifdef _WIN32 /* Replace / with \ on Windows. */ + res_path = *resolved_path; for (i = real_path_len; i < *resolved_len; i++) { if (res_path[i] == '/') res_path[i] = '\\'; @@ -364,8 +365,8 @@ static uvwasi_errno_t uvwasi__resolve_path_to_host( uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi, const struct uvwasi_fd_wrap_t* fd, const char* path, - size_t path_len, - char* resolved_path, + uvwasi_size_t path_len, + char** resolved_path, uvwasi_lookupflags_t flags) { uv_fs_t req; uvwasi_errno_t err; @@ -373,9 +374,9 @@ uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi, char* host_path; char* normalized_path; char* link_target; - size_t input_len; - size_t host_path_len; - size_t normalized_len; + uvwasi_size_t input_len; + uvwasi_size_t host_path_len; + uvwasi_size_t normalized_len; int follow_count; int r; @@ -418,14 +419,6 @@ uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi, if (err != UVWASI_ESUCCESS) goto exit; - /* TODO(cjihrig): Currently performing a bounds check here. The TODO is to - stop allocating resolved_path in every caller and instead return the - path allocated in this function. */ - if (host_path_len > PATH_MAX_BYTES) { - err = UVWASI_ENOBUFS; - goto exit; - } - if ((flags & UVWASI_LOOKUP_SYMLINK_FOLLOW) == UVWASI_LOOKUP_SYMLINK_FOLLOW) { r = uv_fs_readlink(NULL, &req, host_path, NULL); @@ -482,11 +475,14 @@ uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi, } exit: - if (err == UVWASI_ESUCCESS) - memcpy(resolved_path, host_path, host_path_len + 1); + if (err == UVWASI_ESUCCESS) { + *resolved_path = host_path; + } else { + *resolved_path = NULL; + uvwasi__free(uvwasi, host_path); + } uvwasi__free(uvwasi, link_target); uvwasi__free(uvwasi, normalized_path); - uvwasi__free(uvwasi, host_path); return err; } diff --git a/deps/uvwasi/src/path_resolver.h b/deps/uvwasi/src/path_resolver.h index d5f95eafbfbf83..5040c69ac40cb7 100644 --- a/deps/uvwasi/src/path_resolver.h +++ b/deps/uvwasi/src/path_resolver.h @@ -1,28 +1,19 @@ #ifndef __UVWASI_PATH_RESOLVER_H__ #define __UVWASI_PATH_RESOLVER_H__ +#include "fd_table.h" #include "uvwasi.h" -/* TODO(cjihrig): PATH_MAX_BYTES shouldn't be stack allocated. On Windows, paths - can be 32k long, and this PATH_MAX_BYTES is an artificial limitation. */ -#ifdef _WIN32 -/* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */ -# define PATH_MAX_BYTES (MAX_PATH * 4) -#else -# include -# define PATH_MAX_BYTES (PATH_MAX) -#endif - uvwasi_errno_t uvwasi__normalize_path(const char* path, - size_t path_len, + uvwasi_size_t path_len, char* normalized_path, - size_t normalized_len); + uvwasi_size_t normalized_len); uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi, const struct uvwasi_fd_wrap_t* fd, const char* path, - size_t path_len, - char* resolved_path, + uvwasi_size_t path_len, + char** resolved_path, uvwasi_lookupflags_t flags); #endif /* __UVWASI_PATH_RESOLVER_H__ */ diff --git a/deps/uvwasi/src/poll_oneoff.c b/deps/uvwasi/src/poll_oneoff.c new file mode 100644 index 00000000000000..97b8ef332da71f --- /dev/null +++ b/deps/uvwasi/src/poll_oneoff.c @@ -0,0 +1,267 @@ +#include "uv.h" +#include "poll_oneoff.h" +#include "uv_mapping.h" +#include "uvwasi_alloc.h" + + +static void poll_cb(uv_poll_t* handle, int status, int events) { + struct uvwasi_poll_oneoff_state_t* state; + struct uvwasi__poll_fdevent_t* event; + + uv_poll_stop(handle); + event = uv_handle_get_data((uv_handle_t*) handle); + event->revents = events; + + if (status != 0) + event->error = UVWASI_EIO; + + state = uv_loop_get_data(handle->loop); + state->result++; +} + + +static void timeout_cb(uv_timer_t* handle) { + struct uvwasi_poll_oneoff_state_t* state; + uvwasi_size_t i; + + state = uv_loop_get_data(handle->loop); + + for (i = 0; i < state->handle_cnt; i++) + uv_poll_stop(&state->poll_handles[i]); +} + + +uvwasi_errno_t uvwasi__poll_oneoff_state_init( + uvwasi_t* uvwasi, + struct uvwasi_poll_oneoff_state_t* state, + uvwasi_size_t max_fds + ) { + uvwasi_errno_t err; + int r; + + if (uvwasi == NULL || state == NULL) + return UVWASI_EINVAL; + + state->uvwasi = NULL; + state->timeout = 0; + state->has_timer = 0; + state->fdevents = NULL; + state->poll_handles = NULL; + state->max_fds = 0; + state->fdevent_cnt = 0; + state->handle_cnt = 0; + state->result = 0; + + r = uv_loop_init(&state->loop); + if (r != 0) + return uvwasi__translate_uv_error(r); + + if (max_fds > 0) { + state->fdevents = uvwasi__calloc(uvwasi, + max_fds, + sizeof(*state->fdevents)); + if (state->fdevents == NULL) { + err = UVWASI_ENOMEM; + goto error_exit; + } + + state->poll_handles = uvwasi__calloc(uvwasi, + max_fds, + sizeof(*state->poll_handles)); + if (state->poll_handles == NULL) { + err = UVWASI_ENOMEM; + goto error_exit; + } + } + + uv_loop_set_data(&state->loop, (void*) state); + state->uvwasi = uvwasi; + state->max_fds = max_fds; + + return UVWASI_ESUCCESS; + +error_exit: + uv_loop_close(&state->loop); + uvwasi__free(state->uvwasi, state->fdevents); + uvwasi__free(state->uvwasi, state->poll_handles); + return err; +} + + +uvwasi_errno_t uvwasi__poll_oneoff_state_cleanup( + struct uvwasi_poll_oneoff_state_t* state + ) { + struct uvwasi__poll_fdevent_t* event; + uvwasi_size_t i; + int r; + + if (state == NULL) + return UVWASI_EINVAL; + + if (state->has_timer != 0) { + state->timeout = 0; + state->has_timer = 0; + uv_close((uv_handle_t*) &state->timer, NULL); + } + + for (i = 0; i < state->fdevent_cnt; i++) { + event = &state->fdevents[i]; + + if (event->is_duplicate_fd == 0 && event->wrap != NULL) + uv_mutex_unlock(&event->wrap->mutex); + } + + for (i = 0; i < state->handle_cnt; i++) + uv_close((uv_handle_t*) &state->poll_handles[i], NULL); + + state->max_fds = 0; + state->fdevent_cnt = 0; + state->handle_cnt = 0; + + uvwasi__free(state->uvwasi, state->fdevents); + uvwasi__free(state->uvwasi, state->poll_handles); + state->fdevents = NULL; + state->poll_handles = NULL; + state->uvwasi = NULL; + + r = uv_loop_close(&state->loop); + if (r != 0) + return uvwasi__translate_uv_error(r); + + return UVWASI_ESUCCESS; +} + + +uvwasi_errno_t uvwasi__poll_oneoff_state_set_timer( + struct uvwasi_poll_oneoff_state_t* state, + uvwasi_timestamp_t timeout + ) { + int r; + + if (state == NULL) + return UVWASI_EINVAL; + + r = uv_timer_init(&state->loop, &state->timer); + if (r != 0) + return uvwasi__translate_uv_error(r); + + /* Convert WASI timeout from nanoseconds to milliseconds for libuv. */ + state->timeout = timeout / 1000000; + state->has_timer = 1; + return UVWASI_ESUCCESS; +} + + +uvwasi_errno_t uvwasi__poll_oneoff_state_add_fdevent( + struct uvwasi_poll_oneoff_state_t* state, + uvwasi_subscription_t* subscription + ) { + struct uvwasi__poll_fdevent_t* event; + struct uvwasi__poll_fdevent_t* dup; + uv_poll_t* poll_handle; + uvwasi_eventtype_t type; + uvwasi_rights_t rights; + uvwasi_fd_t fd; + uvwasi_errno_t err; + uvwasi_size_t i; + int r; + + if (state == NULL) + return UVWASI_EINVAL; + + event = &state->fdevents[state->fdevent_cnt]; + fd = subscription->u.fd_readwrite.fd; + type = subscription->type; + + if (type == UVWASI_EVENTTYPE_FD_READ) { + event->events = UV_DISCONNECT | UV_READABLE; + rights = UVWASI_RIGHT_POLL_FD_READWRITE | UVWASI_RIGHT_FD_READ; + } else if (type == UVWASI_EVENTTYPE_FD_WRITE) { + event->events = UV_DISCONNECT | UV_WRITABLE; + rights = UVWASI_RIGHT_POLL_FD_READWRITE | UVWASI_RIGHT_FD_WRITE; + } else { + return UVWASI_EINVAL; + } + + /* Check if the same file descriptor is already being polled. If so, use the + wrap and poll handle from the first descriptor. The reasons are that libuv + does not support polling the same fd more than once at the same time, and + uvwasi has the fd's mutex locked. */ + event->is_duplicate_fd = 0; + for (i = 0; i < state->fdevent_cnt; i++) { + dup = &state->fdevents[i]; + if (dup->wrap->id == fd) { + event->is_duplicate_fd = 1; + event->wrap = dup->wrap; + event->poll_handle = dup->poll_handle; + err = event->error; + goto poll_config_done; + } + } + + /* Get the file descriptor. If UVWASI_EBADF is returned, continue on, but + don't do any polling with the handle. */ + err = uvwasi_fd_table_get(state->uvwasi->fds, fd, &event->wrap, rights, 0); + if (err == UVWASI_EBADF) + event->wrap = NULL; + else if (err != UVWASI_ESUCCESS) + return err; + + if (err == UVWASI_ESUCCESS) { + /* The fd is valid, so setup the poll handle. */ + poll_handle = &state->poll_handles[state->handle_cnt]; + r = uv_poll_init(&state->loop, poll_handle, event->wrap->fd); + + if (r != 0) { + /* If uv_poll_init() fails (for example on Windows because only sockets + are supported), set the error for this event to UVWASI_EBADF, but don't + do any polling with the handle. */ + uv_mutex_unlock(&event->wrap->mutex); + return uvwasi__translate_uv_error(r); + } else { + r = uv_poll_start(poll_handle, + event->events, + poll_cb); + if (r != 0) { + uv_mutex_unlock(&event->wrap->mutex); + uv_close((uv_handle_t*) poll_handle, NULL); + return uvwasi__translate_uv_error(r); + } + + uv_handle_set_data((uv_handle_t*) poll_handle, + (void*) &state->fdevents[state->fdevent_cnt]); + event->poll_handle = poll_handle; + state->handle_cnt++; + } + } + +poll_config_done: + event->type = type; + event->userdata = subscription->userdata; + event->error = err; + event->revents = 0; + state->fdevent_cnt++; + return UVWASI_ESUCCESS; +} + + +uvwasi_errno_t uvwasi__poll_oneoff_run( + struct uvwasi_poll_oneoff_state_t* state + ) { + int r; + + if (state->has_timer == 1) { + r = uv_timer_start(&state->timer, timeout_cb, state->timeout, 0); + if (r != 0) + return uvwasi__translate_uv_error(r); + + if (state->fdevent_cnt > 0) + uv_unref((uv_handle_t*) &state->timer); + } + + r = uv_run(&state->loop, UV_RUN_DEFAULT); + if (r != 0) + return uvwasi__translate_uv_error(r); + + return UVWASI_ESUCCESS; +} diff --git a/deps/uvwasi/src/poll_oneoff.h b/deps/uvwasi/src/poll_oneoff.h new file mode 100644 index 00000000000000..64a315af1b334b --- /dev/null +++ b/deps/uvwasi/src/poll_oneoff.h @@ -0,0 +1,60 @@ +#ifndef __UVWASI_POLL_ONEOFF_H__ +#define __UVWASI_POLL_ONEOFF_H__ + +#include "fd_table.h" +#include "wasi_types.h" + +struct uvwasi_s; + +struct uvwasi__poll_fdevent_t { + struct uvwasi_fd_wrap_t* wrap; + uvwasi_userdata_t userdata; + uvwasi_eventtype_t type; + uvwasi_errno_t error; + uv_poll_t* poll_handle; + int is_duplicate_fd; + int events; + int revents; +}; + +struct uvwasi_poll_oneoff_state_t { + struct uvwasi_s* uvwasi; + struct uvwasi__poll_fdevent_t* fdevents; + uv_poll_t* poll_handles; + uv_timer_t timer; + uint64_t timeout; + uv_loop_t loop; + uvwasi_size_t max_fds; + int has_timer; + uvwasi_size_t fdevent_cnt; + uvwasi_size_t handle_cnt; + int result; +}; + + +uvwasi_errno_t uvwasi__poll_oneoff_state_init( + struct uvwasi_s* uvwasi, + struct uvwasi_poll_oneoff_state_t* state, + uvwasi_size_t max_fds + ); + +uvwasi_errno_t uvwasi__poll_oneoff_state_cleanup( + struct uvwasi_poll_oneoff_state_t* state + ); + +uvwasi_errno_t uvwasi__poll_oneoff_state_set_timer( + struct uvwasi_poll_oneoff_state_t* state, + uvwasi_timestamp_t timeout + ); + +uvwasi_errno_t uvwasi__poll_oneoff_state_add_fdevent( + struct uvwasi_poll_oneoff_state_t* state, + uvwasi_subscription_t* subscription + ); + +uvwasi_errno_t uvwasi__poll_oneoff_run( + struct uvwasi_poll_oneoff_state_t* state + ); + + +#endif /* __UVWASI_POLL_ONEOFF_H__ */ diff --git a/deps/uvwasi/src/uvwasi.c b/deps/uvwasi/src/uvwasi.c index 0ee66be36a3951..fc8f0ee4844b9e 100644 --- a/deps/uvwasi/src/uvwasi.c +++ b/deps/uvwasi/src/uvwasi.c @@ -20,7 +20,9 @@ #include "fd_table.h" #include "clocks.h" #include "path_resolver.h" +#include "poll_oneoff.h" #include "wasi_rights.h" +#include "debug.h" /* IBMi PASE does not support posix_fadvise() */ #ifdef __PASE__ @@ -109,9 +111,9 @@ static uvwasi_errno_t uvwasi__lseek(uv_file fd, static uvwasi_errno_t uvwasi__setup_iovs(const uvwasi_t* uvwasi, uv_buf_t** buffers, const uvwasi_iovec_t* iovs, - size_t iovs_len) { + uvwasi_size_t iovs_len) { uv_buf_t* bufs; - size_t i; + uvwasi_size_t i; if ((iovs_len * sizeof(*bufs)) / (sizeof(*bufs)) != iovs_len) return UVWASI_ENOMEM; @@ -131,9 +133,9 @@ static uvwasi_errno_t uvwasi__setup_iovs(const uvwasi_t* uvwasi, static uvwasi_errno_t uvwasi__setup_ciovs(const uvwasi_t* uvwasi, uv_buf_t** buffers, const uvwasi_ciovec_t* iovs, - size_t iovs_len) { + uvwasi_size_t iovs_len) { uv_buf_t* bufs; - size_t i; + uvwasi_size_t i; if ((iovs_len * sizeof(*bufs)) / (sizeof(*bufs)) != iovs_len) return UVWASI_ENOMEM; @@ -154,12 +156,12 @@ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, uvwasi_options_t* options) { uv_fs_t realpath_req; uv_fs_t open_req; uvwasi_errno_t err; - size_t args_size; - size_t size; - size_t offset; - size_t env_count; - size_t env_buf_size; - size_t i; + uvwasi_size_t args_size; + uvwasi_size_t size; + uvwasi_size_t offset; + uvwasi_size_t env_count; + uvwasi_size_t env_buf_size; + uvwasi_size_t i; int r; if (uvwasi == NULL || options == NULL || options->fd_table_size == 0) @@ -173,7 +175,7 @@ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, uvwasi_options_t* options) { uvwasi->argv = NULL; uvwasi->env_buf = NULL; uvwasi->env = NULL; - uvwasi->fds.fds = NULL; + uvwasi->fds = NULL; args_size = 0; for (i = 0; i < options->argc; ++i) @@ -270,7 +272,7 @@ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, uvwasi_options_t* options) { } err = uvwasi_fd_table_insert_preopen(uvwasi, - &uvwasi->fds, + uvwasi->fds, open_req.result, options->preopens[i].mapped_path, realpath_req.ptr); @@ -293,11 +295,12 @@ void uvwasi_destroy(uvwasi_t* uvwasi) { if (uvwasi == NULL) return; - uvwasi_fd_table_free(uvwasi, &uvwasi->fds); + uvwasi_fd_table_free(uvwasi, uvwasi->fds); uvwasi__free(uvwasi, uvwasi->argv_buf); uvwasi__free(uvwasi, uvwasi->argv); uvwasi__free(uvwasi, uvwasi->env_buf); uvwasi__free(uvwasi, uvwasi->env); + uvwasi->fds = NULL; uvwasi->argv_buf = NULL; uvwasi->argv = NULL; uvwasi->env_buf = NULL; @@ -314,7 +317,7 @@ uvwasi_errno_t uvwasi_embedder_remap_fd(uvwasi_t* uvwasi, if (uvwasi == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, 0, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, 0, 0); if (err != UVWASI_ESUCCESS) return err; @@ -325,7 +328,12 @@ uvwasi_errno_t uvwasi_embedder_remap_fd(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_args_get(uvwasi_t* uvwasi, char** argv, char* argv_buf) { - size_t i; + uvwasi_size_t i; + + DEBUG("uvwasi_args_get(uvwasi=%p, argv=%p, argv_buf=%p)\n", + uvwasi, + argv, + argv_buf); if (uvwasi == NULL || argv == NULL || argv_buf == NULL) return UVWASI_EINVAL; @@ -340,8 +348,13 @@ uvwasi_errno_t uvwasi_args_get(uvwasi_t* uvwasi, char** argv, char* argv_buf) { uvwasi_errno_t uvwasi_args_sizes_get(uvwasi_t* uvwasi, - size_t* argc, - size_t* argv_buf_size) { + uvwasi_size_t* argc, + uvwasi_size_t* argv_buf_size) { + DEBUG("uvwasi_args_sizes_get(uvwasi=%p, argc=%p, argv_buf_size=%p)\n", + uvwasi, + argc, + argv_buf_size); + if (uvwasi == NULL || argc == NULL || argv_buf_size == NULL) return UVWASI_EINVAL; @@ -354,6 +367,11 @@ uvwasi_errno_t uvwasi_args_sizes_get(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_clock_res_get(uvwasi_t* uvwasi, uvwasi_clockid_t clock_id, uvwasi_timestamp_t* resolution) { + DEBUG("uvwasi_clock_res_get(uvwasi=%p, clock_id=%d, resolution=%p)\n", + uvwasi, + clock_id, + resolution); + if (uvwasi == NULL || resolution == NULL) return UVWASI_EINVAL; @@ -376,6 +394,13 @@ uvwasi_errno_t uvwasi_clock_time_get(uvwasi_t* uvwasi, uvwasi_clockid_t clock_id, uvwasi_timestamp_t precision, uvwasi_timestamp_t* time) { + DEBUG("uvwasi_clock_time_get(uvwasi=%p, clock_id=%d, " + "precision=%"PRIu64", time=%p)\n", + uvwasi, + clock_id, + precision, + time); + if (uvwasi == NULL || time == NULL) return UVWASI_EINVAL; @@ -398,7 +423,12 @@ uvwasi_errno_t uvwasi_clock_time_get(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_environ_get(uvwasi_t* uvwasi, char** environment, char* environ_buf) { - size_t i; + uvwasi_size_t i; + + DEBUG("uvwasi_environ_get(uvwasi=%p, environment=%p, environ_buf=%p)\n", + uvwasi, + environment, + environ_buf); if (uvwasi == NULL || environment == NULL || environ_buf == NULL) return UVWASI_EINVAL; @@ -413,8 +443,14 @@ uvwasi_errno_t uvwasi_environ_get(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_environ_sizes_get(uvwasi_t* uvwasi, - size_t* environ_count, - size_t* environ_buf_size) { + uvwasi_size_t* environ_count, + uvwasi_size_t* environ_buf_size) { + DEBUG("uvwasi_environ_sizes_get(uvwasi=%p, environ_count=%p, " + "environ_buf_size=%p)\n", + uvwasi, + environ_count, + environ_buf_size); + if (uvwasi == NULL || environ_count == NULL || environ_buf_size == NULL) return UVWASI_EINVAL; @@ -436,6 +472,14 @@ uvwasi_errno_t uvwasi_fd_advise(uvwasi_t* uvwasi, int r; #endif /* POSIX_FADV_NORMAL */ + DEBUG("uvwasi_fd_advise(uvwasi=%p, fd=%d, offset=%"PRIu64", len=%"PRIu64", " + "advice=%d)\n", + uvwasi, + fd, + offset, + len, + advice); + if (uvwasi == NULL) return UVWASI_EINVAL; @@ -474,7 +518,7 @@ uvwasi_errno_t uvwasi_fd_advise(uvwasi_t* uvwasi, return UVWASI_EINVAL; } - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_ADVISE, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_ADVISE, 0); if (err != UVWASI_ESUCCESS) return err; @@ -502,10 +546,17 @@ uvwasi_errno_t uvwasi_fd_allocate(uvwasi_t* uvwasi, uvwasi_errno_t err; int r; + DEBUG("uvwasi_fd_allocate(uvwasi=%p, fd=%d, offset=%"PRIu64", " + "len=%"PRIu64")\n", + uvwasi, + fd, + offset, + len); + if (uvwasi == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_ALLOCATE, @@ -552,12 +603,14 @@ uvwasi_errno_t uvwasi_fd_close(uvwasi_t* uvwasi, uvwasi_fd_t fd) { uv_fs_t req; int r; + DEBUG("uvwasi_fd_close(uvwasi=%p, fd=%d)\n", uvwasi, fd); + if (uvwasi == NULL) return UVWASI_EINVAL; - uvwasi_fd_table_lock(&uvwasi->fds); + uvwasi_fd_table_lock(uvwasi->fds); - err = uvwasi_fd_table_get_nolock(&uvwasi->fds, fd, &wrap, 0, 0); + err = uvwasi_fd_table_get_nolock(uvwasi->fds, fd, &wrap, 0, 0); if (err != UVWASI_ESUCCESS) goto exit; @@ -570,10 +623,10 @@ uvwasi_errno_t uvwasi_fd_close(uvwasi_t* uvwasi, uvwasi_fd_t fd) { goto exit; } - err = uvwasi_fd_table_remove_nolock(uvwasi, &uvwasi->fds, fd); + err = uvwasi_fd_table_remove_nolock(uvwasi, uvwasi->fds, fd); exit: - uvwasi_fd_table_unlock(&uvwasi->fds); + uvwasi_fd_table_unlock(uvwasi->fds); return err; } @@ -584,10 +637,12 @@ uvwasi_errno_t uvwasi_fd_datasync(uvwasi_t* uvwasi, uvwasi_fd_t fd) { uv_fs_t req; int r; + DEBUG("uvwasi_fd_datasync(uvwasi=%p, fd=%d)\n", uvwasi, fd); + if (uvwasi == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_DATASYNC, @@ -615,10 +670,12 @@ uvwasi_errno_t uvwasi_fd_fdstat_get(uvwasi_t* uvwasi, int r; #endif + DEBUG("uvwasi_fd_fdstat_get(uvwasi=%p, fd=%d, buf=%p)\n", uvwasi, fd, buf); + if (uvwasi == NULL || buf == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, 0, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, 0, 0); if (err != UVWASI_ESUCCESS) return err; @@ -646,7 +703,12 @@ uvwasi_errno_t uvwasi_fd_fdstat_set_flags(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_fdflags_t flags) { #ifdef _WIN32 - /* TODO(cjihrig): Missing Windows support. */ + DEBUG("uvwasi_fd_fdstat_set_flags(uvwasi=%p, fd=%d, flags=%d)\n", + uvwasi, + fd, + flags); + + /* TODO(cjihrig): Windows is not supported. */ return UVWASI_ENOSYS; #else struct uvwasi_fd_wrap_t* wrap; @@ -654,10 +716,15 @@ uvwasi_errno_t uvwasi_fd_fdstat_set_flags(uvwasi_t* uvwasi, int mapped_flags; int r; + DEBUG("uvwasi_fd_fdstat_set_flags(uvwasi=%p, fd=%d, flags=%d)\n", + uvwasi, + fd, + flags); + if (uvwasi == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS, @@ -710,10 +777,17 @@ uvwasi_errno_t uvwasi_fd_fdstat_set_rights(uvwasi_t* uvwasi, struct uvwasi_fd_wrap_t* wrap; uvwasi_errno_t err; + DEBUG("uvwasi_fd_fdstat_set_rights(uvwasi=%p, fd=%d, " + "fs_rights_base=%"PRIu64", fs_rights_inheriting=%"PRIu64")\n", + uvwasi, + fd, + fs_rights_base, + fs_rights_inheriting); + if (uvwasi == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, 0, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, 0, 0); if (err != UVWASI_ESUCCESS) return err; @@ -746,10 +820,12 @@ uvwasi_errno_t uvwasi_fd_filestat_get(uvwasi_t* uvwasi, uvwasi_errno_t err; int r; + DEBUG("uvwasi_fd_filestat_get(uvwasi=%p, fd=%d, buf=%p)\n", uvwasi, fd, buf); + if (uvwasi == NULL || buf == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_FILESTAT_GET, @@ -781,10 +857,15 @@ uvwasi_errno_t uvwasi_fd_filestat_set_size(uvwasi_t* uvwasi, uvwasi_errno_t err; int r; + DEBUG("uvwasi_fd_filestat_set_size(uvwasi=%p, fd=%d, st_size=%"PRIu64")\n", + uvwasi, + fd, + st_size); + if (uvwasi == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_FILESTAT_SET_SIZE, @@ -814,6 +895,14 @@ uvwasi_errno_t uvwasi_fd_filestat_set_times(uvwasi_t* uvwasi, uvwasi_errno_t err; int r; + DEBUG("uvwasi_fd_filestat_set_times(uvwasi=%p, fd=%d, st_atim=%"PRIu64", " + "st_mtim=%"PRIu64", fst_flags=%d)\n", + uvwasi, + fd, + st_atim, + st_mtim, + fst_flags); + if (uvwasi == NULL) return UVWASI_EINVAL; @@ -822,7 +911,7 @@ uvwasi_errno_t uvwasi_fd_filestat_set_times(uvwasi_t* uvwasi, return UVWASI_EINVAL; } - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_FILESTAT_SET_TIMES, @@ -845,9 +934,9 @@ uvwasi_errno_t uvwasi_fd_filestat_set_times(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_pread(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_iovec_t* iovs, - size_t iovs_len, + uvwasi_size_t iovs_len, uvwasi_filesize_t offset, - size_t* nread) { + uvwasi_size_t* nread) { struct uvwasi_fd_wrap_t* wrap; uv_buf_t* bufs; uv_fs_t req; @@ -855,10 +944,19 @@ uvwasi_errno_t uvwasi_fd_pread(uvwasi_t* uvwasi, size_t uvread; int r; + DEBUG("uvwasi_fd_pread(uvwasi=%p, fd=%d, iovs=%p, iovs_len=%zu, " + "offset=%"PRIu64", nread=%p)\n", + uvwasi, + fd, + iovs, + iovs_len, + offset, + nread); + if (uvwasi == NULL || iovs == NULL || nread == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_READ | UVWASI_RIGHT_FD_SEEK, @@ -881,7 +979,7 @@ uvwasi_errno_t uvwasi_fd_pread(uvwasi_t* uvwasi, if (r < 0) return uvwasi__translate_uv_error(r); - *nread = uvread; + *nread = (uvwasi_size_t) uvread; return UVWASI_ESUCCESS; } @@ -892,10 +990,15 @@ uvwasi_errno_t uvwasi_fd_prestat_get(uvwasi_t* uvwasi, struct uvwasi_fd_wrap_t* wrap; uvwasi_errno_t err; + DEBUG("uvwasi_fd_prestat_get(uvwasi=%p, fd=%d, buf=%p)\n", + uvwasi, + fd, + buf); + if (uvwasi == NULL || buf == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, 0, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, 0, 0); if (err != UVWASI_ESUCCESS) return err; if (wrap->preopen != 1) { @@ -915,15 +1018,21 @@ uvwasi_errno_t uvwasi_fd_prestat_get(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_prestat_dir_name(uvwasi_t* uvwasi, uvwasi_fd_t fd, char* path, - size_t path_len) { + uvwasi_size_t path_len) { struct uvwasi_fd_wrap_t* wrap; uvwasi_errno_t err; size_t size; + DEBUG("uvwasi_fd_prestat_dir_name(uvwasi=%p, fd=%d, path=%p, path_len=%zu)\n", + uvwasi, + fd, + path, + path_len); + if (uvwasi == NULL || path == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, 0, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, 0, 0); if (err != UVWASI_ESUCCESS) return err; if (wrap->preopen != 1) { @@ -932,7 +1041,7 @@ uvwasi_errno_t uvwasi_fd_prestat_dir_name(uvwasi_t* uvwasi, } size = strlen(wrap->path) + 1; - if (size > path_len) { + if (size > (size_t) path_len) { err = UVWASI_ENOBUFS; goto exit; } @@ -948,9 +1057,9 @@ uvwasi_errno_t uvwasi_fd_prestat_dir_name(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_pwrite(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_ciovec_t* iovs, - size_t iovs_len, + uvwasi_size_t iovs_len, uvwasi_filesize_t offset, - size_t* nwritten) { + uvwasi_size_t* nwritten) { struct uvwasi_fd_wrap_t* wrap; uv_buf_t* bufs; uv_fs_t req; @@ -958,10 +1067,19 @@ uvwasi_errno_t uvwasi_fd_pwrite(uvwasi_t* uvwasi, size_t uvwritten; int r; + DEBUG("uvwasi_fd_pwrite(uvwasi=%p, fd=%d, iovs=%p, iovs_len=%zu, " + "offset=%"PRIu64", nwritten=%p)\n", + uvwasi, + fd, + iovs, + iovs_len, + offset, + nwritten); + if (uvwasi == NULL || iovs == NULL || nwritten == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_WRITE | UVWASI_RIGHT_FD_SEEK, @@ -984,7 +1102,7 @@ uvwasi_errno_t uvwasi_fd_pwrite(uvwasi_t* uvwasi, if (r < 0) return uvwasi__translate_uv_error(r); - *nwritten = uvwritten; + *nwritten = (uvwasi_size_t) uvwritten; return UVWASI_ESUCCESS; } @@ -992,8 +1110,8 @@ uvwasi_errno_t uvwasi_fd_pwrite(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_read(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_iovec_t* iovs, - size_t iovs_len, - size_t* nread) { + uvwasi_size_t iovs_len, + uvwasi_size_t* nread) { struct uvwasi_fd_wrap_t* wrap; uv_buf_t* bufs; uv_fs_t req; @@ -1001,10 +1119,17 @@ uvwasi_errno_t uvwasi_fd_read(uvwasi_t* uvwasi, size_t uvread; int r; + DEBUG("uvwasi_fd_read(uvwasi=%p, fd=%d, iovs=%p, iovs_len=%zu, nread=%p)\n", + uvwasi, + fd, + iovs, + iovs_len, + nread); + if (uvwasi == NULL || iovs == NULL || nread == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_READ, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_READ, 0); if (err != UVWASI_ESUCCESS) return err; @@ -1023,7 +1148,7 @@ uvwasi_errno_t uvwasi_fd_read(uvwasi_t* uvwasi, if (r < 0) return uvwasi__translate_uv_error(r); - *nread = uvread; + *nread = (uvwasi_size_t) uvread; return UVWASI_ESUCCESS; } @@ -1031,9 +1156,9 @@ uvwasi_errno_t uvwasi_fd_read(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi, uvwasi_fd_t fd, void* buf, - size_t buf_len, + uvwasi_size_t buf_len, uvwasi_dircookie_t cookie, - size_t* bufused) { + uvwasi_size_t* bufused) { /* TODO(cjihrig): Support Windows where seekdir() and telldir() are used. */ /* TODO(cjihrig): Avoid opening and closing the directory on each call. */ struct uvwasi_fd_wrap_t* wrap; @@ -1049,10 +1174,19 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi, int i; int r; + DEBUG("uvwasi_fd_readdir(uvwasi=%p, fd=%d, buf=%p, buf_len=%zu, " + "cookie=%"PRIu64", bufused=%p)\n", + uvwasi, + fd, + buf, + buf_len, + cookie, + bufused); + if (uvwasi == NULL || buf == NULL || bufused == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_READDIR, @@ -1171,10 +1305,12 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_renumber(uvwasi_t* uvwasi, uvwasi_fd_t from, uvwasi_fd_t to) { + DEBUG("uvwasi_fd_renumber(uvwasi=%p, from=%d, to=%d)\n", uvwasi, from, to); + if (uvwasi == NULL) return UVWASI_EINVAL; - return uvwasi_fd_table_renumber(uvwasi, &uvwasi->fds, to, from); + return uvwasi_fd_table_renumber(uvwasi, uvwasi->fds, to, from); } @@ -1186,10 +1322,18 @@ uvwasi_errno_t uvwasi_fd_seek(uvwasi_t* uvwasi, struct uvwasi_fd_wrap_t* wrap; uvwasi_errno_t err; + DEBUG("uvwasi_fd_seek(uvwasi=%p, fd=%d, offset=%"PRId64", " + "whence=%d, newoffset=%p)\n", + uvwasi, + fd, + offset, + whence, + newoffset); + if (uvwasi == NULL || newoffset == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_SEEK, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_SEEK, 0); if (err != UVWASI_ESUCCESS) return err; @@ -1205,10 +1349,12 @@ uvwasi_errno_t uvwasi_fd_sync(uvwasi_t* uvwasi, uvwasi_fd_t fd) { uvwasi_errno_t err; int r; + DEBUG("uvwasi_fd_sync(uvwasi=%p, fd=%d)\n", uvwasi, fd); + if (uvwasi == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_SYNC, @@ -1233,10 +1379,12 @@ uvwasi_errno_t uvwasi_fd_tell(uvwasi_t* uvwasi, struct uvwasi_fd_wrap_t* wrap; uvwasi_errno_t err; + DEBUG("uvwasi_fd_tell(uvwasi=%p, fd=%d, offset=%p)\n", uvwasi, fd, offset); + if (uvwasi == NULL || offset == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_TELL, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_TELL, 0); if (err != UVWASI_ESUCCESS) return err; @@ -1249,8 +1397,8 @@ uvwasi_errno_t uvwasi_fd_tell(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_write(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_ciovec_t* iovs, - size_t iovs_len, - size_t* nwritten) { + uvwasi_size_t iovs_len, + uvwasi_size_t* nwritten) { struct uvwasi_fd_wrap_t* wrap; uv_buf_t* bufs; uv_fs_t req; @@ -1258,10 +1406,18 @@ uvwasi_errno_t uvwasi_fd_write(uvwasi_t* uvwasi, size_t uvwritten; int r; + DEBUG("uvwasi_fd_write(uvwasi=%p, fd=%d, iovs=%p, iovs_len=%zu, " + "nwritten=%p)\n", + uvwasi, + fd, + iovs, + iovs_len, + nwritten); + if (uvwasi == NULL || iovs == NULL || nwritten == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_WRITE, 0); + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_FD_WRITE, 0); if (err != UVWASI_ESUCCESS) return err; @@ -1280,7 +1436,7 @@ uvwasi_errno_t uvwasi_fd_write(uvwasi_t* uvwasi, if (r < 0) return uvwasi__translate_uv_error(r); - *nwritten = uvwritten; + *nwritten = (uvwasi_size_t) uvwritten; return UVWASI_ESUCCESS; } @@ -1288,17 +1444,24 @@ uvwasi_errno_t uvwasi_fd_write(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_path_create_directory(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, - size_t path_len) { - char resolved_path[PATH_MAX_BYTES]; + uvwasi_size_t path_len) { + char* resolved_path; struct uvwasi_fd_wrap_t* wrap; uv_fs_t req; uvwasi_errno_t err; int r; + DEBUG("uvwasi_path_create_directory(uvwasi=%p, fd=%d, path='%s', " + "path_len=%zu)\n", + uvwasi, + fd, + path, + path_len); + if (uvwasi == NULL || path == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_PATH_CREATE_DIRECTORY, @@ -1306,12 +1469,13 @@ uvwasi_errno_t uvwasi_path_create_directory(uvwasi_t* uvwasi, if (err != UVWASI_ESUCCESS) return err; - err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, resolved_path, 0); + err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, &resolved_path, 0); if (err != UVWASI_ESUCCESS) goto exit; r = uv_fs_mkdir(NULL, &req, resolved_path, 0777, NULL); uv_fs_req_cleanup(&req); + uvwasi__free(uvwasi, resolved_path); if (r != 0) { err = uvwasi__translate_uv_error(r); @@ -1329,18 +1493,27 @@ uvwasi_errno_t uvwasi_path_filestat_get(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_lookupflags_t flags, const char* path, - size_t path_len, + uvwasi_size_t path_len, uvwasi_filestat_t* buf) { - char resolved_path[PATH_MAX_BYTES]; + char* resolved_path; struct uvwasi_fd_wrap_t* wrap; uv_fs_t req; uvwasi_errno_t err; int r; + DEBUG("uvwasi_path_filestat_get(uvwasi=%p, fd=%d, flags=%d, path='%s', " + "path_len=%zu, buf=%p)\n", + uvwasi, + fd, + flags, + path, + path_len, + buf); + if (uvwasi == NULL || path == NULL || buf == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_PATH_FILESTAT_GET, @@ -1352,12 +1525,13 @@ uvwasi_errno_t uvwasi_path_filestat_get(uvwasi_t* uvwasi, wrap, path, path_len, - resolved_path, + &resolved_path, flags); if (err != UVWASI_ESUCCESS) goto exit; r = uv_fs_stat(NULL, &req, resolved_path, NULL); + uvwasi__free(uvwasi, resolved_path); if (r != 0) { uv_fs_req_cleanup(&req); err = uvwasi__translate_uv_error(r); @@ -1377,17 +1551,28 @@ uvwasi_errno_t uvwasi_path_filestat_set_times(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_lookupflags_t flags, const char* path, - size_t path_len, + uvwasi_size_t path_len, uvwasi_timestamp_t st_atim, uvwasi_timestamp_t st_mtim, uvwasi_fstflags_t fst_flags) { /* TODO(cjihrig): libuv does not currently support nanosecond precision. */ - char resolved_path[PATH_MAX_BYTES]; + char* resolved_path; struct uvwasi_fd_wrap_t* wrap; uv_fs_t req; uvwasi_errno_t err; int r; + DEBUG("uvwasi_path_filestat_set_times(uvwasi=%p, fd=%d, flags=%d, path='%s', " + "path_len=%zu, st_atim=%"PRIu64", st_mtim=%"PRIu64", fst_flags=%d)\n", + uvwasi, + fd, + flags, + path, + path_len, + st_atim, + st_mtim, + fst_flags); + if (uvwasi == NULL || path == NULL) return UVWASI_EINVAL; @@ -1396,7 +1581,7 @@ uvwasi_errno_t uvwasi_path_filestat_set_times(uvwasi_t* uvwasi, return UVWASI_EINVAL; } - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_PATH_FILESTAT_SET_TIMES, @@ -1408,13 +1593,14 @@ uvwasi_errno_t uvwasi_path_filestat_set_times(uvwasi_t* uvwasi, wrap, path, path_len, - resolved_path, + &resolved_path, flags); if (err != UVWASI_ESUCCESS) goto exit; /* TODO(cjihrig): st_atim and st_mtim should not be unconditionally passed. */ r = uv_fs_utime(NULL, &req, resolved_path, st_atim, st_mtim, NULL); + uvwasi__free(uvwasi, resolved_path); uv_fs_req_cleanup(&req); if (r != 0) { @@ -1433,25 +1619,36 @@ uvwasi_errno_t uvwasi_path_link(uvwasi_t* uvwasi, uvwasi_fd_t old_fd, uvwasi_lookupflags_t old_flags, const char* old_path, - size_t old_path_len, + uvwasi_size_t old_path_len, uvwasi_fd_t new_fd, const char* new_path, - size_t new_path_len) { - char resolved_old_path[PATH_MAX_BYTES]; - char resolved_new_path[PATH_MAX_BYTES]; + uvwasi_size_t new_path_len) { + char* resolved_old_path; + char* resolved_new_path; struct uvwasi_fd_wrap_t* old_wrap; struct uvwasi_fd_wrap_t* new_wrap; uvwasi_errno_t err; uv_fs_t req; int r; + DEBUG("uvwasi_path_link(uvwasi=%p, old_fd=%d, old_flags=%d, old_path='%s', " + "old_path_len=%zu, new_fd=%d, new_path='%s', new_path_len=%zu)\n", + uvwasi, + old_fd, + old_flags, + old_path, + old_path_len, + new_fd, + new_path, + new_path_len); + if (uvwasi == NULL || old_path == NULL || new_path == NULL) return UVWASI_EINVAL; - uvwasi_fd_table_lock(&uvwasi->fds); + uvwasi_fd_table_lock(uvwasi->fds); if (old_fd == new_fd) { - err = uvwasi_fd_table_get_nolock(&uvwasi->fds, + err = uvwasi_fd_table_get_nolock(uvwasi->fds, old_fd, &old_wrap, UVWASI_RIGHT_PATH_LINK_SOURCE | @@ -1459,17 +1656,17 @@ uvwasi_errno_t uvwasi_path_link(uvwasi_t* uvwasi, 0); new_wrap = old_wrap; } else { - err = uvwasi_fd_table_get_nolock(&uvwasi->fds, + err = uvwasi_fd_table_get_nolock(uvwasi->fds, old_fd, &old_wrap, UVWASI_RIGHT_PATH_LINK_SOURCE, 0); if (err != UVWASI_ESUCCESS) { - uvwasi_fd_table_unlock(&uvwasi->fds); + uvwasi_fd_table_unlock(uvwasi->fds); return err; } - err = uvwasi_fd_table_get_nolock(&uvwasi->fds, + err = uvwasi_fd_table_get_nolock(uvwasi->fds, new_fd, &new_wrap, UVWASI_RIGHT_PATH_LINK_TARGET, @@ -1478,16 +1675,19 @@ uvwasi_errno_t uvwasi_path_link(uvwasi_t* uvwasi, uv_mutex_unlock(&old_wrap->mutex); } - uvwasi_fd_table_unlock(&uvwasi->fds); + uvwasi_fd_table_unlock(uvwasi->fds); if (err != UVWASI_ESUCCESS) return err; + resolved_old_path = NULL; + resolved_new_path = NULL; + err = uvwasi__resolve_path(uvwasi, old_wrap, old_path, old_path_len, - resolved_old_path, + &resolved_old_path, old_flags); if (err != UVWASI_ESUCCESS) goto exit; @@ -1496,7 +1696,7 @@ uvwasi_errno_t uvwasi_path_link(uvwasi_t* uvwasi, new_wrap, new_path, new_path_len, - resolved_new_path, + &resolved_new_path, 0); if (err != UVWASI_ESUCCESS) goto exit; @@ -1513,6 +1713,9 @@ uvwasi_errno_t uvwasi_path_link(uvwasi_t* uvwasi, uv_mutex_unlock(&new_wrap->mutex); if (old_fd != new_fd) uv_mutex_unlock(&old_wrap->mutex); + + uvwasi__free(uvwasi, resolved_old_path); + uvwasi__free(uvwasi, resolved_new_path); return err; } @@ -1521,13 +1724,13 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, uvwasi_fd_t dirfd, uvwasi_lookupflags_t dirflags, const char* path, - size_t path_len, + uvwasi_size_t path_len, uvwasi_oflags_t o_flags, uvwasi_rights_t fs_rights_base, uvwasi_rights_t fs_rights_inheriting, uvwasi_fdflags_t fs_flags, uvwasi_fd_t* fd) { - char resolved_path[PATH_MAX_BYTES]; + char* resolved_path; uvwasi_rights_t needed_inheriting; uvwasi_rights_t needed_base; uvwasi_rights_t max_base; @@ -1542,6 +1745,20 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, int write; int r; + DEBUG("uvwasi_path_open(uvwasi=%p, dirfd=%d, dirflags=%d, path='%s', " + "path_len=%zu, o_flags=%d, fs_rights_base=%"PRIu64", " + "fs_rights_inheriting=%"PRIu64", fs_flags=%d, fd=%p)\n", + uvwasi, + dirfd, + dirflags, + path, + path_len, + o_flags, + fs_rights_base, + fs_rights_inheriting, + fs_flags, + fd); + if (uvwasi == NULL || path == NULL || fd == NULL) return UVWASI_EINVAL; @@ -1591,7 +1808,7 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, if (write && (flags & (UV_FS_O_APPEND | UV_FS_O_TRUNC)) == 0) needed_inheriting |= UVWASI_RIGHT_FD_SEEK; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, dirfd, &dirfd_wrap, needed_base, @@ -1603,7 +1820,7 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, dirfd_wrap, path, path_len, - resolved_path, + &resolved_path, dirflags); if (err != UVWASI_ESUCCESS) { uv_mutex_unlock(&dirfd_wrap->mutex); @@ -1614,8 +1831,10 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, uv_mutex_unlock(&dirfd_wrap->mutex); uv_fs_req_cleanup(&req); - if (r < 0) + if (r < 0) { + uvwasi__free(uvwasi, resolved_path); return uvwasi__translate_uv_error(r); + } /* Not all platforms support UV_FS_O_DIRECTORY, so get the file type and check it here. */ @@ -1634,7 +1853,7 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, goto close_file_and_error_exit; err = uvwasi_fd_table_insert(uvwasi, - &uvwasi->fds, + uvwasi->fds, r, resolved_path, resolved_path, @@ -1648,11 +1867,13 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, *fd = wrap->id; uv_mutex_unlock(&wrap->mutex); + uvwasi__free(uvwasi, resolved_path); return UVWASI_ESUCCESS; close_file_and_error_exit: uv_fs_close(NULL, &req, r, NULL); uv_fs_req_cleanup(&req); + uvwasi__free(uvwasi, resolved_path); return err; } @@ -1660,21 +1881,31 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, - size_t path_len, + uvwasi_size_t path_len, char* buf, - size_t buf_len, - size_t* bufused) { - char resolved_path[PATH_MAX_BYTES]; + uvwasi_size_t buf_len, + uvwasi_size_t* bufused) { + char* resolved_path; struct uvwasi_fd_wrap_t* wrap; uvwasi_errno_t err; uv_fs_t req; size_t len; int r; + DEBUG("uvwasi_path_readlink(uvwasi=%p, fd=%d, path='%s', path_len=%zu, " + "buf=%p, buf_len=%zu, bufused=%p)\n", + uvwasi, + fd, + path, + path_len, + buf, + buf_len, + bufused); + if (uvwasi == NULL || path == NULL || buf == NULL || bufused == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_PATH_READLINK, @@ -1682,7 +1913,7 @@ uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi, if (err != UVWASI_ESUCCESS) return err; - err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, resolved_path, 0); + err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, &resolved_path, 0); if (err != UVWASI_ESUCCESS) { uv_mutex_unlock(&wrap->mutex); return err; @@ -1690,6 +1921,7 @@ uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi, r = uv_fs_readlink(NULL, &req, resolved_path, NULL); uv_mutex_unlock(&wrap->mutex); + uvwasi__free(uvwasi, resolved_path); if (r != 0) { uv_fs_req_cleanup(&req); return uvwasi__translate_uv_error(r); @@ -1712,17 +1944,24 @@ uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_path_remove_directory(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, - size_t path_len) { - char resolved_path[PATH_MAX_BYTES]; + uvwasi_size_t path_len) { + char* resolved_path; struct uvwasi_fd_wrap_t* wrap; uv_fs_t req; uvwasi_errno_t err; int r; + DEBUG("uvwasi_path_remove_directory(uvwasi=%p, fd=%d, path='%s', " + "path_len=%zu)\n", + uvwasi, + fd, + path, + path_len); + if (uvwasi == NULL || path == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_PATH_REMOVE_DIRECTORY, @@ -1730,7 +1969,7 @@ uvwasi_errno_t uvwasi_path_remove_directory(uvwasi_t* uvwasi, if (err != UVWASI_ESUCCESS) return err; - err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, resolved_path, 0); + err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, &resolved_path, 0); if (err != UVWASI_ESUCCESS) { uv_mutex_unlock(&wrap->mutex); return err; @@ -1738,6 +1977,7 @@ uvwasi_errno_t uvwasi_path_remove_directory(uvwasi_t* uvwasi, r = uv_fs_rmdir(NULL, &req, resolved_path, NULL); uv_mutex_unlock(&wrap->mutex); + uvwasi__free(uvwasi, resolved_path); uv_fs_req_cleanup(&req); if (r != 0) @@ -1750,25 +1990,35 @@ uvwasi_errno_t uvwasi_path_remove_directory(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_path_rename(uvwasi_t* uvwasi, uvwasi_fd_t old_fd, const char* old_path, - size_t old_path_len, + uvwasi_size_t old_path_len, uvwasi_fd_t new_fd, const char* new_path, - size_t new_path_len) { - char resolved_old_path[PATH_MAX_BYTES]; - char resolved_new_path[PATH_MAX_BYTES]; + uvwasi_size_t new_path_len) { + char* resolved_old_path; + char* resolved_new_path; struct uvwasi_fd_wrap_t* old_wrap; struct uvwasi_fd_wrap_t* new_wrap; uvwasi_errno_t err; uv_fs_t req; int r; + DEBUG("uvwasi_path_rename(uvwasi=%p, old_fd=%d, old_path='%s', " + "old_path_len=%zu, new_fd=%d, new_path='%s', new_path_len=%zu)\n", + uvwasi, + old_fd, + old_path, + old_path_len, + new_fd, + new_path, + new_path_len); + if (uvwasi == NULL || old_path == NULL || new_path == NULL) return UVWASI_EINVAL; - uvwasi_fd_table_lock(&uvwasi->fds); + uvwasi_fd_table_lock(uvwasi->fds); if (old_fd == new_fd) { - err = uvwasi_fd_table_get_nolock(&uvwasi->fds, + err = uvwasi_fd_table_get_nolock(uvwasi->fds, old_fd, &old_wrap, UVWASI_RIGHT_PATH_RENAME_SOURCE | @@ -1776,17 +2026,17 @@ uvwasi_errno_t uvwasi_path_rename(uvwasi_t* uvwasi, 0); new_wrap = old_wrap; } else { - err = uvwasi_fd_table_get_nolock(&uvwasi->fds, + err = uvwasi_fd_table_get_nolock(uvwasi->fds, old_fd, &old_wrap, UVWASI_RIGHT_PATH_RENAME_SOURCE, 0); if (err != UVWASI_ESUCCESS) { - uvwasi_fd_table_unlock(&uvwasi->fds); + uvwasi_fd_table_unlock(uvwasi->fds); return err; } - err = uvwasi_fd_table_get_nolock(&uvwasi->fds, + err = uvwasi_fd_table_get_nolock(uvwasi->fds, new_fd, &new_wrap, UVWASI_RIGHT_PATH_RENAME_TARGET, @@ -1795,16 +2045,19 @@ uvwasi_errno_t uvwasi_path_rename(uvwasi_t* uvwasi, uv_mutex_unlock(&old_wrap->mutex); } - uvwasi_fd_table_unlock(&uvwasi->fds); + uvwasi_fd_table_unlock(uvwasi->fds); if (err != UVWASI_ESUCCESS) return err; + resolved_old_path = NULL; + resolved_new_path = NULL; + err = uvwasi__resolve_path(uvwasi, old_wrap, old_path, old_path_len, - resolved_old_path, + &resolved_old_path, 0); if (err != UVWASI_ESUCCESS) goto exit; @@ -1813,7 +2066,7 @@ uvwasi_errno_t uvwasi_path_rename(uvwasi_t* uvwasi, new_wrap, new_path, new_path_len, - resolved_new_path, + &resolved_new_path, 0); if (err != UVWASI_ESUCCESS) goto exit; @@ -1831,26 +2084,37 @@ uvwasi_errno_t uvwasi_path_rename(uvwasi_t* uvwasi, if (old_fd != new_fd) uv_mutex_unlock(&old_wrap->mutex); + uvwasi__free(uvwasi, resolved_old_path); + uvwasi__free(uvwasi, resolved_new_path); return err; } uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi, const char* old_path, - size_t old_path_len, + uvwasi_size_t old_path_len, uvwasi_fd_t fd, const char* new_path, - size_t new_path_len) { - char resolved_new_path[PATH_MAX_BYTES]; + uvwasi_size_t new_path_len) { + char* resolved_new_path; struct uvwasi_fd_wrap_t* wrap; uvwasi_errno_t err; uv_fs_t req; int r; + DEBUG("uvwasi_path_symlink(uvwasi=%p, old_path='%s', old_path_len=%zu, " + "fd=%d, new_path='%s', new_path_len=%zu)\n", + uvwasi, + old_path, + old_path_len, + fd, + new_path, + new_path_len); + if (uvwasi == NULL || old_path == NULL || new_path == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_PATH_SYMLINK, @@ -1862,7 +2126,7 @@ uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi, wrap, new_path, new_path_len, - resolved_new_path, + &resolved_new_path, 0); if (err != UVWASI_ESUCCESS) { uv_mutex_unlock(&wrap->mutex); @@ -1872,6 +2136,7 @@ uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi, /* Windows support may require setting the flags option. */ r = uv_fs_symlink(NULL, &req, old_path, resolved_new_path, 0, NULL); uv_mutex_unlock(&wrap->mutex); + uvwasi__free(uvwasi, resolved_new_path); uv_fs_req_cleanup(&req); if (r != 0) return uvwasi__translate_uv_error(r); @@ -1883,17 +2148,23 @@ uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_path_unlink_file(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, - size_t path_len) { - char resolved_path[PATH_MAX_BYTES]; + uvwasi_size_t path_len) { + char* resolved_path; struct uvwasi_fd_wrap_t* wrap; uv_fs_t req; uvwasi_errno_t err; int r; + DEBUG("uvwasi_path_unlink_file(uvwasi=%p, fd=%d, path='%s', path_len=%zu)\n", + uvwasi, + fd, + path, + path_len); + if (uvwasi == NULL || path == NULL) return UVWASI_EINVAL; - err = uvwasi_fd_table_get(&uvwasi->fds, + err = uvwasi_fd_table_get(uvwasi->fds, fd, &wrap, UVWASI_RIGHT_PATH_UNLINK_FILE, @@ -1901,7 +2172,7 @@ uvwasi_errno_t uvwasi_path_unlink_file(uvwasi_t* uvwasi, if (err != UVWASI_ESUCCESS) return err; - err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, resolved_path, 0); + err = uvwasi__resolve_path(uvwasi, wrap, path, path_len, &resolved_path, 0); if (err != UVWASI_ESUCCESS) { uv_mutex_unlock(&wrap->mutex); return err; @@ -1909,6 +2180,7 @@ uvwasi_errno_t uvwasi_path_unlink_file(uvwasi_t* uvwasi, r = uv_fs_unlink(NULL, &req, resolved_path, NULL); uv_mutex_unlock(&wrap->mutex); + uvwasi__free(uvwasi, resolved_path); uv_fs_req_cleanup(&req); if (r != 0) @@ -1921,14 +2193,127 @@ uvwasi_errno_t uvwasi_path_unlink_file(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_poll_oneoff(uvwasi_t* uvwasi, const uvwasi_subscription_t* in, uvwasi_event_t* out, - size_t nsubscriptions, - size_t* nevents) { - /* TODO(cjihrig): Implement this. */ - return UVWASI_ENOTSUP; + uvwasi_size_t nsubscriptions, + uvwasi_size_t* nevents) { + struct uvwasi_poll_oneoff_state_t state; + struct uvwasi__poll_fdevent_t* fdevent; + uvwasi_userdata_t timer_userdata; + uvwasi_timestamp_t min_timeout; + uvwasi_timestamp_t cur_timeout; + uvwasi_timestamp_t now; + uvwasi_subscription_t sub; + uvwasi_event_t* event; + uvwasi_errno_t err; + int has_timeout; + uvwasi_size_t i; + + DEBUG("uvwasi_poll_oneoff(uvwasi=%p, in=%p, out=%p, nsubscriptions=%zu, " + "nevents=%p)\n", + uvwasi, + in, + out, + nsubscriptions, + nevents); + + if (uvwasi == NULL || in == NULL || out == NULL || + nsubscriptions == 0 || nevents == NULL) { + return UVWASI_EINVAL; + } + + *nevents = 0; + err = uvwasi__poll_oneoff_state_init(uvwasi, &state, nsubscriptions); + if (err != UVWASI_ESUCCESS) + return err; + + has_timeout = 0; + min_timeout = 0; + + for (i = 0; i < nsubscriptions; i++) { + sub = in[i]; + + switch (sub.type) { + case UVWASI_EVENTTYPE_CLOCK: + if (sub.u.clock.flags == UVWASI_SUBSCRIPTION_CLOCK_ABSTIME) { + /* Convert absolute time to relative delay. */ + err = uvwasi__clock_gettime_realtime(&now); + if (err != UVWASI_ESUCCESS) + goto exit; + + cur_timeout = sub.u.clock.timeout - now; + } else { + cur_timeout = sub.u.clock.timeout; + } + + if (has_timeout == 0 || cur_timeout < min_timeout) { + min_timeout = cur_timeout; + timer_userdata = sub.userdata; + has_timeout = 1; + } + + break; + case UVWASI_EVENTTYPE_FD_READ: + case UVWASI_EVENTTYPE_FD_WRITE: + err = uvwasi__poll_oneoff_state_add_fdevent(&state, &sub); + if (err != UVWASI_ESUCCESS) + goto exit; + + break; + default: + err = UVWASI_EINVAL; + goto exit; + } + } + + if (has_timeout == 1) { + err = uvwasi__poll_oneoff_state_set_timer(&state, min_timeout); + if (err != UVWASI_ESUCCESS) + goto exit; + } + + /* Handle poll() errors, then timeouts, then happy path. */ + err = uvwasi__poll_oneoff_run(&state); + if (err != UVWASI_ESUCCESS) { + goto exit; + } else if (state.result == 0) { + event = &out[0]; + event->userdata = timer_userdata; + event->error = UVWASI_ESUCCESS; + event->type = UVWASI_EVENTTYPE_CLOCK; + *nevents = 1; + } else { + for (i = 0; i < state.fdevent_cnt; i++) { + fdevent = &state.fdevents[i]; + event = &out[*nevents]; + + event->userdata = fdevent->userdata; + event->error = fdevent->error; + event->type = fdevent->type; + event->u.fd_readwrite.nbytes = 0; + event->u.fd_readwrite.flags = 0; + + if (fdevent->error != UVWASI_ESUCCESS) + ; + else if ((fdevent->revents & UV_DISCONNECT) != 0) + event->u.fd_readwrite.flags = UVWASI_EVENT_FD_READWRITE_HANGUP; + else if ((fdevent->revents & (UV_READABLE | UV_WRITABLE)) != 0) + ; /* TODO(cjihrig): Set nbytes if type is UVWASI_EVENTTYPE_FD_READ. */ + else + continue; + + *nevents = *nevents + 1; + } + } + + err = UVWASI_ESUCCESS; + +exit: + uvwasi__poll_oneoff_state_cleanup(&state); + return err; } uvwasi_errno_t uvwasi_proc_exit(uvwasi_t* uvwasi, uvwasi_exitcode_t rval) { + DEBUG("uvwasi_proc_exit(uvwasi=%p, rval=%d)\n", uvwasi, rval); exit(rval); return UVWASI_ESUCCESS; /* This doesn't happen. */ } @@ -1937,6 +2322,8 @@ uvwasi_errno_t uvwasi_proc_exit(uvwasi_t* uvwasi, uvwasi_exitcode_t rval) { uvwasi_errno_t uvwasi_proc_raise(uvwasi_t* uvwasi, uvwasi_signal_t sig) { int r; + DEBUG("uvwasi_proc_raise(uvwasi=%p, sig=%d)\n", uvwasi, sig); + if (uvwasi == NULL) return UVWASI_EINVAL; @@ -1952,9 +2339,16 @@ uvwasi_errno_t uvwasi_proc_raise(uvwasi_t* uvwasi, uvwasi_signal_t sig) { } -uvwasi_errno_t uvwasi_random_get(uvwasi_t* uvwasi, void* buf, size_t buf_len) { +uvwasi_errno_t uvwasi_random_get(uvwasi_t* uvwasi, + void* buf, + uvwasi_size_t buf_len) { int r; + DEBUG("uvwasi_random_get(uvwasi=%p, buf=%p, buf_len=%zu)\n", + uvwasi, + buf, + buf_len); + if (uvwasi == NULL || buf == NULL) return UVWASI_EINVAL; @@ -1967,6 +2361,8 @@ uvwasi_errno_t uvwasi_random_get(uvwasi_t* uvwasi, void* buf, size_t buf_len) { uvwasi_errno_t uvwasi_sched_yield(uvwasi_t* uvwasi) { + DEBUG("uvwasi_sched_yield(uvwasi=%p)\n", uvwasi); + if (uvwasi == NULL) return UVWASI_EINVAL; @@ -1984,12 +2380,13 @@ uvwasi_errno_t uvwasi_sched_yield(uvwasi_t* uvwasi) { uvwasi_errno_t uvwasi_sock_recv(uvwasi_t* uvwasi, uvwasi_fd_t sock, const uvwasi_iovec_t* ri_data, - size_t ri_data_len, + uvwasi_size_t ri_data_len, uvwasi_riflags_t ri_flags, - size_t* ro_datalen, + uvwasi_size_t* ro_datalen, uvwasi_roflags_t* ro_flags) { /* TODO(cjihrig): Waiting to implement, pending https://github.com/WebAssembly/WASI/issues/4 */ + DEBUG("uvwasi_sock_recv(uvwasi=%p, unimplemented)\n", uvwasi); return UVWASI_ENOTSUP; } @@ -1997,11 +2394,12 @@ uvwasi_errno_t uvwasi_sock_recv(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_sock_send(uvwasi_t* uvwasi, uvwasi_fd_t sock, const uvwasi_ciovec_t* si_data, - size_t si_data_len, + uvwasi_size_t si_data_len, uvwasi_siflags_t si_flags, - size_t* so_datalen) { + uvwasi_size_t* so_datalen) { /* TODO(cjihrig): Waiting to implement, pending https://github.com/WebAssembly/WASI/issues/4 */ + DEBUG("uvwasi_sock_send(uvwasi=%p, unimplemented)\n", uvwasi); return UVWASI_ENOTSUP; } @@ -2011,6 +2409,7 @@ uvwasi_errno_t uvwasi_sock_shutdown(uvwasi_t* uvwasi, uvwasi_sdflags_t how) { /* TODO(cjihrig): Waiting to implement, pending https://github.com/WebAssembly/WASI/issues/4 */ + DEBUG("uvwasi_sock_shutdown(uvwasi=%p, unimplemented)\n", uvwasi); return UVWASI_ENOTSUP; } diff --git a/deps/uvwasi/src/wasi_serdes.c b/deps/uvwasi/src/wasi_serdes.c new file mode 100644 index 00000000000000..96253fc5af0623 --- /dev/null +++ b/deps/uvwasi/src/wasi_serdes.c @@ -0,0 +1,259 @@ +#include "wasi_serdes.h" +#include "wasi_types.h" + +void uvwasi_serdes_write_uint64_t(void* ptr, + size_t offset, + uint64_t value) { + uvwasi_serdes_write_uint32_t(ptr, offset, (uint32_t) value); + uvwasi_serdes_write_uint32_t(ptr, offset + 4, value >> 32); +} + +void uvwasi_serdes_write_uint32_t(void* ptr, + size_t offset, + uint32_t value) { + uvwasi_serdes_write_uint16_t(ptr, offset, (uint16_t) value); + uvwasi_serdes_write_uint16_t(ptr, offset + 2, value >> 16); +} + +void uvwasi_serdes_write_uint16_t(void* ptr, + size_t offset, + uint16_t value) { + uvwasi_serdes_write_uint8_t(ptr, offset, (uint8_t) value); + uvwasi_serdes_write_uint8_t(ptr, offset + 1, value >> 8); +} + +void uvwasi_serdes_write_uint8_t(void* ptr, + size_t offset, + uint8_t value) { + ((uint8_t*) ptr)[offset] = value; +} + +uint64_t uvwasi_serdes_read_uint64_t(const void* ptr, size_t offset) { + uint64_t low = uvwasi_serdes_read_uint32_t(ptr, offset); + uint64_t high = uvwasi_serdes_read_uint32_t(ptr, offset + 4); + return low | (high << 32); +} + +uint32_t uvwasi_serdes_read_uint32_t(const void* ptr, size_t offset) { + uint32_t low = uvwasi_serdes_read_uint16_t(ptr, offset); + uint32_t high = uvwasi_serdes_read_uint16_t(ptr, offset + 2); + return low | (high << 16); +} + +uint16_t uvwasi_serdes_read_uint16_t(const void* ptr, size_t offset) { + uint16_t low = uvwasi_serdes_read_uint8_t(ptr, offset); + uint16_t high = uvwasi_serdes_read_uint8_t(ptr, offset + 1); + return low | (high << 8); +} + +uint8_t uvwasi_serdes_read_uint8_t(const void* ptr, size_t offset) { + return ((const uint8_t*) ptr)[offset]; +} + +#define TYPE_SWITCH switch (value->type) + +#define ALL_TYPES(STRUCT, FIELD, ALIAS) \ + \ + ALIAS(advice_t, uint8_t) \ + ALIAS(clockid_t, uint32_t) \ + ALIAS(device_t, uint64_t) \ + ALIAS(dircookie_t, uint64_t) \ + ALIAS(errno_t, uint16_t) \ + ALIAS(eventrwflags_t, uint16_t) \ + ALIAS(eventtype_t, uint8_t) \ + ALIAS(exitcode_t, uint32_t) \ + ALIAS(fd_t, uint32_t) \ + ALIAS(fdflags_t, uint16_t) \ + ALIAS(filesize_t, uint64_t) \ + ALIAS(filetype_t, uint8_t) \ + ALIAS(fstflags_t, uint16_t) \ + ALIAS(inode_t, uint64_t) \ + ALIAS(linkcount_t, uint64_t) \ + ALIAS(lookupflags_t, uint32_t) \ + ALIAS(oflags_t, uint16_t) \ + ALIAS(preopentype_t, uint8_t) \ + ALIAS(riflags_t, uint16_t) \ + ALIAS(rights_t, uint64_t) \ + ALIAS(roflags_t, uint16_t) \ + ALIAS(sdflags_t, uint8_t) \ + ALIAS(siflags_t, uint16_t) \ + ALIAS(signal_t, uint8_t) \ + ALIAS(size_t, uint32_t) \ + ALIAS(subclockflags_t, uint16_t) \ + ALIAS(timestamp_t, uint64_t) \ + ALIAS(userdata_t, uint64_t) \ + ALIAS(whence_t, uint8_t) \ + \ + STRUCT(fdstat_t) { \ + FIELD( 0, filetype_t, fs_filetype); \ + FIELD( 2, fdflags_t, fs_flags); \ + FIELD( 8, rights_t, fs_rights_base); \ + FIELD(16, rights_t, fs_rights_inheriting); \ + } \ + \ + STRUCT(filestat_t) { \ + FIELD( 0, device_t, st_dev); \ + FIELD( 8, inode_t, st_ino); \ + FIELD(16, filetype_t, st_filetype); \ + FIELD(24, linkcount_t, st_nlink); \ + FIELD(32, filesize_t, st_size); \ + FIELD(40, timestamp_t, st_atim); \ + FIELD(48, timestamp_t, st_mtim); \ + FIELD(56, timestamp_t, st_ctim); \ + } \ + \ + STRUCT(prestat_t) { \ + FIELD(0, preopentype_t, pr_type); \ + FIELD(4, uint32_t, u.dir.pr_name_len); \ + } \ + \ + STRUCT(event_t) { \ + FIELD( 0, userdata_t, userdata); \ + FIELD( 8, errno_t, error); \ + FIELD(10, eventtype_t, type); \ + TYPE_SWITCH { \ + case UVWASI_EVENTTYPE_FD_READ: \ + case UVWASI_EVENTTYPE_FD_WRITE: \ + FIELD(16, filesize_t, u.fd_readwrite.nbytes); \ + FIELD(24, eventrwflags_t, u.fd_readwrite.flags); \ + } \ + } \ + \ + STRUCT(subscription_t) { \ + FIELD(0, userdata_t, userdata); \ + FIELD(8, eventtype_t, type); \ + TYPE_SWITCH { \ + case UVWASI_EVENTTYPE_CLOCK: \ + FIELD(16, clockid_t, u.clock.clock_id); \ + FIELD(24, timestamp_t, u.clock.timeout); \ + FIELD(32, timestamp_t, u.clock.precision); \ + FIELD(40, subclockflags_t, u.clock.flags); \ + break; \ + case UVWASI_EVENTTYPE_FD_READ: \ + case UVWASI_EVENTTYPE_FD_WRITE: \ + FIELD(16, fd_t, u.fd_readwrite.fd); \ + } \ + } \ + +#define WRITE_STRUCT(name) \ + void uvwasi_serdes_write_##name(void* ptr, \ + size_t offset, \ + const uvwasi_##name* value) \ + +#define READ_STRUCT(name) \ + void uvwasi_serdes_read_##name(const void* ptr, \ + size_t offset, \ + uvwasi_##name* value) \ + +#define WRITE_FIELD(field_offset, type, field) \ + do { \ + uvwasi_serdes_write_##type(ptr, offset + field_offset, value->field); \ + } while (0) \ + +#define READ_FIELD(field_offset, type, field) \ + do { \ + value->field = uvwasi_serdes_read_##type(ptr, offset + field_offset); \ + } while (0) \ + +#define WRITE_ALIAS(new_name, old_name) \ + void uvwasi_serdes_write_##new_name(void* ptr, \ + size_t offset, \ + uvwasi_##new_name value) { \ + uvwasi_serdes_write_##old_name(ptr, offset, value); \ + } \ + +#define READ_ALIAS(new_name, old_name) \ + uvwasi_##new_name uvwasi_serdes_read_##new_name(const void* ptr, \ + size_t offset) { \ + return uvwasi_serdes_read_##old_name(ptr, offset); \ + } \ + +ALL_TYPES(WRITE_STRUCT, WRITE_FIELD, WRITE_ALIAS) +ALL_TYPES(READ_STRUCT, READ_FIELD, READ_ALIAS) + + +uvwasi_errno_t uvwasi_serdes_read_ciovec_t(const void* ptr, + size_t end, + size_t offset, + uvwasi_ciovec_t* value) { + uint32_t buf_ptr; + + buf_ptr = uvwasi_serdes_read_uint32_t(ptr, offset); + value->buf_len = uvwasi_serdes_read_size_t(ptr, offset + 4); + + if (!uvwasi_serdes_check_bounds(buf_ptr, end, value->buf_len)) + return UVWASI_EOVERFLOW; + + value->buf = ((uint8_t*) ptr + buf_ptr); + return UVWASI_ESUCCESS; +} + + +uvwasi_errno_t uvwasi_serdes_read_iovec_t(const void* ptr, + size_t end, + size_t offset, + uvwasi_iovec_t* value) { + uint32_t buf_ptr; + + buf_ptr = uvwasi_serdes_read_uint32_t(ptr, offset); + value->buf_len = uvwasi_serdes_read_size_t(ptr, offset + 4); + + if (!uvwasi_serdes_check_bounds(buf_ptr, end, value->buf_len)) + return UVWASI_EOVERFLOW; + + value->buf = ((uint8_t*) ptr + buf_ptr); + return UVWASI_ESUCCESS; +} + + +uvwasi_errno_t uvwasi_serdes_readv_ciovec_t(const void* ptr, + size_t end, + size_t offset, + uvwasi_ciovec_t* iovs, + uvwasi_size_t iovs_len) { + uvwasi_errno_t err; + uvwasi_size_t i; + + for (i = 0; i < iovs_len; i++) { + err = uvwasi_serdes_read_ciovec_t(ptr, end, offset, &iovs[i]); + if (err != UVWASI_ESUCCESS) + return err; + offset += UVWASI_SERDES_SIZE_ciovec_t; + } + + return UVWASI_ESUCCESS; +} + + +uvwasi_errno_t uvwasi_serdes_readv_iovec_t(const void* ptr, + size_t end, + size_t offset, + uvwasi_iovec_t* iovs, + uvwasi_size_t iovs_len) { + uvwasi_errno_t err; + uvwasi_size_t i; + + for (i = 0; i < iovs_len; i++) { + err = uvwasi_serdes_read_iovec_t(ptr, end, offset, &iovs[i]); + if (err != UVWASI_ESUCCESS) + return err; + offset += UVWASI_SERDES_SIZE_iovec_t; + } + + return UVWASI_ESUCCESS; +} + + +int uvwasi_serdes_check_bounds(size_t offset, size_t end, size_t size) { + return end > offset && size <= (end - offset); +} + + +int uvwasi_serdes_check_array_bounds(size_t offset, + size_t end, + size_t size, + size_t count) { + return end > offset && + ((count * size) / size == count) && + (count * size <= end - offset); +} diff --git a/deps/uvwasi/uvwasi.gyp b/deps/uvwasi/uvwasi.gyp index 42769095ecbafd..d4189eeee2fc94 100644 --- a/deps/uvwasi/uvwasi.gyp +++ b/deps/uvwasi/uvwasi.gyp @@ -12,9 +12,11 @@ 'src/clocks.c', 'src/fd_table.c', 'src/path_resolver.c', + 'src/poll_oneoff.c', 'src/uv_mapping.c', 'src/uvwasi.c', 'src/wasi_rights.c', + 'src/wasi_serdes.c', ], 'dependencies': [ '../uv/uv.gyp:libuv', diff --git a/src/node_wasi.cc b/src/node_wasi.cc index 909023d84e0235..dad8bfc07674de 100644 --- a/src/node_wasi.cc +++ b/src/node_wasi.cc @@ -13,12 +13,6 @@ namespace node { namespace wasi { -static inline bool is_access_oob(size_t mem_size, - uint32_t offset, - uint32_t buf_size) { - return offset + buf_size > mem_size; -} - template inline void Debug(WASI* wasi, Args&&... args) { Debug(wasi->env(), DebugCategory::WASI, std::forward(args)...); @@ -72,7 +66,7 @@ inline void Debug(WASI* wasi, Args&&... args) { #define CHECK_BOUNDS_OR_RETURN(args, mem_size, offset, buf_size) \ do { \ - if (is_access_oob((mem_size), (offset), (buf_size))) { \ + if (!uvwasi_serdes_check_bounds((offset), (mem_size), (buf_size))) { \ (args).GetReturnValue().Set(UVWASI_EOVERFLOW); \ return; \ } \ @@ -185,7 +179,8 @@ void WASI::New(const FunctionCallbackInfo& args) { options.err = 2; options.fd_table_size = 3; options.argc = argc; - options.argv = argc == 0 ? nullptr : new char*[argc]; + options.argv = + const_cast(argc == 0 ? nullptr : new char*[argc]); for (uint32_t i = 0; i < argc; i++) { auto arg = argv->Get(context, i).ToLocalChecked(); @@ -197,7 +192,7 @@ void WASI::New(const FunctionCallbackInfo& args) { Local env_pairs = args[1].As(); const uint32_t envc = env_pairs->Length(); - options.envp = new char*[envc + 1]; + options.envp = const_cast(new char*[envc + 1]); for (uint32_t i = 0; i < envc; i++) { auto pair = env_pairs->Get(context, i).ToLocalChecked(); CHECK(pair->IsString()); @@ -230,13 +225,13 @@ void WASI::New(const FunctionCallbackInfo& args) { if (options.argv != nullptr) { for (uint32_t i = 0; i < argc; i++) - free(options.argv[i]); + free(const_cast(options.argv[i])); delete[] options.argv; } if (options.envp != nullptr) { for (uint32_t i = 0; options.envp[i]; i++) - free(options.envp[i]); + free(const_cast(options.envp[i])); delete[] options.envp; } @@ -267,7 +262,10 @@ void WASI::ArgsGet(const FunctionCallbackInfo& args) { mem_size, argv_buf_offset, wasi->uvw_.argv_buf_size); - CHECK_BOUNDS_OR_RETURN(args, mem_size, argv_offset, wasi->uvw_.argc * 4); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + argv_offset, + wasi->uvw_.argc * UVWASI_SERDES_SIZE_uint32_t); std::vector argv(wasi->uvw_.argc); char* argv_buf = &memory[argv_buf_offset]; uvwasi_errno_t err = uvwasi_args_get(&wasi->uvw_, argv.data(), argv_buf); @@ -275,7 +273,10 @@ void WASI::ArgsGet(const FunctionCallbackInfo& args) { if (err == UVWASI_ESUCCESS) { for (size_t i = 0; i < wasi->uvw_.argc; i++) { uint32_t offset = argv_buf_offset + (argv[i] - argv[0]); - wasi->writeUInt32(memory, offset, argv_offset + (i * 4)); + uvwasi_serdes_write_uint32_t(memory, + argv_offset + + (i * UVWASI_SERDES_SIZE_uint32_t), + offset); } } @@ -295,16 +296,22 @@ void WASI::ArgsSizesGet(const FunctionCallbackInfo& args) { ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "args_sizes_get(%d, %d)\n", argc_offset, argv_buf_offset); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); - CHECK_BOUNDS_OR_RETURN(args, mem_size, argc_offset, 4); - CHECK_BOUNDS_OR_RETURN(args, mem_size, argv_buf_offset, 4); - size_t argc; - size_t argv_buf_size; + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + argc_offset, + UVWASI_SERDES_SIZE_size_t); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + argv_buf_offset, + UVWASI_SERDES_SIZE_size_t); + uvwasi_size_t argc; + uvwasi_size_t argv_buf_size; uvwasi_errno_t err = uvwasi_args_sizes_get(&wasi->uvw_, &argc, &argv_buf_size); if (err == UVWASI_ESUCCESS) { - wasi->writeUInt32(memory, argc, argc_offset); - wasi->writeUInt32(memory, argv_buf_size, argv_buf_offset); + uvwasi_serdes_write_size_t(memory, argc_offset, argc); + uvwasi_serdes_write_size_t(memory, argv_buf_offset, argv_buf_size); } args.GetReturnValue().Set(err); @@ -323,13 +330,16 @@ void WASI::ClockResGet(const FunctionCallbackInfo& args) { ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "clock_res_get(%d, %d)\n", clock_id, resolution_ptr); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); - CHECK_BOUNDS_OR_RETURN(args, mem_size, resolution_ptr, 8); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + resolution_ptr, + UVWASI_SERDES_SIZE_timestamp_t); uvwasi_timestamp_t resolution; uvwasi_errno_t err = uvwasi_clock_res_get(&wasi->uvw_, clock_id, &resolution); if (err == UVWASI_ESUCCESS) - wasi->writeUInt64(memory, resolution, resolution_ptr); + uvwasi_serdes_write_timestamp_t(memory, resolution_ptr, resolution); args.GetReturnValue().Set(err); } @@ -349,14 +359,17 @@ void WASI::ClockTimeGet(const FunctionCallbackInfo& args) { ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "clock_time_get(%d, %d, %d)\n", clock_id, precision, time_ptr); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); - CHECK_BOUNDS_OR_RETURN(args, mem_size, time_ptr, 8); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + time_ptr, + UVWASI_SERDES_SIZE_timestamp_t); uvwasi_timestamp_t time; uvwasi_errno_t err = uvwasi_clock_time_get(&wasi->uvw_, clock_id, precision, &time); if (err == UVWASI_ESUCCESS) - wasi->writeUInt64(memory, time, time_ptr); + uvwasi_serdes_write_timestamp_t(memory, time_ptr, time); args.GetReturnValue().Set(err); } @@ -378,7 +391,10 @@ void WASI::EnvironGet(const FunctionCallbackInfo& args) { mem_size, environ_buf_offset, wasi->uvw_.env_buf_size); - CHECK_BOUNDS_OR_RETURN(args, mem_size, environ_offset, wasi->uvw_.envc * 4); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + environ_offset, + wasi->uvw_.envc * UVWASI_SERDES_SIZE_uint32_t); std::vector environment(wasi->uvw_.envc); char* environ_buf = &memory[environ_buf_offset]; uvwasi_errno_t err = uvwasi_environ_get(&wasi->uvw_, @@ -388,7 +404,11 @@ void WASI::EnvironGet(const FunctionCallbackInfo& args) { if (err == UVWASI_ESUCCESS) { for (size_t i = 0; i < wasi->uvw_.envc; i++) { uint32_t offset = environ_buf_offset + (environment[i] - environment[0]); - wasi->writeUInt32(memory, offset, environ_offset + (i * 4)); + + uvwasi_serdes_write_uint32_t(memory, + environ_offset + + (i * UVWASI_SERDES_SIZE_uint32_t), + offset); } } @@ -408,16 +428,22 @@ void WASI::EnvironSizesGet(const FunctionCallbackInfo& args) { ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "environ_sizes_get(%d, %d)\n", envc_offset, env_buf_offset); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); - CHECK_BOUNDS_OR_RETURN(args, mem_size, envc_offset, 4); - CHECK_BOUNDS_OR_RETURN(args, mem_size, env_buf_offset, 4); - size_t envc; - size_t env_buf_size; + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + envc_offset, + UVWASI_SERDES_SIZE_size_t); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + env_buf_offset, + UVWASI_SERDES_SIZE_size_t); + uvwasi_size_t envc; + uvwasi_size_t env_buf_size; uvwasi_errno_t err = uvwasi_environ_sizes_get(&wasi->uvw_, &envc, &env_buf_size); if (err == UVWASI_ESUCCESS) { - wasi->writeUInt32(memory, envc, envc_offset); - wasi->writeUInt32(memory, env_buf_size, env_buf_offset); + uvwasi_serdes_write_size_t(memory, envc_offset, envc); + uvwasi_serdes_write_size_t(memory, env_buf_offset, env_buf_size); } args.GetReturnValue().Set(err); @@ -494,16 +520,12 @@ void WASI::FdFdstatGet(const FunctionCallbackInfo& args) { ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_fdstat_get(%d, %d)\n", fd, buf); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); - CHECK_BOUNDS_OR_RETURN(args, mem_size, buf, 24); + CHECK_BOUNDS_OR_RETURN(args, mem_size, buf, UVWASI_SERDES_SIZE_fdstat_t); uvwasi_fdstat_t stats; uvwasi_errno_t err = uvwasi_fd_fdstat_get(&wasi->uvw_, fd, &stats); - if (err == UVWASI_ESUCCESS) { - wasi->writeUInt8(memory, stats.fs_filetype, buf); - wasi->writeUInt16(memory, stats.fs_flags, buf + 2); - wasi->writeUInt64(memory, stats.fs_rights_base, buf + 8); - wasi->writeUInt64(memory, stats.fs_rights_inheriting, buf + 16); - } + if (err == UVWASI_ESUCCESS) + uvwasi_serdes_write_fdstat_t(memory, buf, &stats); args.GetReturnValue().Set(err); } @@ -558,20 +580,12 @@ void WASI::FdFilestatGet(const FunctionCallbackInfo& args) { ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_filestat_get(%d, %d)\n", fd, buf); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); - CHECK_BOUNDS_OR_RETURN(args, mem_size, buf, 64); + CHECK_BOUNDS_OR_RETURN(args, mem_size, buf, UVWASI_SERDES_SIZE_filestat_t); uvwasi_filestat_t stats; uvwasi_errno_t err = uvwasi_fd_filestat_get(&wasi->uvw_, fd, &stats); - if (err == UVWASI_ESUCCESS) { - wasi->writeUInt64(memory, stats.st_dev, buf); - wasi->writeUInt64(memory, stats.st_ino, buf + 8); - wasi->writeUInt8(memory, stats.st_filetype, buf + 16); - wasi->writeUInt64(memory, stats.st_nlink, buf + 24); - wasi->writeUInt64(memory, stats.st_size, buf + 32); - wasi->writeUInt64(memory, stats.st_atim, buf + 40); - wasi->writeUInt64(memory, stats.st_mtim, buf + 48); - wasi->writeUInt64(memory, stats.st_ctim, buf + 56); - } + if (err == UVWASI_ESUCCESS) + uvwasi_serdes_write_filestat_t(memory, buf, &stats); args.GetReturnValue().Set(err); } @@ -642,42 +656,30 @@ void WASI::FdPread(const FunctionCallbackInfo& args) { offset, nread_ptr); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); - CHECK_BOUNDS_OR_RETURN(args, mem_size, iovs_ptr, iovs_len * 8); - CHECK_BOUNDS_OR_RETURN(args, mem_size, nread_ptr, 4); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + iovs_ptr, + iovs_len * UVWASI_SERDES_SIZE_iovec_t); + CHECK_BOUNDS_OR_RETURN(args, mem_size, nread_ptr, UVWASI_SERDES_SIZE_size_t); uvwasi_iovec_t* iovs = UncheckedCalloc(iovs_len); + uvwasi_errno_t err; if (iovs == nullptr) { args.GetReturnValue().Set(UVWASI_ENOMEM); return; } - for (uint32_t i = 0; i < iovs_len; ++i) { - uint32_t buf_ptr; - uint32_t buf_len; - - wasi->readUInt32(memory, &buf_ptr, iovs_ptr); - wasi->readUInt32(memory, &buf_len, iovs_ptr + 4); - - if (is_access_oob(mem_size, buf_ptr, buf_len)) { - free(iovs); - args.GetReturnValue().Set(UVWASI_EOVERFLOW); - return; - } - - iovs_ptr += 8; - iovs[i].buf = static_cast(&memory[buf_ptr]); - iovs[i].buf_len = buf_len; + err = uvwasi_serdes_readv_iovec_t(memory, mem_size, iovs_ptr, iovs, iovs_len); + if (err != UVWASI_ESUCCESS) { + free(iovs); + args.GetReturnValue().Set(err); + return; } - size_t nread; - uvwasi_errno_t err = uvwasi_fd_pread(&wasi->uvw_, - fd, - iovs, - iovs_len, - offset, - &nread); + uvwasi_size_t nread; + err = uvwasi_fd_pread(&wasi->uvw_, fd, iovs, iovs_len, offset, &nread); if (err == UVWASI_ESUCCESS) - wasi->writeUInt32(memory, nread, nread_ptr); + uvwasi_serdes_write_size_t(memory, nread_ptr, nread); free(iovs); args.GetReturnValue().Set(err); @@ -696,14 +698,12 @@ void WASI::FdPrestatGet(const FunctionCallbackInfo& args) { ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_prestat_get(%d, %d)\n", fd, buf); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); - CHECK_BOUNDS_OR_RETURN(args, mem_size, buf, 8); + CHECK_BOUNDS_OR_RETURN(args, mem_size, buf, UVWASI_SERDES_SIZE_prestat_t); uvwasi_prestat_t prestat; uvwasi_errno_t err = uvwasi_fd_prestat_get(&wasi->uvw_, fd, &prestat); - if (err == UVWASI_ESUCCESS) { - wasi->writeUInt32(memory, prestat.pr_type, buf); - wasi->writeUInt32(memory, prestat.u.dir.pr_name_len, buf + 4); - } + if (err == UVWASI_ESUCCESS) + uvwasi_serdes_write_prestat_t(memory, buf, &prestat); args.GetReturnValue().Set(err); } @@ -756,42 +756,37 @@ void WASI::FdPwrite(const FunctionCallbackInfo& args) { offset, nwritten_ptr); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); - CHECK_BOUNDS_OR_RETURN(args, mem_size, iovs_ptr, iovs_len * 8); - CHECK_BOUNDS_OR_RETURN(args, mem_size, nwritten_ptr, 4); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + iovs_ptr, + iovs_len * UVWASI_SERDES_SIZE_ciovec_t); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + nwritten_ptr, + UVWASI_SERDES_SIZE_size_t); uvwasi_ciovec_t* iovs = UncheckedCalloc(iovs_len); + uvwasi_errno_t err; if (iovs == nullptr) { args.GetReturnValue().Set(UVWASI_ENOMEM); return; } - for (uint32_t i = 0; i < iovs_len; ++i) { - uint32_t buf_ptr; - uint32_t buf_len; - - wasi->readUInt32(memory, &buf_ptr, iovs_ptr); - wasi->readUInt32(memory, &buf_len, iovs_ptr + 4); - - if (is_access_oob(mem_size, buf_ptr, buf_len)) { - free(iovs); - args.GetReturnValue().Set(UVWASI_EOVERFLOW); - return; - } - - iovs_ptr += 8; - iovs[i].buf = static_cast(&memory[buf_ptr]); - iovs[i].buf_len = buf_len; + err = uvwasi_serdes_readv_ciovec_t(memory, + mem_size, + iovs_ptr, + iovs, + iovs_len); + if (err != UVWASI_ESUCCESS) { + free(iovs); + args.GetReturnValue().Set(err); + return; } - size_t nwritten; - uvwasi_errno_t err = uvwasi_fd_pwrite(&wasi->uvw_, - fd, - iovs, - iovs_len, - offset, - &nwritten); + uvwasi_size_t nwritten; + err = uvwasi_fd_pwrite(&wasi->uvw_, fd, iovs, iovs_len, offset, &nwritten); if (err == UVWASI_ESUCCESS) - wasi->writeUInt32(memory, nwritten, nwritten_ptr); + uvwasi_serdes_write_size_t(memory, nwritten_ptr, nwritten); free(iovs); args.GetReturnValue().Set(err); @@ -814,41 +809,30 @@ void WASI::FdRead(const FunctionCallbackInfo& args) { ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_read(%d, %d, %d, %d)\n", fd, iovs_ptr, iovs_len, nread_ptr); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); - CHECK_BOUNDS_OR_RETURN(args, mem_size, iovs_ptr, iovs_len * 8); - CHECK_BOUNDS_OR_RETURN(args, mem_size, nread_ptr, 4); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + iovs_ptr, + iovs_len * UVWASI_SERDES_SIZE_iovec_t); + CHECK_BOUNDS_OR_RETURN(args, mem_size, nread_ptr, UVWASI_SERDES_SIZE_size_t); uvwasi_iovec_t* iovs = UncheckedCalloc(iovs_len); + uvwasi_errno_t err; if (iovs == nullptr) { args.GetReturnValue().Set(UVWASI_ENOMEM); return; } - for (uint32_t i = 0; i < iovs_len; ++i) { - uint32_t buf_ptr; - uint32_t buf_len; - - wasi->readUInt32(memory, &buf_ptr, iovs_ptr); - wasi->readUInt32(memory, &buf_len, iovs_ptr + 4); - - if (is_access_oob(mem_size, buf_ptr, buf_len)) { - free(iovs); - args.GetReturnValue().Set(UVWASI_EOVERFLOW); - return; - } - - iovs_ptr += 8; - iovs[i].buf = static_cast(&memory[buf_ptr]); - iovs[i].buf_len = buf_len; + err = uvwasi_serdes_readv_iovec_t(memory, mem_size, iovs_ptr, iovs, iovs_len); + if (err != UVWASI_ESUCCESS) { + free(iovs); + args.GetReturnValue().Set(err); + return; } - size_t nread; - uvwasi_errno_t err = uvwasi_fd_read(&wasi->uvw_, - fd, - iovs, - iovs_len, - &nread); + uvwasi_size_t nread; + err = uvwasi_fd_read(&wasi->uvw_, fd, iovs, iovs_len, &nread); if (err == UVWASI_ESUCCESS) - wasi->writeUInt32(memory, nread, nread_ptr); + uvwasi_serdes_write_size_t(memory, nread_ptr, nread); free(iovs); args.GetReturnValue().Set(err); @@ -880,8 +864,11 @@ void WASI::FdReaddir(const FunctionCallbackInfo& args) { bufused_ptr); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, buf_ptr, buf_len); - CHECK_BOUNDS_OR_RETURN(args, mem_size, bufused_ptr, 4); - size_t bufused; + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + bufused_ptr, + UVWASI_SERDES_SIZE_size_t); + uvwasi_size_t bufused; uvwasi_errno_t err = uvwasi_fd_readdir(&wasi->uvw_, fd, &memory[buf_ptr], @@ -889,7 +876,7 @@ void WASI::FdReaddir(const FunctionCallbackInfo& args) { cookie, &bufused); if (err == UVWASI_ESUCCESS) - wasi->writeUInt32(memory, bufused, bufused_ptr); + uvwasi_serdes_write_size_t(memory, bufused_ptr, bufused); args.GetReturnValue().Set(err); } @@ -925,7 +912,10 @@ void WASI::FdSeek(const FunctionCallbackInfo& args) { ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_seek(%d, %d, %d, %d)\n", fd, offset, whence, newoffset_ptr); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); - CHECK_BOUNDS_OR_RETURN(args, mem_size, newoffset_ptr, 8); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + newoffset_ptr, + UVWASI_SERDES_SIZE_filesize_t); uvwasi_filesize_t newoffset; uvwasi_errno_t err = uvwasi_fd_seek(&wasi->uvw_, fd, @@ -933,7 +923,7 @@ void WASI::FdSeek(const FunctionCallbackInfo& args) { whence, &newoffset); if (err == UVWASI_ESUCCESS) - wasi->writeUInt64(memory, newoffset, newoffset_ptr); + uvwasi_serdes_write_filesize_t(memory, newoffset_ptr, newoffset); args.GetReturnValue().Set(err); } @@ -963,12 +953,15 @@ void WASI::FdTell(const FunctionCallbackInfo& args) { ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_tell(%d, %d)\n", fd, offset_ptr); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); - CHECK_BOUNDS_OR_RETURN(args, mem_size, offset_ptr, 8); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + offset_ptr, + UVWASI_SERDES_SIZE_filesize_t); uvwasi_filesize_t offset; uvwasi_errno_t err = uvwasi_fd_tell(&wasi->uvw_, fd, &offset); if (err == UVWASI_ESUCCESS) - wasi->writeUInt64(memory, offset, offset_ptr); + uvwasi_serdes_write_filesize_t(memory, offset_ptr, offset); args.GetReturnValue().Set(err); } @@ -995,41 +988,37 @@ void WASI::FdWrite(const FunctionCallbackInfo& args) { iovs_len, nwritten_ptr); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); - CHECK_BOUNDS_OR_RETURN(args, mem_size, iovs_ptr, iovs_len * 8); - CHECK_BOUNDS_OR_RETURN(args, mem_size, nwritten_ptr, 4); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + iovs_ptr, + iovs_len * UVWASI_SERDES_SIZE_ciovec_t); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + nwritten_ptr, + UVWASI_SERDES_SIZE_size_t); uvwasi_ciovec_t* iovs = UncheckedCalloc(iovs_len); + uvwasi_errno_t err; if (iovs == nullptr) { args.GetReturnValue().Set(UVWASI_ENOMEM); return; } - for (uint32_t i = 0; i < iovs_len; ++i) { - uint32_t buf_ptr; - uint32_t buf_len; - - wasi->readUInt32(memory, &buf_ptr, iovs_ptr); - wasi->readUInt32(memory, &buf_len, iovs_ptr + 4); - - if (is_access_oob(mem_size, buf_ptr, buf_len)) { - free(iovs); - args.GetReturnValue().Set(UVWASI_EOVERFLOW); - return; - } - - iovs_ptr += 8; - iovs[i].buf = static_cast(&memory[buf_ptr]); - iovs[i].buf_len = buf_len; + err = uvwasi_serdes_readv_ciovec_t(memory, + mem_size, + iovs_ptr, + iovs, + iovs_len); + if (err != UVWASI_ESUCCESS) { + free(iovs); + args.GetReturnValue().Set(err); + return; } - size_t nwritten; - uvwasi_errno_t err = uvwasi_fd_write(&wasi->uvw_, - fd, - iovs, - iovs_len, - &nwritten); + uvwasi_size_t nwritten; + err = uvwasi_fd_write(&wasi->uvw_, fd, iovs, iovs_len, &nwritten); if (err == UVWASI_ESUCCESS) - wasi->writeUInt32(memory, nwritten, nwritten_ptr); + uvwasi_serdes_write_size_t(memory, nwritten_ptr, nwritten); free(iovs); args.GetReturnValue().Set(err); @@ -1082,7 +1071,10 @@ void WASI::PathFilestatGet(const FunctionCallbackInfo& args) { path_len); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len); - CHECK_BOUNDS_OR_RETURN(args, mem_size, buf_ptr, 64); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + buf_ptr, + UVWASI_SERDES_SIZE_filestat_t); uvwasi_filestat_t stats; uvwasi_errno_t err = uvwasi_path_filestat_get(&wasi->uvw_, fd, @@ -1090,16 +1082,8 @@ void WASI::PathFilestatGet(const FunctionCallbackInfo& args) { &memory[path_ptr], path_len, &stats); - if (err == UVWASI_ESUCCESS) { - wasi->writeUInt64(memory, stats.st_dev, buf_ptr); - wasi->writeUInt64(memory, stats.st_ino, buf_ptr + 8); - wasi->writeUInt8(memory, stats.st_filetype, buf_ptr + 16); - wasi->writeUInt64(memory, stats.st_nlink, buf_ptr + 24); - wasi->writeUInt64(memory, stats.st_size, buf_ptr + 32); - wasi->writeUInt64(memory, stats.st_atim, buf_ptr + 40); - wasi->writeUInt64(memory, stats.st_mtim, buf_ptr + 48); - wasi->writeUInt64(memory, stats.st_ctim, buf_ptr + 56); - } + if (err == UVWASI_ESUCCESS) + uvwasi_serdes_write_filestat_t(memory, buf_ptr, &stats); args.GetReturnValue().Set(err); } @@ -1229,7 +1213,7 @@ void WASI::PathOpen(const FunctionCallbackInfo& args) { fd_ptr); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len); - CHECK_BOUNDS_OR_RETURN(args, mem_size, fd_ptr, 4); + CHECK_BOUNDS_OR_RETURN(args, mem_size, fd_ptr, UVWASI_SERDES_SIZE_fd_t); uvwasi_fd_t fd; uvwasi_errno_t err = uvwasi_path_open(&wasi->uvw_, dirfd, @@ -1242,7 +1226,7 @@ void WASI::PathOpen(const FunctionCallbackInfo& args) { static_cast(fs_flags), &fd); if (err == UVWASI_ESUCCESS) - wasi->writeUInt32(memory, fd, fd_ptr); + uvwasi_serdes_write_size_t(memory, fd_ptr, fd); args.GetReturnValue().Set(err); } @@ -1277,17 +1261,20 @@ void WASI::PathReadlink(const FunctionCallbackInfo& args) { GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len); CHECK_BOUNDS_OR_RETURN(args, mem_size, buf_ptr, buf_len); - CHECK_BOUNDS_OR_RETURN(args, mem_size, bufused_ptr, 4); - size_t bufused; + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + bufused_ptr, + UVWASI_SERDES_SIZE_size_t); + uvwasi_size_t bufused; uvwasi_errno_t err = uvwasi_path_readlink(&wasi->uvw_, - fd, - &memory[path_ptr], - path_len, - &memory[buf_ptr], - buf_len, - &bufused); + fd, + &memory[path_ptr], + path_len, + &memory[buf_ptr], + buf_len, + &bufused); if (err == UVWASI_ESUCCESS) - wasi->writeUInt32(memory, bufused, bufused_ptr); + uvwasi_serdes_write_size_t(memory, bufused_ptr, bufused); args.GetReturnValue().Set(err); } @@ -1436,9 +1423,18 @@ void WASI::PollOneoff(const FunctionCallbackInfo& args) { nsubscriptions, nevents_ptr); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); - CHECK_BOUNDS_OR_RETURN(args, mem_size, in_ptr, nsubscriptions * 48); - CHECK_BOUNDS_OR_RETURN(args, mem_size, out_ptr, nsubscriptions * 32); - CHECK_BOUNDS_OR_RETURN(args, mem_size, nevents_ptr, 4); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + in_ptr, + nsubscriptions * UVWASI_SERDES_SIZE_subscription_t); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + out_ptr, + nsubscriptions * UVWASI_SERDES_SIZE_event_t); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + nevents_ptr, + UVWASI_SERDES_SIZE_size_t); uvwasi_subscription_t* in = UncheckedCalloc(nsubscriptions); @@ -1456,46 +1452,22 @@ void WASI::PollOneoff(const FunctionCallbackInfo& args) { } for (uint32_t i = 0; i < nsubscriptions; ++i) { - uvwasi_subscription_t* sub = &in[i]; - wasi->readUInt64(memory, &sub->userdata, in_ptr); - wasi->readUInt8(memory, &sub->type, in_ptr + 8); - - if (sub->type == UVWASI_EVENTTYPE_CLOCK) { - wasi->readUInt32(memory, &sub->u.clock.clock_id, in_ptr + 16); - wasi->readUInt64(memory, &sub->u.clock.timeout, in_ptr + 24); - wasi->readUInt64(memory, &sub->u.clock.precision, in_ptr + 32); - wasi->readUInt16(memory, &sub->u.clock.flags, in_ptr + 40); - } else if (sub->type == UVWASI_EVENTTYPE_FD_READ || - sub->type == UVWASI_EVENTTYPE_FD_WRITE) { - wasi->readUInt32(memory, &sub->u.fd_readwrite.fd, in_ptr + 16); - } - - in_ptr += 48; + uvwasi_serdes_read_subscription_t(memory, in_ptr, &in[i]); + in_ptr += UVWASI_SERDES_SIZE_subscription_t; } - size_t nevents; + uvwasi_size_t nevents; uvwasi_errno_t err = uvwasi_poll_oneoff(&wasi->uvw_, in, out, nsubscriptions, &nevents); if (err == UVWASI_ESUCCESS) { - wasi->writeUInt32(memory, nevents, nevents_ptr); + uvwasi_serdes_write_size_t(memory, nevents_ptr, nevents); for (uint32_t i = 0; i < nsubscriptions; ++i) { - uvwasi_event_t event = out[i]; - - wasi->writeUInt64(memory, event.userdata, out_ptr); - wasi->writeUInt16(memory, event.error, out_ptr + 8); - wasi->writeUInt8(memory, event.type, out_ptr + 10); - - if (event.type == UVWASI_EVENTTYPE_FD_READ || - event.type == UVWASI_EVENTTYPE_FD_WRITE) { - wasi->writeUInt64(memory, event.u.fd_readwrite.nbytes, out_ptr + 16); - wasi->writeUInt16(memory, event.u.fd_readwrite.flags, out_ptr + 24); - } - - out_ptr += 32; + uvwasi_serdes_write_event_t(memory, out_ptr, &out[i]); + out_ptr += UVWASI_SERDES_SIZE_event_t; } } @@ -1585,7 +1557,10 @@ void WASI::SockRecv(const FunctionCallbackInfo& args) { ro_datalen_ptr, ro_flags_ptr); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); - CHECK_BOUNDS_OR_RETURN(args, mem_size, ri_data_ptr, ri_data_len * 8); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + ri_data_ptr, + ri_data_len * UVWASI_SERDES_SIZE_iovec_t); CHECK_BOUNDS_OR_RETURN(args, mem_size, ro_datalen_ptr, 4); CHECK_BOUNDS_OR_RETURN(args, mem_size, ro_flags_ptr, 4); uvwasi_iovec_t* ri_data = UncheckedCalloc(ri_data_len); @@ -1595,36 +1570,29 @@ void WASI::SockRecv(const FunctionCallbackInfo& args) { return; } - for (uint32_t i = 0; i < ri_data_len; ++i) { - uint32_t buf_ptr; - uint32_t buf_len; - - wasi->readUInt32(memory, &buf_ptr, ri_data_ptr); - wasi->readUInt32(memory, &buf_len, ri_data_ptr + 4); - - if (is_access_oob(mem_size, buf_ptr, buf_len)) { - free(ri_data); - args.GetReturnValue().Set(UVWASI_EOVERFLOW); - return; - } - - ri_data_ptr += 8; - ri_data[i].buf = static_cast(&memory[buf_ptr]); - ri_data[i].buf_len = buf_len; + uvwasi_errno_t err = uvwasi_serdes_readv_iovec_t(memory, + mem_size, + ri_data_ptr, + ri_data, + ri_data_len); + if (err != UVWASI_ESUCCESS) { + free(ri_data); + args.GetReturnValue().Set(err); + return; } - size_t ro_datalen; + uvwasi_size_t ro_datalen; uvwasi_roflags_t ro_flags; - uvwasi_errno_t err = uvwasi_sock_recv(&wasi->uvw_, - sock, - ri_data, - ri_data_len, - ri_flags, - &ro_datalen, - &ro_flags); + err = uvwasi_sock_recv(&wasi->uvw_, + sock, + ri_data, + ri_data_len, + ri_flags, + &ro_datalen, + &ro_flags); if (err == UVWASI_ESUCCESS) { - wasi->writeUInt32(memory, ro_datalen, ro_datalen_ptr); - wasi->writeUInt32(memory, ro_flags, ro_flags_ptr); + uvwasi_serdes_write_size_t(memory, ro_datalen_ptr, ro_datalen); + uvwasi_serdes_write_roflags_t(memory, ro_flags_ptr, ro_flags); } free(ri_data); @@ -1656,8 +1624,14 @@ void WASI::SockSend(const FunctionCallbackInfo& args) { si_flags, so_datalen_ptr); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); - CHECK_BOUNDS_OR_RETURN(args, mem_size, si_data_ptr, si_data_len * 8); - CHECK_BOUNDS_OR_RETURN(args, mem_size, so_datalen_ptr, 4); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + si_data_ptr, + si_data_len * UVWASI_SERDES_SIZE_ciovec_t); + CHECK_BOUNDS_OR_RETURN(args, + mem_size, + so_datalen_ptr, + UVWASI_SERDES_SIZE_size_t); uvwasi_ciovec_t* si_data = UncheckedCalloc(si_data_len); if (si_data == nullptr) { @@ -1665,33 +1639,26 @@ void WASI::SockSend(const FunctionCallbackInfo& args) { return; } - for (uint32_t i = 0; i < si_data_len; ++i) { - uint32_t buf_ptr; - uint32_t buf_len; - - wasi->readUInt32(memory, &buf_ptr, si_data_ptr); - wasi->readUInt32(memory, &buf_len, si_data_ptr + 4); - - if (is_access_oob(mem_size, buf_ptr, buf_len)) { - free(si_data); - args.GetReturnValue().Set(UVWASI_EOVERFLOW); - return; - } - - si_data_ptr += 8; - si_data[i].buf = static_cast(&memory[buf_ptr]); - si_data[i].buf_len = buf_len; + uvwasi_errno_t err = uvwasi_serdes_readv_ciovec_t(memory, + mem_size, + si_data_ptr, + si_data, + si_data_len); + if (err != UVWASI_ESUCCESS) { + free(si_data); + args.GetReturnValue().Set(err); + return; } - size_t so_datalen; - uvwasi_errno_t err = uvwasi_sock_send(&wasi->uvw_, - sock, - si_data, - si_data_len, - si_flags, - &so_datalen); + uvwasi_size_t so_datalen; + err = uvwasi_sock_send(&wasi->uvw_, + sock, + si_data, + si_data_len, + si_flags, + &so_datalen); if (err == UVWASI_ESUCCESS) - wasi->writeUInt32(memory, so_datalen, so_datalen_ptr); + uvwasi_serdes_write_size_t(memory, so_datalen_ptr, so_datalen); free(si_data); args.GetReturnValue().Set(err); @@ -1721,81 +1688,6 @@ void WASI::_SetMemory(const FunctionCallbackInfo& args) { } -void WASI::readUInt8(char* memory, uint8_t* value, uint32_t offset) { - CHECK_NOT_NULL(memory); - CHECK_NOT_NULL(value); - *value = memory[offset] & 0xFF; -} - - -void WASI::readUInt16(char* memory, uint16_t* value, uint32_t offset) { - CHECK_NOT_NULL(memory); - CHECK_NOT_NULL(value); - *value = (memory[offset] & 0xFF) | - ((memory[offset + 1] & 0xFF) << 8); -} - - -void WASI::readUInt32(char* memory, uint32_t* value, uint32_t offset) { - CHECK_NOT_NULL(memory); - CHECK_NOT_NULL(value); - *value = (memory[offset] & 0xFF) | - ((memory[offset + 1] & 0xFF) << 8) | - ((memory[offset + 2] & 0xFF) << 16) | - ((memory[offset + 3] & 0xFF) << 24); -} - - -void WASI::readUInt64(char* memory, uint64_t* value, uint32_t offset) { - CHECK_NOT_NULL(memory); - CHECK_NOT_NULL(value); - uint64_t low = (memory[offset] & 0xFF) | - ((memory[offset + 1] & 0xFF) << 8) | - ((memory[offset + 2] & 0xFF) << 16) | - ((memory[offset + 3] & 0xFF) << 24); - uint64_t high = (memory[offset + 4] & 0xFF) | - ((memory[offset + 5] & 0xFF) << 8) | - ((memory[offset + 6] & 0xFF) << 16) | - ((memory[offset + 7] & 0xFF) << 24); - *value = (high << 32) + low; -} - - -void WASI::writeUInt8(char* memory, uint8_t value, uint32_t offset) { - CHECK_NOT_NULL(memory); - memory[offset] = value & 0xFF; -} - - -void WASI::writeUInt16(char* memory, uint16_t value, uint32_t offset) { - CHECK_NOT_NULL(memory); - memory[offset++] = value & 0xFF; - memory[offset] = (value >> 8) & 0xFF; -} - - -void WASI::writeUInt32(char* memory, uint32_t value, uint32_t offset) { - CHECK_NOT_NULL(memory); - memory[offset++] = value & 0xFF; - memory[offset++] = (value >> 8) & 0xFF; - memory[offset++] = (value >> 16) & 0xFF; - memory[offset] = (value >> 24) & 0xFF; -} - - -void WASI::writeUInt64(char* memory, uint64_t value, uint32_t offset) { - CHECK_NOT_NULL(memory); - memory[offset++] = value & 0xFF; - memory[offset++] = (value >> 8) & 0xFF; - memory[offset++] = (value >> 16) & 0xFF; - memory[offset++] = (value >> 24) & 0xFF; - memory[offset++] = (value >> 32) & 0xFF; - memory[offset++] = (value >> 40) & 0xFF; - memory[offset++] = (value >> 48) & 0xFF; - memory[offset] = (value >> 56) & 0xFF; -} - - uvwasi_errno_t WASI::backingStore(char** store, size_t* byte_length) { Environment* env = this->env(); Local memory = PersistentToLocal::Strong(this->memory_); @@ -1811,6 +1703,7 @@ uvwasi_errno_t WASI::backingStore(char** store, size_t* byte_length) { std::shared_ptr backing_store = ab->GetBackingStore(); *byte_length = backing_store->ByteLength(); *store = static_cast(backing_store->Data()); + CHECK_NOT_NULL(*store); return UVWASI_ESUCCESS; }