From c01544de1f0ed033327861d65ddb5cb94ea1fb94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Mon, 4 May 2020 16:23:37 +0000 Subject: [PATCH] wasi: prevent syscalls before start PR-URL: https://github.com/nodejs/node/pull/33235 Reviewed-By: Colin Ihrig Reviewed-By: Gus Caplan Reviewed-By: Anna Henningsen --- doc/api/errors.md | 5 ++ src/node_errors.h | 2 + src/node_wasi.cc | 100 ++++++++++++++++------------- test/wasi/test-wasi-not-started.js | 40 ++++++++++++ 4 files changed, 102 insertions(+), 45 deletions(-) create mode 100644 test/wasi/test-wasi-not-started.js diff --git a/doc/api/errors.md b/doc/api/errors.md index 172eadf7686794..82f59190bbb9e9 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -2099,6 +2099,11 @@ meaning of the error depends on the specific function. The WASI instance has already started. + +### `ERR_WASI_NOT_STARTED` + +The WASI instance has not been started. + ### `ERR_WORKER_INIT_FAILED` diff --git a/src/node_errors.h b/src/node_errors.h index 3c57f4b8b02fee..f79b87afd2d525 100644 --- a/src/node_errors.h +++ b/src/node_errors.h @@ -54,6 +54,7 @@ void OnFatalError(const char* location, const char* message); V(ERR_TRANSFERRING_EXTERNALIZED_SHAREDARRAYBUFFER, TypeError) \ V(ERR_TLS_PSK_SET_IDENTIY_HINT_FAILED, Error) \ V(ERR_VM_MODULE_CACHED_DATA_REJECTED, Error) \ + V(ERR_WASI_NOT_STARTED, Error) \ V(ERR_WORKER_INIT_FAILED, Error) \ V(ERR_PROTO_ACCESS, Error) @@ -104,6 +105,7 @@ void OnFatalError(const char* location, const char* message); V(ERR_TRANSFERRING_EXTERNALIZED_SHAREDARRAYBUFFER, \ "Cannot serialize externalized SharedArrayBuffer") \ V(ERR_TLS_PSK_SET_IDENTIY_HINT_FAILED, "Failed to set PSK identity hint") \ + V(ERR_WASI_NOT_STARTED, "wasi.start() has not been called") \ V(ERR_WORKER_INIT_FAILED, "Worker initialization failure") \ V(ERR_PROTO_ACCESS, \ "Accessing Object.prototype.__proto__ has been " \ diff --git a/src/node_wasi.cc b/src/node_wasi.cc index 0330656b29e926..b057df9644c185 100644 --- a/src/node_wasi.cc +++ b/src/node_wasi.cc @@ -5,6 +5,7 @@ #include "node_mem-inl.h" #include "util-inl.h" #include "node.h" +#include "node_errors.h" #include "uv.h" #include "uvwasi.h" #include "node_wasi.h" @@ -23,6 +24,15 @@ inline void Debug(WASI* wasi, Args&&... args) { Debug(wasi->env(), DebugCategory::WASI, std::forward(args)...); } +#define ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(ptr, obj) \ + do { \ + ASSIGN_OR_RETURN_UNWRAP(ptr, obj); \ + if ((*(ptr))->memory_.IsEmpty()) { \ + THROW_ERR_WASI_NOT_STARTED(Environment::GetCurrent(args)); \ + return; \ + } \ + } while (0) + #define RETURN_IF_BAD_ARG_COUNT(args, expected) \ do { \ if ((args).Length() != (expected)) { \ @@ -250,7 +260,7 @@ void WASI::ArgsGet(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, argv_offset); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, argv_buf_offset); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "args_get(%d, %d)\n", argv_offset, argv_buf_offset); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, @@ -282,7 +292,7 @@ void WASI::ArgsSizesGet(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, argc_offset); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, argv_buf_offset); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + 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); @@ -310,7 +320,7 @@ void WASI::ClockResGet(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, clock_id); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, resolution_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + 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); @@ -336,7 +346,7 @@ void WASI::ClockTimeGet(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, clock_id); UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, precision); CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, time_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + 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); @@ -361,7 +371,7 @@ void WASI::EnvironGet(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, environ_offset); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, environ_buf_offset); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "environ_get(%d, %d)\n", environ_offset, environ_buf_offset); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, @@ -395,7 +405,7 @@ void WASI::EnvironSizesGet(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, envc_offset); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, env_buf_offset); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + 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); @@ -425,7 +435,7 @@ void WASI::FdAdvise(const FunctionCallbackInfo& args) { UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, offset); UNWRAP_BIGINT_OR_RETURN(args, args[2], Uint64, len); CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, advice); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_advise(%d, %d, %d, %d)\n", fd, offset, len, advice); uvwasi_errno_t err = uvwasi_fd_advise(&wasi->uvw_, fd, offset, len, advice); args.GetReturnValue().Set(err); @@ -441,7 +451,7 @@ void WASI::FdAllocate(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, offset); UNWRAP_BIGINT_OR_RETURN(args, args[2], Uint64, len); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_allocate(%d, %d, %d)\n", fd, offset, len); uvwasi_errno_t err = uvwasi_fd_allocate(&wasi->uvw_, fd, offset, len); args.GetReturnValue().Set(err); @@ -453,7 +463,7 @@ void WASI::FdClose(const FunctionCallbackInfo& args) { uint32_t fd; RETURN_IF_BAD_ARG_COUNT(args, 1); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_close(%d)\n", fd); uvwasi_errno_t err = uvwasi_fd_close(&wasi->uvw_, fd); args.GetReturnValue().Set(err); @@ -465,7 +475,7 @@ void WASI::FdDatasync(const FunctionCallbackInfo& args) { uint32_t fd; RETURN_IF_BAD_ARG_COUNT(args, 1); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_datasync(%d)\n", fd); uvwasi_errno_t err = uvwasi_fd_datasync(&wasi->uvw_, fd); args.GetReturnValue().Set(err); @@ -481,7 +491,7 @@ void WASI::FdFdstatGet(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, buf); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + 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); @@ -506,7 +516,7 @@ void WASI::FdFdstatSetFlags(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, flags); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_fdstat_set_flags(%d, %d)\n", fd, flags); uvwasi_errno_t err = uvwasi_fd_fdstat_set_flags(&wasi->uvw_, fd, flags); args.GetReturnValue().Set(err); @@ -522,7 +532,7 @@ void WASI::FdFdstatSetRights(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, fs_rights_base); UNWRAP_BIGINT_OR_RETURN(args, args[2], Uint64, fs_rights_inheriting); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_fdstat_set_rights(%d, %d, %d)\n", fd, @@ -545,7 +555,7 @@ void WASI::FdFilestatGet(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, buf); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + 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); @@ -574,7 +584,7 @@ void WASI::FdFilestatSetSize(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, st_size); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_filestat_set_size(%d, %d)\n", fd, st_size); uvwasi_errno_t err = uvwasi_fd_filestat_set_size(&wasi->uvw_, fd, st_size); args.GetReturnValue().Set(err); @@ -592,7 +602,7 @@ void WASI::FdFilestatSetTimes(const FunctionCallbackInfo& args) { UNWRAP_BIGINT_OR_RETURN(args, args[1], Uint64, st_atim); UNWRAP_BIGINT_OR_RETURN(args, args[2], Uint64, st_mtim); CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, fst_flags); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_filestat_set_times(%d, %d, %d, %d)\n", fd, @@ -623,7 +633,7 @@ void WASI::FdPread(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, iovs_len); UNWRAP_BIGINT_OR_RETURN(args, args[3], Uint64, offset); CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, nread_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "uvwasi_fd_pread(%d, %d, %d, %d, %d)\n", fd, @@ -683,7 +693,7 @@ void WASI::FdPrestatGet(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, buf); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + 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); @@ -710,7 +720,7 @@ void WASI::FdPrestatDirName(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, path_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_len); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_prestat_dir_name(%d, %d, %d)\n", fd, path_ptr, path_len); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len); @@ -737,7 +747,7 @@ void WASI::FdPwrite(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, iovs_len); UNWRAP_BIGINT_OR_RETURN(args, args[3], Uint64, offset); CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, nwritten_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "uvwasi_fd_pwrite(%d, %d, %d, %d, %d)\n", fd, @@ -801,7 +811,7 @@ void WASI::FdRead(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, iovs_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, iovs_len); CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, nread_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + 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); @@ -860,7 +870,7 @@ void WASI::FdReaddir(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, buf_len); UNWRAP_BIGINT_OR_RETURN(args, args[3], Uint64, cookie); CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, bufused_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "uvwasi_fd_readdir(%d, %d, %d, %d, %d)\n", fd, @@ -892,7 +902,7 @@ void WASI::FdRenumber(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, from); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, to); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_renumber(%d, %d)\n", from, to); uvwasi_errno_t err = uvwasi_fd_renumber(&wasi->uvw_, from, to); args.GetReturnValue().Set(err); @@ -912,7 +922,7 @@ void WASI::FdSeek(const FunctionCallbackInfo& args) { UNWRAP_BIGINT_OR_RETURN(args, args[1], Int64, offset); CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, whence); CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, newoffset_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + 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); @@ -934,7 +944,7 @@ void WASI::FdSync(const FunctionCallbackInfo& args) { uint32_t fd; RETURN_IF_BAD_ARG_COUNT(args, 1); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_sync(%d)\n", fd); uvwasi_errno_t err = uvwasi_fd_sync(&wasi->uvw_, fd); args.GetReturnValue().Set(err); @@ -950,7 +960,7 @@ void WASI::FdTell(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, offset_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + 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); @@ -977,7 +987,7 @@ void WASI::FdWrite(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, iovs_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, iovs_len); CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, nwritten_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "fd_write(%d, %d, %d, %d)\n", fd, @@ -1037,7 +1047,7 @@ void WASI::PathCreateDirectory(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, path_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_len); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_create_directory(%d, %d, %d)\n", fd, path_ptr, path_len); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len); @@ -1064,7 +1074,7 @@ void WASI::PathFilestatGet(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, path_len); CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, buf_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_filestat_get(%d, %d, %d)\n", fd, @@ -1114,7 +1124,7 @@ void WASI::PathFilestatSetTimes(const FunctionCallbackInfo& args) { UNWRAP_BIGINT_OR_RETURN(args, args[4], Uint64, st_atim); UNWRAP_BIGINT_OR_RETURN(args, args[5], Uint64, st_mtim); CHECK_TO_TYPE_OR_RETURN(args, args[6], Uint32, fst_flags); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_filestat_set_times(%d, %d, %d, %d, %d, %d, %d)\n", fd, @@ -1157,7 +1167,7 @@ void WASI::PathLink(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, new_fd); CHECK_TO_TYPE_OR_RETURN(args, args[5], Uint32, new_path_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[6], Uint32, new_path_len); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_link(%d, %d, %d, %d, %d, %d, %d)\n", old_fd, @@ -1205,7 +1215,7 @@ void WASI::PathOpen(const FunctionCallbackInfo& args) { UNWRAP_BIGINT_OR_RETURN(args, args[6], Uint64, fs_rights_inheriting); CHECK_TO_TYPE_OR_RETURN(args, args[7], Uint32, fs_flags); CHECK_TO_TYPE_OR_RETURN(args, args[8], Uint32, fd_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_open(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", dirfd, @@ -1255,7 +1265,7 @@ void WASI::PathReadlink(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, buf_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, buf_len); CHECK_TO_TYPE_OR_RETURN(args, args[5], Uint32, bufused_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_readlink(%d, %d, %d, %d, %d, %d)\n", fd, @@ -1294,7 +1304,7 @@ void WASI::PathRemoveDirectory(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, path_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_len); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_remove_directory(%d, %d, %d)\n", fd, path_ptr, path_len); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len); @@ -1323,7 +1333,7 @@ void WASI::PathRename(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, new_fd); CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, new_path_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[5], Uint32, new_path_len); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_rename(%d, %d, %d, %d, %d, %d)\n", old_fd, @@ -1361,7 +1371,7 @@ void WASI::PathSymlink(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, new_path_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, new_path_len); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_symlink(%d, %d, %d, %d, %d)\n", old_path_ptr, @@ -1393,7 +1403,7 @@ void WASI::PathUnlinkFile(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, fd); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, path_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, path_len); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "path_unlink_file(%d, %d, %d)\n", fd, path_ptr, path_len); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, path_ptr, path_len); @@ -1418,7 +1428,7 @@ void WASI::PollOneoff(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, out_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, nsubscriptions); CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, nevents_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "poll_oneoff(%d, %d, %d, %d)\n", in_ptr, @@ -1500,7 +1510,7 @@ void WASI::ProcExit(const FunctionCallbackInfo& args) { uint32_t code; RETURN_IF_BAD_ARG_COUNT(args, 1); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, code); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "proc_exit(%d)\n", code); args.GetReturnValue().Set(uvwasi_proc_exit(&wasi->uvw_, code)); } @@ -1511,7 +1521,7 @@ void WASI::ProcRaise(const FunctionCallbackInfo& args) { uint32_t sig; RETURN_IF_BAD_ARG_COUNT(args, 1); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, sig); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "proc_raise(%d)\n", sig); uvwasi_errno_t err = uvwasi_proc_raise(&wasi->uvw_, sig); args.GetReturnValue().Set(err); @@ -1527,7 +1537,7 @@ void WASI::RandomGet(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, buf_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, buf_len); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "random_get(%d, %d)\n", buf_ptr, buf_len); GET_BACKING_STORE_OR_RETURN(wasi, args, &memory, &mem_size); CHECK_BOUNDS_OR_RETURN(args, mem_size, buf_ptr, buf_len); @@ -1541,7 +1551,7 @@ void WASI::RandomGet(const FunctionCallbackInfo& args) { void WASI::SchedYield(const FunctionCallbackInfo& args) { WASI* wasi; RETURN_IF_BAD_ARG_COUNT(args, 0); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "sched_yield()\n"); uvwasi_errno_t err = uvwasi_sched_yield(&wasi->uvw_); args.GetReturnValue().Set(err); @@ -1565,7 +1575,7 @@ void WASI::SockRecv(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, ri_flags); CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, ro_datalen_ptr); CHECK_TO_TYPE_OR_RETURN(args, args[5], Uint32, ro_flags_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "sock_recv(%d, %d, %d, %d, %d, %d)\n", sock, @@ -1637,7 +1647,7 @@ void WASI::SockSend(const FunctionCallbackInfo& args) { CHECK_TO_TYPE_OR_RETURN(args, args[2], Uint32, si_data_len); CHECK_TO_TYPE_OR_RETURN(args, args[3], Uint32, si_flags); CHECK_TO_TYPE_OR_RETURN(args, args[4], Uint32, so_datalen_ptr); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "sock_send(%d, %d, %d, %d, %d)\n", sock, @@ -1695,7 +1705,7 @@ void WASI::SockShutdown(const FunctionCallbackInfo& args) { RETURN_IF_BAD_ARG_COUNT(args, 2); CHECK_TO_TYPE_OR_RETURN(args, args[0], Uint32, sock); CHECK_TO_TYPE_OR_RETURN(args, args[1], Uint32, how); - ASSIGN_OR_RETURN_UNWRAP(&wasi, args.This()); + ASSIGN_INITIALIZED_OR_RETURN_UNWRAP(&wasi, args.This()); Debug(wasi, "sock_shutdown(%d, %d)\n", sock, how); uvwasi_errno_t err = uvwasi_sock_shutdown(&wasi->uvw_, sock, how); args.GetReturnValue().Set(err); diff --git a/test/wasi/test-wasi-not-started.js b/test/wasi/test-wasi-not-started.js new file mode 100644 index 00000000000000..ad13e6d711802b --- /dev/null +++ b/test/wasi/test-wasi-not-started.js @@ -0,0 +1,40 @@ +'use strict'; +require('../common'); + +if (process.argv[2] === 'wasi-child') { + const assert = require('assert'); + const fs = require('fs'); + const path = require('path'); + + const { WASI } = require('wasi'); + const wasi = new WASI({ + args: ['foo', '-bar', '--baz=value'] + }); + const importObject = { wasi_snapshot_preview1: wasi.wasiImport }; + + const modulePath = path.join(__dirname, 'wasm', 'main_args.wasm'); + const buffer = fs.readFileSync(modulePath); + + assert.rejects(async () => { + const { instance } = await WebAssembly.instantiate(buffer, importObject); + instance.exports._start(); + }, { + name: 'Error', + code: 'ERR_WASI_NOT_STARTED', + message: 'wasi.start() has not been called' + }); +} else { + const assert = require('assert'); + const cp = require('child_process'); + + const child = cp.spawnSync(process.execPath, [ + '--experimental-wasi-unstable-preview1', + '--experimental-wasm-bigint', + __filename, + 'wasi-child' + ], { + env: { ...process.env, NODE_DEBUG_NATIVE: 'wasi' } + }); + assert.strictEqual(child.signal, null); + assert.strictEqual(child.status, 0); +}