From 4302d247ad5d8a51973ae9ebf7aca727db190a74 Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Tue, 9 Sep 2025 02:03:59 +0100 Subject: [PATCH] deps: update uvwasi to 0.0.23 PR-URL: https://github.com/nodejs/node/pull/59791 Reviewed-By: Antoine du Hamel Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig Reviewed-By: Marco Ippolito Reviewed-By: Rafael Gonzaga --- deps/uvwasi/include/uvwasi.h | 53 +++++++++++++++- deps/uvwasi/include/wasi_serdes.h | 9 +++ deps/uvwasi/include/wasi_types.h | 6 ++ deps/uvwasi/src/path_resolver.c | 36 ++++++++++- deps/uvwasi/src/uvwasi.c | 101 +++++++++++++++++++++--------- 5 files changed, 172 insertions(+), 33 deletions(-) diff --git a/deps/uvwasi/include/uvwasi.h b/deps/uvwasi/include/uvwasi.h index 7dbcc66779..2a9d45207b 100644 --- a/deps/uvwasi/include/uvwasi.h +++ b/deps/uvwasi/include/uvwasi.h @@ -11,7 +11,7 @@ extern "C" { #define UVWASI_VERSION_MAJOR 0 #define UVWASI_VERSION_MINOR 0 -#define UVWASI_VERSION_PATCH 21 +#define UVWASI_VERSION_PATCH 23 #define UVWASI_VERSION_HEX ((UVWASI_VERSION_MAJOR << 16) | \ (UVWASI_VERSION_MINOR << 8) | \ (UVWASI_VERSION_PATCH)) @@ -77,124 +77,159 @@ typedef struct uvwasi_options_s { } uvwasi_options_t; /* Embedder API. */ +UVWASI_EXPORT uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, const uvwasi_options_t* options); +UVWASI_EXPORT void uvwasi_destroy(uvwasi_t* uvwasi); +UVWASI_EXPORT void uvwasi_options_init(uvwasi_options_t* options); /* Use int instead of uv_file to avoid needing uv.h */ +UVWASI_EXPORT uvwasi_errno_t uvwasi_embedder_remap_fd(uvwasi_t* uvwasi, const uvwasi_fd_t fd, int new_host_fd); +UVWASI_EXPORT const char* uvwasi_embedder_err_code_to_string(uvwasi_errno_t code); /* WASI system call API. */ +UVWASI_EXPORT uvwasi_errno_t uvwasi_args_get(uvwasi_t* uvwasi, char** argv, char* argv_buf); +UVWASI_EXPORT uvwasi_errno_t uvwasi_args_sizes_get(uvwasi_t* uvwasi, uvwasi_size_t* argc, uvwasi_size_t* argv_buf_size); +UVWASI_EXPORT uvwasi_errno_t uvwasi_clock_res_get(uvwasi_t* uvwasi, uvwasi_clockid_t clock_id, uvwasi_timestamp_t* resolution); +UVWASI_EXPORT uvwasi_errno_t uvwasi_clock_time_get(uvwasi_t* uvwasi, uvwasi_clockid_t clock_id, uvwasi_timestamp_t precision, uvwasi_timestamp_t* time); +UVWASI_EXPORT uvwasi_errno_t uvwasi_environ_get(uvwasi_t* uvwasi, char** environment, char* environ_buf); +UVWASI_EXPORT uvwasi_errno_t uvwasi_environ_sizes_get(uvwasi_t* uvwasi, uvwasi_size_t* environ_count, uvwasi_size_t* environ_buf_size); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_advise(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_filesize_t offset, uvwasi_filesize_t len, uvwasi_advice_t advice); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_allocate(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_filesize_t offset, uvwasi_filesize_t len); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_close(uvwasi_t* uvwasi, uvwasi_fd_t fd); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_datasync(uvwasi_t* uvwasi, uvwasi_fd_t fd); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_fdstat_get(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_fdstat_t* buf); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_fdstat_set_flags(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_fdflags_t flags); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_fdstat_set_rights(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_rights_t fs_rights_base, uvwasi_rights_t fs_rights_inheriting ); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_filestat_get(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_filestat_t* buf); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_filestat_set_size(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_filesize_t st_size); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_filestat_set_times(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_timestamp_t st_atim, uvwasi_timestamp_t st_mtim, uvwasi_fstflags_t fst_flags); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_pread(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_iovec_t* iovs, uvwasi_size_t iovs_len, uvwasi_filesize_t offset, uvwasi_size_t* nread); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_prestat_get(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_prestat_t* buf); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_prestat_dir_name(uvwasi_t* uvwasi, uvwasi_fd_t fd, char* path, uvwasi_size_t path_len); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_pwrite(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_ciovec_t* iovs, uvwasi_size_t iovs_len, uvwasi_filesize_t offset, uvwasi_size_t* nwritten); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_read(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_iovec_t* iovs, uvwasi_size_t iovs_len, uvwasi_size_t* nread); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi, uvwasi_fd_t fd, void* buf, uvwasi_size_t buf_len, uvwasi_dircookie_t cookie, uvwasi_size_t* bufused); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_renumber(uvwasi_t* uvwasi, uvwasi_fd_t from, uvwasi_fd_t to); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_seek(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_filedelta_t offset, uvwasi_whence_t whence, uvwasi_filesize_t* newoffset); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_sync(uvwasi_t* uvwasi, uvwasi_fd_t fd); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_tell(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_filesize_t* offset); +UVWASI_EXPORT uvwasi_errno_t uvwasi_fd_write(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_ciovec_t* iovs, uvwasi_size_t iovs_len, uvwasi_size_t* nwritten); +UVWASI_EXPORT uvwasi_errno_t uvwasi_path_create_directory(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, uvwasi_size_t path_len); +UVWASI_EXPORT uvwasi_errno_t uvwasi_path_filestat_get(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_lookupflags_t flags, const char* path, uvwasi_size_t path_len, uvwasi_filestat_t* buf); +UVWASI_EXPORT uvwasi_errno_t uvwasi_path_filestat_set_times(uvwasi_t* uvwasi, uvwasi_fd_t fd, uvwasi_lookupflags_t flags, @@ -203,6 +238,7 @@ uvwasi_errno_t uvwasi_path_filestat_set_times(uvwasi_t* uvwasi, uvwasi_timestamp_t st_atim, uvwasi_timestamp_t st_mtim, uvwasi_fstflags_t fst_flags); +UVWASI_EXPORT uvwasi_errno_t uvwasi_path_link(uvwasi_t* uvwasi, uvwasi_fd_t old_fd, uvwasi_lookupflags_t old_flags, @@ -211,6 +247,7 @@ uvwasi_errno_t uvwasi_path_link(uvwasi_t* uvwasi, uvwasi_fd_t new_fd, const char* new_path, uvwasi_size_t new_path_len); +UVWASI_EXPORT uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, uvwasi_fd_t dirfd, uvwasi_lookupflags_t dirflags, @@ -221,6 +258,7 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, uvwasi_rights_t fs_rights_inheriting, uvwasi_fdflags_t fs_flags, uvwasi_fd_t* fd); +UVWASI_EXPORT uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, @@ -228,10 +266,12 @@ uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi, char* buf, uvwasi_size_t buf_len, uvwasi_size_t* bufused); +UVWASI_EXPORT uvwasi_errno_t uvwasi_path_remove_directory(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, uvwasi_size_t path_len); +UVWASI_EXPORT uvwasi_errno_t uvwasi_path_rename(uvwasi_t* uvwasi, uvwasi_fd_t old_fd, const char* old_path, @@ -239,31 +279,40 @@ uvwasi_errno_t uvwasi_path_rename(uvwasi_t* uvwasi, uvwasi_fd_t new_fd, const char* new_path, uvwasi_size_t new_path_len); +UVWASI_EXPORT uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi, const char* old_path, uvwasi_size_t old_path_len, uvwasi_fd_t fd, const char* new_path, uvwasi_size_t new_path_len); +UVWASI_EXPORT uvwasi_errno_t uvwasi_path_unlink_file(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, uvwasi_size_t path_len); +UVWASI_EXPORT uvwasi_errno_t uvwasi_poll_oneoff(uvwasi_t* uvwasi, const uvwasi_subscription_t* in, uvwasi_event_t* out, uvwasi_size_t nsubscriptions, uvwasi_size_t* nevents); +UVWASI_EXPORT uvwasi_errno_t uvwasi_proc_exit(uvwasi_t* uvwasi, uvwasi_exitcode_t rval); +UVWASI_EXPORT uvwasi_errno_t uvwasi_proc_raise(uvwasi_t* uvwasi, uvwasi_signal_t sig); +UVWASI_EXPORT uvwasi_errno_t uvwasi_random_get(uvwasi_t* uvwasi, void* buf, uvwasi_size_t buf_len); +UVWASI_EXPORT uvwasi_errno_t uvwasi_sched_yield(uvwasi_t* uvwasi); +UVWASI_EXPORT uvwasi_errno_t uvwasi_sock_accept(uvwasi_t* uvwasi, uvwasi_fd_t sock, uvwasi_fdflags_t flags, uvwasi_fd_t* fd); +UVWASI_EXPORT uvwasi_errno_t uvwasi_sock_recv(uvwasi_t* uvwasi, uvwasi_fd_t sock, const uvwasi_iovec_t* ri_data, @@ -271,12 +320,14 @@ uvwasi_errno_t uvwasi_sock_recv(uvwasi_t* uvwasi, uvwasi_riflags_t ri_flags, uvwasi_size_t* ro_datalen, uvwasi_roflags_t* ro_flags); +UVWASI_EXPORT uvwasi_errno_t uvwasi_sock_send(uvwasi_t* uvwasi, uvwasi_fd_t sock, const uvwasi_ciovec_t* si_data, uvwasi_size_t si_data_len, uvwasi_siflags_t si_flags, uvwasi_size_t* so_datalen); +UVWASI_EXPORT 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 index 038ae74786..b482918855 100644 --- a/deps/uvwasi/include/wasi_serdes.h +++ b/deps/uvwasi/include/wasi_serdes.h @@ -6,7 +6,9 @@ /* Basic uint{8,16,32,64}_t read/write functions. */ #define BASIC_TYPE(name, type) \ + UVWASI_EXPORT \ void uvwasi_serdes_write_##name(void* ptr, size_t offset, type value); \ + UVWASI_EXPORT \ type uvwasi_serdes_read_##name(const void* ptr, size_t offset); \ #define BASIC_TYPE_UVWASI(type) BASIC_TYPE(type, uvwasi_##type) @@ -83,15 +85,18 @@ BASIC_TYPE_UVWASI(whence_t) /* WASI structure read/write functions. */ #define STRUCT(name) \ + UVWASI_EXPORT \ void uvwasi_serdes_write_##name(void* ptr, \ size_t offset, \ const uvwasi_##name* value); \ + UVWASI_EXPORT \ 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_EXPORT \ uvwasi_errno_t uvwasi_serdes_read_##name(const void* ptr, \ size_t end, \ size_t offset, \ @@ -124,12 +129,14 @@ STRUCT(subscription_t) #undef STRUCT #undef IOVS_STRUCT +UVWASI_EXPORT 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_EXPORT uvwasi_errno_t uvwasi_serdes_readv_iovec_t(const void* ptr, size_t end, size_t offset, @@ -137,7 +144,9 @@ uvwasi_errno_t uvwasi_serdes_readv_iovec_t(const void* ptr, uvwasi_size_t iovs_len); /* Helper functions for memory bounds checking. */ +UVWASI_EXPORT int uvwasi_serdes_check_bounds(size_t offset, size_t end, size_t size); +UVWASI_EXPORT int uvwasi_serdes_check_array_bounds(size_t offset, size_t end, size_t size, diff --git a/deps/uvwasi/include/wasi_types.h b/deps/uvwasi/include/wasi_types.h index 045c552880..85eadd73b9 100644 --- a/deps/uvwasi/include/wasi_types.h +++ b/deps/uvwasi/include/wasi_types.h @@ -322,4 +322,10 @@ typedef uint8_t uvwasi_whence_t; #define UVWASI_WHENCE_CUR 1 #define UVWASI_WHENCE_END 2 +#ifdef NEED_UVWASI_EXPORT + #define UVWASI_EXPORT __attribute__((visibility("default"))) +#else + #define UVWASI_EXPORT +#endif /* NEED_UVWASI_EXPORT */ + #endif /* __UVWASI_WASI_TYPES_H__ */ diff --git a/deps/uvwasi/src/path_resolver.c b/deps/uvwasi/src/path_resolver.c index deb3f60382..8a73f03d54 100644 --- a/deps/uvwasi/src/path_resolver.c +++ b/deps/uvwasi/src/path_resolver.c @@ -72,16 +72,23 @@ uvwasi_errno_t uvwasi__normalize_path(const char* path, uvwasi_size_t path_len, char* normalized_path, uvwasi_size_t normalized_len) { + /* Normalizes path and stores the resulting buffer in normalized_path. + the sizes of the buffers must correspond to strlen() of the relevant + buffers, i.e. there must be room in the relevant buffers for a + NULL-byte. */ const char* cur; char* ptr; char* next; char* last; size_t cur_len; int is_absolute; + int has_trailing_slash; if (path_len > normalized_len) return UVWASI_ENOBUFS; + has_trailing_slash = path_len > 0 && IS_SLASH(path[path_len - 1]); + is_absolute = uvwasi__is_absolute_path(path, path_len); normalized_path[0] = '\0'; ptr = normalized_path; @@ -156,6 +163,12 @@ uvwasi_errno_t uvwasi__normalize_path(const char* path, *ptr = '\0'; } + if (has_trailing_slash && !IS_SLASH(*(ptr - 1))) { + *ptr = '/'; + ptr++; + *ptr = '\0'; + } + return UVWASI_ESUCCESS; } @@ -171,7 +184,9 @@ static int uvwasi__is_path_sandboxed(const char* path, return path == strstr(path, fd_path) ? 1 : 0; /* Handle relative fds that normalized to '.' */ - if (fd_path_len == 1 && fd_path[0] == '.') { + if ((fd_path_len == 1 && fd_path[0] == '.') + || (fd_path_len == 2 && fd_path[0] == '.' && fd_path[1] == '/') + ) { /* If the fd's path is '.', then any path does not begin with '..' is OK. */ if ((path_len == 2 && path[0] == '.' && path[1] == '.') || (path_len > 2 && path[0] == '.' && path[1] == '.' && path[2] == '/')) { @@ -334,7 +349,8 @@ static uvwasi_errno_t uvwasi__resolve_path_to_host( char** resolved_path, uvwasi_size_t* resolved_len ) { - /* Return the normalized path, but resolved to the host's real path. */ + /* Return the normalized path, but resolved to the host's real path. + `path` must be a NULL-terminated string. */ char* res_path; char* stripped_path; int real_path_len; @@ -348,7 +364,11 @@ static uvwasi_errno_t uvwasi__resolve_path_to_host( fake_path_len = strlen(fd->normalized_path); /* If the fake path is '.' just ignore it. */ - if (fake_path_len == 1 && fd->normalized_path[0] == '.') { + if ((fake_path_len == 1 && fd->normalized_path[0] == '.') + || (fake_path_len == 2 + && fd->normalized_path[0] == '.' + && fd->normalized_path[1] == '/') + ) { fake_path_len = 0; } @@ -425,10 +445,20 @@ uvwasi_errno_t uvwasi__resolve_path(const uvwasi_t* uvwasi, normalized_parent = NULL; resolved_link_target = NULL; + if (uvwasi__is_absolute_path(input, input_len)) { + *resolved_path = NULL; + return UVWASI_ENOTCAPABLE; + } + start: normalized_path = NULL; err = UVWASI_ESUCCESS; + if (input_len != strnlen(input, input_len - 1) + 1) { + err = UVWASI_EINVAL; + goto exit; + } + if (1 == uvwasi__is_absolute_path(input, input_len)) { err = uvwasi__normalize_absolute_path(uvwasi, fd, diff --git a/deps/uvwasi/src/uvwasi.c b/deps/uvwasi/src/uvwasi.c index 948c1355c9..c33f5c4dee 100644 --- a/deps/uvwasi/src/uvwasi.c +++ b/deps/uvwasi/src/uvwasi.c @@ -395,6 +395,10 @@ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, const uvwasi_options_t* options) { if (options->preopen_socketc > 0) { uvwasi->loop = uvwasi__malloc(uvwasi, sizeof(uv_loop_t)); + + if (uvwasi->loop == NULL) + return UVWASI_ENOMEM; + r = uv_loop_init(uvwasi->loop); if (r != 0) { err = uvwasi__translate_uv_error(r); @@ -803,7 +807,7 @@ uvwasi_errno_t uvwasi_fd_close(uvwasi_t* uvwasi, uvwasi_fd_t fd) { uv_mutex_unlock(&wrap->mutex); if (err != UVWASI_ESUCCESS) { goto exit; - } + } } if (r != 0) { @@ -1392,6 +1396,7 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi, #if defined(UVWASI_FD_READDIR_SUPPORTED) /* TODO(cjihrig): Avoid opening and closing the directory on each call. */ struct uvwasi_fd_wrap_t* wrap; + uvwasi_dircookie_t cur_cookie; uvwasi_dirent_t dirent; uv_dirent_t dirents[UVWASI__READDIR_NUM_ENTRIES]; uv_dir_t* dir; @@ -1400,7 +1405,6 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi, size_t name_len; size_t available; size_t size_to_cp; - long tell; int i; int r; #endif /* defined(UVWASI_FD_READDIR_SUPPORTED) */ @@ -1440,8 +1444,22 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi, uv_fs_req_cleanup(&req); /* Seek to the proper location in the directory. */ - if (cookie != UVWASI_DIRCOOKIE_START) - seekdir(dir->dir, cookie); + cur_cookie = 0; + while (cur_cookie < cookie) { + r = uv_fs_readdir(NULL, &req, dir, NULL); + if (r < 0) { + err = uvwasi__translate_uv_error(r); + uv_fs_req_cleanup(&req); + goto exit; + } + + cur_cookie += (uvwasi_dircookie_t)r; + uv_fs_req_cleanup(&req); + + if (r == 0) { + break; + } + } /* Read the directory entries into the provided buffer. */ err = UVWASI_ESUCCESS; @@ -1456,15 +1474,9 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi, available = 0; for (i = 0; i < r; i++) { - tell = telldir(dir->dir); - if (tell < 0) { - err = uvwasi__translate_uv_error(uv_translate_sys_error(errno)); - uv_fs_req_cleanup(&req); - goto exit; - } - + cur_cookie++; name_len = strlen(dirents[i].name); - dirent.d_next = (uvwasi_dircookie_t) tell; + dirent.d_next = (uvwasi_dircookie_t) cur_cookie; /* TODO(cjihrig): libuv doesn't provide d_ino, and d_type is not supported on all platforms. Use stat()? */ dirent.d_ino = 0; @@ -2105,8 +2117,13 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, if (err != UVWASI_ESUCCESS) goto close_file_and_error_exit; - if ((o_flags & UVWASI_O_DIRECTORY) != 0 && - filetype != UVWASI_FILETYPE_DIRECTORY) { + if ( + (filetype != UVWASI_FILETYPE_DIRECTORY) + && ( + (o_flags & UVWASI_O_DIRECTORY) != 0 + || (resolved_path[strlen(resolved_path) - 1] == '/') + ) + ) { err = UVWASI_ENOTDIR; goto close_file_and_error_exit; } @@ -2361,6 +2378,7 @@ uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi, const char* new_path, uvwasi_size_t new_path_len) { char* truncated_old_path; + char* resolved_old_path; char* resolved_new_path; struct uvwasi_fd_wrap_t* wrap; uvwasi_errno_t err; @@ -2387,40 +2405,61 @@ uvwasi_errno_t uvwasi_path_symlink(uvwasi_t* uvwasi, if (err != UVWASI_ESUCCESS) return err; + resolved_old_path = NULL; + resolved_new_path = NULL; + truncated_old_path = NULL; + truncated_old_path = uvwasi__malloc(uvwasi, old_path_len + 1); if (truncated_old_path == NULL) { - uv_mutex_unlock(&wrap->mutex); - return UVWASI_ENOMEM; + err = UVWASI_ENOMEM; + goto exit; } memcpy(truncated_old_path, old_path, old_path_len); truncated_old_path[old_path_len] = '\0'; + if (old_path_len > 0 && old_path[0] == '/') { + err = UVWASI_EPERM; + goto exit; + } + + err = uvwasi__resolve_path(uvwasi, + wrap, + old_path, + old_path_len, + &resolved_old_path, + 0); + if (err != UVWASI_ESUCCESS) + goto exit; + err = uvwasi__resolve_path(uvwasi, wrap, new_path, new_path_len, &resolved_new_path, 0); - if (err != UVWASI_ESUCCESS) { - uv_mutex_unlock(&wrap->mutex); - uvwasi__free(uvwasi, truncated_old_path); - return err; - } + if (err != UVWASI_ESUCCESS) + goto exit; + /* Windows support may require setting the flags option. */ r = uv_fs_symlink(NULL, &req, truncated_old_path, resolved_new_path, 0, NULL); - uv_mutex_unlock(&wrap->mutex); - uvwasi__free(uvwasi, truncated_old_path); - uvwasi__free(uvwasi, resolved_new_path); uv_fs_req_cleanup(&req); - if (r != 0) - return uvwasi__translate_uv_error(r); + if (r != 0) { + err = uvwasi__translate_uv_error(r); + goto exit; + } - return UVWASI_ESUCCESS; + err = UVWASI_ESUCCESS; +exit: + uv_mutex_unlock(&wrap->mutex); + uvwasi__free(uvwasi, resolved_old_path); + uvwasi__free(uvwasi, resolved_new_path); + uvwasi__free(uvwasi, truncated_old_path); + + return err; } - uvwasi_errno_t uvwasi_path_unlink_file(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, @@ -2793,7 +2832,7 @@ uvwasi_errno_t uvwasi_sock_shutdown(uvwasi_t* uvwasi, uv_mutex_unlock(&wrap->mutex); - if (shutdown_data.status != 0) + if (shutdown_data.status != 0) return uvwasi__translate_uv_error(shutdown_data.status); return UVWASI_ESUCCESS; @@ -2832,6 +2871,10 @@ uvwasi_errno_t uvwasi_sock_accept(uvwasi_t* uvwasi, sock_loop = uv_handle_get_loop((uv_handle_t*) wrap->sock); uv_tcp_t* uv_connect_sock = (uv_tcp_t*) uvwasi__malloc(uvwasi, sizeof(uv_tcp_t)); + + if (uv_connect_sock == NULL) + return UVWASI_ENOMEM; + uv_tcp_init(sock_loop, uv_connect_sock); r = uv_accept((uv_stream_t*) wrap->sock, (uv_stream_t*) uv_connect_sock);