Repository: nodejs/node
Pull request: deps: update uvwasi to 0.0.23

This is an automated update of uvwasi to 0.0.23.

Changed files:
filename: deps/uvwasi/include/uvwasi.h
patch: @@ -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,62 +258,76 @@ 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,
                                     uvwasi_size_t path_len,
                                     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,
                                   uvwasi_size_t old_path_len,
                                   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,
                                 uvwasi_size_t ri_data_len,
                                 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);

filename: deps/uvwasi/include/wasi_serdes.h
patch: @@ -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,20 +129,24 @@ 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,
                                            uvwasi_iovec_t* iovs,
                                            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,

filename: deps/uvwasi/include/wasi_types.h
patch: @@ -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__ */

filename: deps/uvwasi/src/path_resolver.c
patch: @@ -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,

filename: deps/uvwasi/src/uvwasi.c
patch: @@ -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_fs_req_cleanup(&req);
+  if (r != 0) {
+    err = uvwasi__translate_uv_error(r);
+    goto exit;
+  }
+
+  err = UVWASI_ESUCCESS;
+exit:
   uv_mutex_unlock(&wrap->mutex);
-  uvwasi__free(uvwasi, truncated_old_path);
+  uvwasi__free(uvwasi, resolved_old_path);
   uvwasi__free(uvwasi, resolved_new_path);
-  uv_fs_req_cleanup(&req);
-  if (r != 0)
-    return uvwasi__translate_uv_error(r);
+  uvwasi__free(uvwasi, truncated_old_path);
 
-  return UVWASI_ESUCCESS;
+  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);