diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /third_party/rlbox_wasm2c_sandbox/src/wasm2c_rt_minwasi.c | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rlbox_wasm2c_sandbox/src/wasm2c_rt_minwasi.c')
-rw-r--r-- | third_party/rlbox_wasm2c_sandbox/src/wasm2c_rt_minwasi.c | 799 |
1 files changed, 799 insertions, 0 deletions
diff --git a/third_party/rlbox_wasm2c_sandbox/src/wasm2c_rt_minwasi.c b/third_party/rlbox_wasm2c_sandbox/src/wasm2c_rt_minwasi.c new file mode 100644 index 0000000000..9289cd75b1 --- /dev/null +++ b/third_party/rlbox_wasm2c_sandbox/src/wasm2c_rt_minwasi.c @@ -0,0 +1,799 @@ +/* A minimum wasi implementation supporting only stdin, stdout, stderr, argv + * (upto 1000 args), env (upto 1000 env), and clock functions. */ + +#include <assert.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#ifdef _WIN32 +# include <windows.h> +#endif + +#if defined(__APPLE__) && defined(__MACH__) +// Macs priors to OSX 10.12 don't have the clock functions. So we will use mac +// specific options +# include <mach/mach_time.h> +# include <sys/time.h> +#endif + +#include "wasm-rt.h" +#include "wasm2c_rt_minwasi.h" + +#ifndef WASM_RT_CORE_TYPES_DEFINED +# define WASM_RT_CORE_TYPES_DEFINED +typedef uint8_t u8; +typedef int8_t s8; +typedef uint16_t u16; +typedef int16_t s16; +typedef uint32_t u32; +typedef int32_t s32; +typedef uint64_t u64; +typedef int64_t s64; +typedef float f32; +typedef double f64; +#endif + +#ifndef UNLIKELY +# if defined(__GNUC__) +# define UNLIKELY(x) __builtin_expect(!!(x), 0) +# define LIKELY(x) __builtin_expect(!!(x), 1) +# else +# define UNLIKELY(x) (x) +# define LIKELY(x) (x) +# endif +#endif + +#define TRAP(x) wasm_rt_trap(WASM_RT_TRAP_##x) + +#define WASI_MEMACCESS(mem, a) ((void*)&(mem->data[a])) + +#define WASI_MEMCHECK_SIZE(mem, a, sz) \ + if (UNLIKELY(((u64)(a)) + sz > mem->size)) \ + TRAP(OOB) + +#define WASI_CHECK_COPY(mem, a, sz, src) \ + do { \ + WASI_MEMCHECK_SIZE(mem, a, sz); \ + memcpy(WASI_MEMACCESS(mem, a), src, sz); \ + } while (0) + +#define WASI_MEMCHECK(mem, a, t) WASI_MEMCHECK_SIZE(mem, a, sizeof(t)) + +#define DEFINE_WASI_LOAD(name, t1, t2, t3) \ + static inline t3 name(wasm_rt_memory_t* mem, u64 addr) \ + { \ + WASI_MEMCHECK(mem, addr, t1); \ + t1 result; \ + memcpy(&result, WASI_MEMACCESS(mem, addr), sizeof(t1)); \ + return (t3)(t2)result; \ + } + +#define DEFINE_WASI_STORE(name, t1, t2) \ + static inline void name(wasm_rt_memory_t* mem, u64 addr, t2 value) \ + { \ + WASI_MEMCHECK(mem, addr, t1); \ + t1 wrapped = (t1)value; \ + memcpy(WASI_MEMACCESS(mem, addr), &wrapped, sizeof(t1)); \ + } + +DEFINE_WASI_LOAD(wasm_i32_load, u32, u32, u32); +DEFINE_WASI_STORE(wasm_i32_store, u32, u32); +DEFINE_WASI_STORE(wasm_i64_store, u64, u64); + +static bool safe_add_u32(u32* ret, u32 a, u32 b) +{ + if (UINT32_MAX - a < b) { + *ret = 0; + return false; + } + *ret = a + b; + return true; +} + +// clang-format off + +////////////// Supported WASI APIs +// +// Clock operations +// ---------------- +// errno_t clock_res_get(void* ctx, clockid_t clock_id, timestamp_t* resolution); +// errno_t clock_time_get(void* ctx, clockid_t clock_id, timestamp_t precision, timestamp_t* time); +// +// File operations +// ---------------- +// Only the default descriptors of STDIN, STDOUT, STDERR are allowed by the +// runtime. +// +// errno_t fd_prestat_get(void* ctx, fd_t fd, prestat_t* buf); +// errno_t fd_read(void* ctx, fd_t fd, const iovec_t* iovs, size_t iovs_len, size_t* nread); +// errno_t fd_write(void* ctx, fd_t fd, const ciovec_t* iovs, size_t iovs_len, size_t* nwritten); + +////////////// Partially supported WASI APIs +// +// App environment operations +// -------------------------- +// These APIs work but return an empty buffer +// +// errno_t args_get(void* ctx, char** argv, char* argv_buf); +// errno_t args_sizes_get(void* ctx, size_t* argc, size_t* argv_buf_size); +// errno_t environ_get(void* ctx, char** environment, char* environ_buf); +// errno_t environ_sizes_get(void* ctx, size_t* environ_count, size_t* environ_buf_size); +// +// Proc exit operation +// ------------------- +// This is a no-op here in this runtime as the focus is on library +// sandboxing +// +// errno_t proc_exit(void* ctx, exitcode_t rval); + +////////////// Unsupported WASI APIs +// errno_t fd_advise(void* ctx, fd_t fd, filesize_t offset, filesize_t len, advice_t advice); +// errno_t fd_allocate(void* ctx, fd_t fd, filesize_t offset, filesize_t len); +// errno_t fd_close(void* ctx, fd_t fd); +// errno_t fd_datasync(void* ctx, fd_t fd); +// errno_t fd_fdstat_get(void* ctx, fd_t fd, fdstat_t* buf); +// errno_t fd_fdstat_set_flags(void* ctx, fd_t fd, fdflags_t flags); +// errno_t fd_fdstat_set_rights(void* ctx, fd_t fd, rights_t fs_rights_base, rights_t fs_rights_inheriting); +// errno_t fd_filestat_get(void* ctx, fd_t fd, filestat_t* buf); +// errno_t fd_filestat_set_size(void* ctx, fd_t fd, filesize_t st_size); +// errno_t fd_filestat_set_times(void* ctx, fd_t fd, timestamp_t st_atim, timestamp_t st_mtim, fstflags_t fst_flags); +// errno_t fd_pread(void* ctx, fd_t fd, const iovec_t* iovs, size_t iovs_len, filesize_t offset, size_t* nread); +// errno_t fd_prestat_dir_name(void* ctx, fd_t fd, char* path, size_t path_len); +// errno_t fd_pwrite(void* ctx, fd_t fd, const ciovec_t* iovs, size_t iovs_len, filesize_t offset, size_t* nwritten); +// errno_t fd_readdir(void* ctx, fd_t fd, void* buf, size_t buf_len, dircookie_t cookie, size_t* bufused); +// errno_t fd_renumber(void* ctx, fd_t from, fd_t to); +// errno_t fd_seek(void* ctx, fd_t fd, filedelta_t offset, whence_t whence, filesize_t* newoffset); +// errno_t fd_sync(void* ctx, fd_t fd); +// errno_t fd_tell(void* ctx, fd_t fd, filesize_t* offset); +// errno_t path_create_directory(void* ctx, fd_t fd, const char* path, size_t path_len); +// errno_t path_filestat_get(void* ctx, fd_t fd, lookupflags_t flags, const char* path, size_t path_len, filestat_t* buf); +// errno_t path_filestat_set_times(void* ctx, fd_t fd, lookupflags_t flags, const char* path, size_t path_len, timestamp_t st_atim, timestamp_t st_mtim, fstflags_t fst_flags); +// errno_t path_link(void* ctx, fd_t old_fd, lookupflags_t old_flags, const char* old_path, size_t old_path_len, fd_t new_fd, const char* new_path, size_t new_path_len); +// errno_t path_open(void* ctx, fd_t dirfd, lookupflags_t dirflags, const char* path, size_t path_len, oflags_t o_flags, rights_t fs_rights_base, rights_t fs_rights_inheriting, fdflags_t fs_flags, fd_t* fd); +// errno_t path_readlink(void* ctx, fd_t fd, const char* path, size_t path_len, char* buf, size_t buf_len, size_t* bufused); +// errno_t path_remove_directory(void* ctx, fd_t fd, const char* path, size_t path_len); +// errno_t path_rename(void* ctx, fd_t old_fd, const char* old_path, size_t old_path_len, fd_t new_fd, const char* new_path, size_t new_path_len); +// errno_t path_symlink(void* ctx, const char* old_path, size_t old_path_len, fd_t fd, const char* new_path, size_t new_path_len); +// errno_t path_unlink_file(void* ctx, fd_t fd, const char* path, size_t path_len); +// errno_t poll_oneoff(void* ctx, const subscription_t* in, event_t* out, size_t nsubscriptions, size_t* nevents); +// errno_t proc_raise(void* ctx, signal_t sig); +// errno_t random_get(void* ctx, void* buf, size_t buf_len); +// errno_t sched_yield(t* uvwasi); +// errno_t sock_accept(void* ctx, fd_t sock, flags_t fdflags, fd* fd); +// errno_t sock_recv(void* ctx, fd_t sock, const iovec_t* ri_data, size_t ri_data_len, riflags_t ri_flags, size_t* ro_datalen, roflags_t* ro_flags); +// errno_t sock_send(void* ctx, fd_t sock, const ciovec_t* si_data, size_t si_data_len, siflags_t si_flags, size_t* so_datalen); +// errno_t sock_shutdown(void* ctx, fd_t sock, sdflags_t how); + +// clang-format on + +// Success +#define WASI_SUCCESS 0 +// Bad file descriptor. +#define WASI_BADF_ERROR 8 +// Invalid argument +#define WASI_INVAL_ERROR 28 +// Operation not permitted. +#define WASI_PERM_ERROR 63 +// Syscall not implemented +#define WASI_NOSYS_ERROR 53 + +#define WASI_RET_ERR_ON_FAIL(exp) \ + if (!(exp)) { \ + return WASI_INVAL_ERROR; \ + } + +///////////////////////////////////////////////////////////// +// Clock operations +///////////////////////////////////////////////////////////// + +#if defined(_WIN32) + +typedef struct +{ + LARGE_INTEGER counts_per_sec; /* conversion factor */ +} wasi_win_clock_info_t; + +static wasi_win_clock_info_t g_wasi_win_clock_info; +static int g_os_data_initialized = 0; + +static bool os_clock_init() +{ + // From here: + // https://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows/38212960#38212960 + if (QueryPerformanceFrequency(&g_wasi_win_clock_info.counts_per_sec) == 0) { + return false; + } + g_os_data_initialized = 1; + return true; +} + +static bool os_clock_init_instance(void** clock_data_pointer) +{ + if (!g_os_data_initialized) { + os_clock_init(); + } + + wasi_win_clock_info_t* alloc = + (wasi_win_clock_info_t*)malloc(sizeof(wasi_win_clock_info_t)); + if (!alloc) { + return false; + } + memcpy(alloc, &g_wasi_win_clock_info, sizeof(wasi_win_clock_info_t)); + *clock_data_pointer = alloc; + return true; +} + +static void os_clock_cleanup_instance(void** clock_data_pointer) +{ + if (*clock_data_pointer == 0) { + free(*clock_data_pointer); + *clock_data_pointer = 0; + } +} + +static int os_clock_gettime(void* clock_data, + int clock_id, + struct timespec* out_struct) +{ + wasi_win_clock_info_t* alloc = (wasi_win_clock_info_t*)clock_data; + + LARGE_INTEGER count; + (void)clock_id; + + if (alloc->counts_per_sec.QuadPart <= 0 || + QueryPerformanceCounter(&count) == 0) { + return -1; + } + +# define BILLION 1000000000LL + out_struct->tv_sec = count.QuadPart / alloc->counts_per_sec.QuadPart; + out_struct->tv_nsec = + ((count.QuadPart % alloc->counts_per_sec.QuadPart) * BILLION) / + alloc->counts_per_sec.QuadPart; +# undef BILLION + + return 0; +} + +static int os_clock_getres(void* clock_data, + int clock_id, + struct timespec* out_struct) +{ + (void)clock_id; + out_struct->tv_sec = 0; + out_struct->tv_nsec = 1000; + return 0; +} + +#elif defined(__APPLE__) && defined(__MACH__) + +typedef struct +{ + mach_timebase_info_data_t timebase; /* numer = 0, denom = 0 */ + struct timespec inittime; /* nanoseconds since 1-Jan-1970 to init() */ + uint64_t initclock; /* ticks since boot to init() */ +} wasi_mac_clock_info_t; + +static wasi_mac_clock_info_t g_wasi_mac_clock_info; +static int g_os_data_initialized = 0; + +static bool os_clock_init() +{ + // From here: + // https://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x/21352348#21352348 + if (mach_timebase_info(&g_wasi_mac_clock_info.timebase) != 0) { + return false; + } + + // microseconds since 1 Jan 1970 + struct timeval micro; + if (gettimeofday(µ, NULL) != 0) { + return false; + } + + g_wasi_mac_clock_info.initclock = mach_absolute_time(); + + g_wasi_mac_clock_info.inittime.tv_sec = micro.tv_sec; + g_wasi_mac_clock_info.inittime.tv_nsec = micro.tv_usec * 1000; + + g_os_data_initialized = 1; + return true; +} + +static bool os_clock_init_instance(void** clock_data_pointer) +{ + if (!g_os_data_initialized) { + os_clock_init(); + } + + wasi_mac_clock_info_t* alloc = + (wasi_mac_clock_info_t*)malloc(sizeof(wasi_mac_clock_info_t)); + if (!alloc) { + return false; + } + memcpy(alloc, &g_wasi_mac_clock_info, sizeof(wasi_mac_clock_info_t)); + *clock_data_pointer = alloc; + return true; +} + +static void os_clock_cleanup_instance(void** clock_data_pointer) +{ + if (*clock_data_pointer == 0) { + free(*clock_data_pointer); + *clock_data_pointer = 0; + } +} + +static int os_clock_gettime(void* clock_data, + int clock_id, + struct timespec* out_struct) +{ + int ret = 0; + wasi_mac_clock_info_t* alloc = (wasi_mac_clock_info_t*)clock_data; + + // From here: + // https://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x/21352348#21352348 + + (void)clock_id; + // ticks since init + uint64_t clock = mach_absolute_time() - alloc->initclock; + // nanoseconds since init + uint64_t nano = clock * (uint64_t)(alloc->timebase.numer) / + (uint64_t)(alloc->timebase.denom); + *out_struct = alloc->inittime; + +# define BILLION 1000000000L + out_struct->tv_sec += nano / BILLION; + out_struct->tv_nsec += nano % BILLION; + // normalize + out_struct->tv_sec += out_struct->tv_nsec / BILLION; + out_struct->tv_nsec = out_struct->tv_nsec % BILLION; +# undef BILLION + return ret; +} + +static int os_clock_getres(void* clock_data, + int clock_id, + struct timespec* out_struct) +{ + int ret = 0; + (void)clock_id; + out_struct->tv_sec = 0; + out_struct->tv_nsec = 1; + return ret; +} + +#else + +static bool os_clock_init() +{ + return true; +} + +static bool os_clock_init_instance(void** clock_data_pointer) +{ + (void)clock_data_pointer; + return true; +} + +static void os_clock_cleanup_instance(void** clock_data_pointer) +{ + (void)clock_data_pointer; +} + +static int os_clock_gettime(void* clock_data, + int clock_id, + struct timespec* out_struct) +{ + (void)clock_data; + int ret = clock_gettime(clock_id, out_struct); + return ret; +} + +static int os_clock_getres(void* clock_data, + int clock_id, + struct timespec* out_struct) +{ + (void)clock_data; + int ret = clock_getres(clock_id, out_struct); + return ret; +} + +#endif + +#define WASM_CLOCK_REALTIME 0 +#define WASM_CLOCK_MONOTONIC 1 +#define WASM_CLOCK_PROCESS_CPUTIME 2 +#define WASM_CLOCK_THREAD_CPUTIME_ID 3 + +static int check_clock(u32 clock_id) +{ + return clock_id == WASM_CLOCK_REALTIME || clock_id == WASM_CLOCK_MONOTONIC || + clock_id == WASM_CLOCK_PROCESS_CPUTIME || + clock_id == WASM_CLOCK_THREAD_CPUTIME_ID; +} + +// out is a pointer to a u64 timestamp in nanoseconds +// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-timestamp-u64 +u32 w2c_wasi__snapshot__preview1_clock_time_get( + w2c_wasi__snapshot__preview1* wasi_data, + u32 clock_id, + u64 precision, + u32 out) +{ + if (!check_clock(clock_id)) { + return WASI_INVAL_ERROR; + } + + struct timespec out_struct; + int ret = os_clock_gettime(wasi_data->clock_data, clock_id, &out_struct); + u64 result = + ((u64)out_struct.tv_sec) * 1000 * 1000 * 1000 + ((u64)out_struct.tv_nsec); + wasm_i64_store(wasi_data->instance_memory, out, result); + return ret; +} + +u32 w2c_wasi__snapshot__preview1_clock_res_get( + w2c_wasi__snapshot__preview1* wasi_data, + u32 clock_id, + u32 out) +{ + if (!check_clock(clock_id)) { + return WASI_INVAL_ERROR; + } + + struct timespec out_struct; + int ret = os_clock_getres(wasi_data->clock_data, clock_id, &out_struct); + u64 result = + ((u64)out_struct.tv_sec) * 1000 * 1000 * 1000 + ((u64)out_struct.tv_nsec); + wasm_i64_store(wasi_data->instance_memory, out, result); + return ret; +} + +///////////////////////////////////////////////////////////// +////////// File operations +///////////////////////////////////////////////////////////// + +// Only allow stdin (0), stdout (1), stderr(2) + +#define WASM_STDIN 0 +#define WASM_STDOUT 1 +#define WASM_STDERR 2 + +u32 w2c_wasi__snapshot__preview1_fd_prestat_get( + w2c_wasi__snapshot__preview1* wasi_data, + u32 fd, + u32 prestat) +{ + if (fd == WASM_STDIN || fd == WASM_STDOUT || fd == WASM_STDERR) { + return WASI_PERM_ERROR; + } + return WASI_BADF_ERROR; +} + +u32 w2c_wasi__snapshot__preview1_fd_write( + w2c_wasi__snapshot__preview1* wasi_data, + u32 fd, + u32 iov, + u32 iovcnt, + u32 pnum) +{ + if (fd != WASM_STDOUT && fd != WASM_STDERR) { + return WASI_BADF_ERROR; + } + + u32 num = 0; + for (u32 i = 0; i < iovcnt; i++) { + u32 ptr = wasm_i32_load(wasi_data->instance_memory, iov + i * 8); + u32 len = wasm_i32_load(wasi_data->instance_memory, iov + i * 8 + 4); + + WASI_MEMCHECK_SIZE(wasi_data->instance_memory, ptr, len); + + size_t result = fwrite(WASI_MEMACCESS(wasi_data->instance_memory, ptr), + 1 /* size */, + len /* n */, + fd == WASM_STDOUT ? stdout : stderr); + + // Guaranteed by fwrite + assert(result <= len); + + WASI_RET_ERR_ON_FAIL(safe_add_u32(&num, num, (u32)result)); + + if (((u32)result) != len) { + wasm_i32_store(wasi_data->instance_memory, pnum, num); + return WASI_PERM_ERROR; + } + } + + wasm_i32_store(wasi_data->instance_memory, pnum, num); + return WASI_SUCCESS; +} + +u32 w2c_wasi__snapshot__preview1_fd_read( + w2c_wasi__snapshot__preview1* wasi_data, + u32 fd, + u32 iov, + u32 iovcnt, + u32 pnum) +{ + if (fd != WASM_STDIN) { + return WASI_BADF_ERROR; + } + + u32 num = 0; + for (u32 i = 0; i < iovcnt; i++) { + u32 ptr = wasm_i32_load(wasi_data->instance_memory, iov + i * 8); + u32 len = wasm_i32_load(wasi_data->instance_memory, iov + i * 8 + 4); + + WASI_MEMCHECK_SIZE(wasi_data->instance_memory, ptr, len); + size_t result = fread(WASI_MEMACCESS(wasi_data->instance_memory, ptr), + 1 /* size */, + len /* n */, + stdin); + + // Guaranteed by fwrite + assert(result <= len); + + WASI_RET_ERR_ON_FAIL(safe_add_u32(&num, num, (u32)result)); + + if (((u32)result) != len) { + break; // nothing more to read + } + } + wasm_i32_store(wasi_data->instance_memory, pnum, num); + return WASI_SUCCESS; +} + +///////////////////////////////////////////////////////////// +// App environment operations +///////////////////////////////////////////////////////////// + +#define ARGV_AND_ENV_LIMIT 1000 + +static u32 strings_sizes_get(wasm_rt_memory_t* instance_memory, + const char* name, + u32 p_str_count, + u32 p_str_buff_size, + u32 string_count, + const char** strings) +{ + u32 chosen_count = string_count; + if (chosen_count > ARGV_AND_ENV_LIMIT) { + chosen_count = ARGV_AND_ENV_LIMIT; + printf("Truncated %s args to %d\n", name, ARGV_AND_ENV_LIMIT); + } + + u32 curr_buf_size = 0; + for (u32 i = 0; i < chosen_count; i++) { + size_t original_len = strlen(strings[i]); + // len has to be at most u32 - 1 + WASI_RET_ERR_ON_FAIL(original_len < (size_t)UINT32_MAX); + + u32 len = (u32)original_len; + u32 len_plus_nullchar = len + 1; + + WASI_RET_ERR_ON_FAIL( + safe_add_u32(&curr_buf_size, curr_buf_size, len_plus_nullchar)); + } + + wasm_i32_store(instance_memory, p_str_count, chosen_count); + wasm_i32_store(instance_memory, p_str_buff_size, curr_buf_size); + return WASI_SUCCESS; +} + +static u32 strings_get(wasm_rt_memory_t* instance_memory, + const char* name, + u32 p_str_arr, + u32 p_str_buf, + u32 string_count, + const char** strings) +{ + u32 chosen_count = string_count; + if (chosen_count > ARGV_AND_ENV_LIMIT) { + chosen_count = ARGV_AND_ENV_LIMIT; + // Warning is already printed in get_size + } + + u32 curr_buf_loc = 0; + + for (u32 i = 0; i < chosen_count; i++) { + // Implement: p_str_arr[i] = p_str_buf[curr_buf_loc] + u32 target_argv_i_ref; + WASI_RET_ERR_ON_FAIL(safe_add_u32(&target_argv_i_ref, p_str_arr, i * 4)); + + u32 target_buf_curr_ref; + WASI_RET_ERR_ON_FAIL( + safe_add_u32(&target_buf_curr_ref, p_str_buf, curr_buf_loc)); + + wasm_i32_store(instance_memory, target_argv_i_ref, target_buf_curr_ref); + + // Implement: strcpy(p_str_buf[curr_buf_loc], strings[i]); + size_t original_len = strlen(strings[i]); + // len has to be at most u32 - 1 + WASI_RET_ERR_ON_FAIL(original_len < (size_t)UINT32_MAX); + + u32 len = (u32)original_len; + u32 len_plus_nullchar = len + 1; + + WASI_CHECK_COPY( + instance_memory, target_buf_curr_ref, len_plus_nullchar, strings[i]); + // Implement: curr_buf_loc += strlen(p_str_buf[curr_buf_loc]) + WASI_RET_ERR_ON_FAIL( + safe_add_u32(&curr_buf_loc, curr_buf_loc, len_plus_nullchar)); + } + return WASI_SUCCESS; +} + +u32 w2c_wasi__snapshot__preview1_args_sizes_get( + w2c_wasi__snapshot__preview1* wasi_data, + u32 p_argc, + u32 p_argv_buf_size) +{ + return strings_sizes_get(wasi_data->instance_memory, + "main", + p_argc, + p_argv_buf_size, + wasi_data->main_argc, + wasi_data->main_argv); +} + +u32 w2c_wasi__snapshot__preview1_args_get( + w2c_wasi__snapshot__preview1* wasi_data, + u32 p_argv, + u32 p_argv_buf) +{ + return strings_get(wasi_data->instance_memory, + "main", + p_argv, + p_argv_buf, + wasi_data->main_argc, + wasi_data->main_argv); +} + +u32 w2c_wasi__snapshot__preview1_environ_sizes_get( + w2c_wasi__snapshot__preview1* wasi_data, + u32 p_env_count, + u32 p_env_buf_size) +{ + return strings_sizes_get(wasi_data->instance_memory, + "env", + p_env_count, + p_env_buf_size, + wasi_data->env_count, + wasi_data->env); +} + +u32 w2c_wasi__snapshot__preview1_environ_get( + w2c_wasi__snapshot__preview1* wasi_data, + u32 p_env, + u32 p_env_buf) +{ + return strings_get(wasi_data->instance_memory, + "env", + p_env, + p_env_buf, + wasi_data->env_count, + wasi_data->env); +} + +///////////////////////////////////////////////////////////// +// Proc exit operation +///////////////////////////////////////////////////////////// + +void w2c_wasi__snapshot__preview1_proc_exit( + w2c_wasi__snapshot__preview1* wasi_data, + u32 x) +{ +#ifdef WASM2C_WASI_TRAP_ON_EXIT + TRAP(WASI); +#else + exit(x); +#endif +} + +///////////////////////////////////////////////////////////// +////////////// Unsupported WASI APIs +///////////////////////////////////////////////////////////// + +#define STUB_IMPORT_IMPL(ret, name, params) \ + ret name params { return WASI_NOSYS_ERROR; } + +// clang-format off + +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_advise, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u64 b, u64 c, u32 d)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_allocate, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u64 b, u64 c)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_close, + (w2c_wasi__snapshot__preview1* wasi_data, u32 fd)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_datasync, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_fdstat_get, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_fdstat_set_flags, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_fdstat_set_rights, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u64 b, u64 c)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_filestat_get, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_filestat_set_size, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u64 b)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_filestat_set_times, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u64 b, u64 c, u32 d)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_pread, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u64 d, u32 e)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_prestat_dir_name, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_pwrite, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u64 d, u32 e)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_readdir, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u64 d, u32 e)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_renumber, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_seek, + (w2c_wasi__snapshot__preview1* wasi_data, u32 fd, u64 offset, u32 whence, u32 new_offset)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_sync, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_fd_tell, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_create_directory, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_filestat_get, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d, u32 e)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_filestat_set_times, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d, u64 e, u64 f, u32 g)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_link, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d, u32 e, u32 f, u32 g)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_open, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d, u32 e, u64 f, u64 g, u32 h, u32 i)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_readlink, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d, u32 e, u32 f)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_remove_directory, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_rename, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d, u32 e, u32 f)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_symlink, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d, u32 e)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_path_unlink_file, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_poll_oneoff, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_proc_raise, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_random_get, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_sched_yield, + (w2c_wasi__snapshot__preview1* wasi_data)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_sock_accept, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_sock_recv, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d, u32 e, u32 f)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_sock_send, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b, u32 c, u32 d, u32 e)); +STUB_IMPORT_IMPL(u32, w2c_wasi__snapshot__preview1_sock_shutdown, + (w2c_wasi__snapshot__preview1* wasi_data, u32 a, u32 b)); + +// clang-format on + +///////////////////////////////////////////////////////////// +////////// Misc +///////////////////////////////////////////////////////////// + +bool minwasi_init() +{ + return os_clock_init(); +} + +bool minwasi_init_instance(w2c_wasi__snapshot__preview1* wasi_data) +{ + return os_clock_init_instance(&(wasi_data->clock_data)); +} + +void minwasi_cleanup_instance(w2c_wasi__snapshot__preview1* wasi_data) +{ + os_clock_cleanup_instance(&(wasi_data->clock_data)); +} |