diff --git a/product-mini/platforms/common/libc_wasi.c b/product-mini/platforms/common/libc_wasi.c new file mode 100644 index 00000000..0fd2443c --- /dev/null +++ b/product-mini/platforms/common/libc_wasi.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +#include "bh_platform.h" +#include "wasm_export.h" + +typedef struct { + const char *dir_list[8]; + uint32 dir_list_size; + const char *env_list[8]; + uint32 env_list_size; + const char *addr_pool[8]; + uint32 addr_pool_size; + const char *ns_lookup_pool[8]; + uint32 ns_lookup_pool_size; +} libc_wasi_parse_context_t; + +typedef enum { + LIBC_WASI_PARSE_RESULT_OK = 0, + LIBC_WASI_PARSE_RESULT_NEED_HELP, + LIBC_WASI_PARSE_RESULT_BAD_PARAM +} libc_wasi_parse_result_t; + +static void +libc_wasi_print_help() +{ + printf(" --env= Pass wasi environment variables with " + "\"key=value\"\n"); + printf(" to the program, for example:\n"); + printf(" --env=\"key1=value1\" " + "--env=\"key2=value2\"\n"); + printf(" --dir= Grant wasi access to the given host " + "directories\n"); + printf(" to the program, for example:\n"); + printf(" --dir= --dir=\n"); + printf(" --addr-pool= Grant wasi access to the given network " + "addresses in\n"); + printf(" CIRD notation to the program, seperated " + "with ',',\n"); + printf(" for example:\n"); + printf(" --addr-pool=1.2.3.4/15,2.3.4.5/16\n"); + printf(" --allow-resolve= Allow the lookup of the specific domain " + "name or domain\n"); + printf(" name suffixes using a wildcard, for " + "example:\n"); + printf(" --allow-resolve=example.com # allow the " + "lookup of the specific domain\n"); + printf(" --allow-resolve=*.example.com # allow " + "the lookup of all subdomains\n"); + printf(" --allow-resolve=* # allow any lookup\n"); +} + +static bool +validate_env_str(char *env) +{ + char *p = env; + int key_len = 0; + + while (*p != '\0' && *p != '=') { + key_len++; + p++; + } + + if (*p != '=' || key_len == 0) + return false; + + return true; +} + +libc_wasi_parse_result_t +libc_wasi_parse(char *arg, libc_wasi_parse_context_t *ctx) +{ + if (!strncmp(arg, "--dir=", 6)) { + if (arg[6] == '\0') + return LIBC_WASI_PARSE_RESULT_NEED_HELP; + if (ctx->dir_list_size >= sizeof(ctx->dir_list) / sizeof(char *)) { + printf("Only allow max dir number %d\n", + (int)(sizeof(ctx->dir_list) / sizeof(char *))); + return LIBC_WASI_PARSE_RESULT_BAD_PARAM; + } + ctx->dir_list[ctx->dir_list_size++] = arg + 6; + } + else if (!strncmp(arg, "--env=", 6)) { + char *tmp_env; + + if (arg[6] == '\0') + return LIBC_WASI_PARSE_RESULT_NEED_HELP; + if (ctx->env_list_size >= sizeof(ctx->env_list) / sizeof(char *)) { + printf("Only allow max env number %d\n", + (int)(sizeof(ctx->env_list) / sizeof(char *))); + return LIBC_WASI_PARSE_RESULT_BAD_PARAM; + } + tmp_env = arg + 6; + if (validate_env_str(tmp_env)) + ctx->env_list[ctx->env_list_size++] = tmp_env; + else { + printf("Wasm parse env string failed: expect \"key=value\", " + "got \"%s\"\n", + tmp_env); + return LIBC_WASI_PARSE_RESULT_NEED_HELP; + } + } + /* TODO: parse the configuration file via --addr-pool-file */ + else if (!strncmp(arg, "--addr-pool=", strlen("--addr-pool="))) { + /* like: --addr-pool=100.200.244.255/30 */ + char *token = NULL; + + if ('\0' == arg[12]) + return LIBC_WASI_PARSE_RESULT_NEED_HELP; + + token = strtok(arg + strlen("--addr-pool="), ","); + while (token) { + if (ctx->addr_pool_size + >= sizeof(ctx->addr_pool) / sizeof(char *)) { + printf("Only allow max address number %d\n", + (int)(sizeof(ctx->addr_pool) / sizeof(char *))); + return LIBC_WASI_PARSE_RESULT_BAD_PARAM; + } + + ctx->addr_pool[ctx->addr_pool_size++] = token; + token = strtok(NULL, ";"); + } + } + else if (!strncmp(arg, "--allow-resolve=", 16)) { + if (arg[16] == '\0') + return LIBC_WASI_PARSE_RESULT_NEED_HELP; + if (ctx->ns_lookup_pool_size + >= sizeof(ctx->ns_lookup_pool) / sizeof(ctx->ns_lookup_pool[0])) { + printf("Only allow max ns lookup number %d\n", + (int)(sizeof(ctx->ns_lookup_pool) + / sizeof(ctx->ns_lookup_pool[0]))); + return LIBC_WASI_PARSE_RESULT_BAD_PARAM; + } + ctx->ns_lookup_pool[ctx->ns_lookup_pool_size++] = arg + 16; + } + return LIBC_WASI_PARSE_RESULT_OK; +} + +void +libc_wasi_init(wasm_module_t wasm_module, int argc, char **argv, + libc_wasi_parse_context_t *ctx) +{ + wasm_runtime_set_wasi_args(wasm_module, ctx->dir_list, ctx->dir_list_size, + NULL, 0, ctx->env_list, ctx->env_list_size, argv, + argc); + + wasm_runtime_set_wasi_addr_pool(wasm_module, ctx->addr_pool, + ctx->addr_pool_size); + wasm_runtime_set_wasi_ns_lookup_pool(wasm_module, ctx->ns_lookup_pool, + ctx->ns_lookup_pool_size); +} diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index 45214243..ea4ca7bd 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -14,6 +14,10 @@ #include "bh_read_file.h" #include "wasm_export.h" +#if WASM_ENABLE_LIBC_WASI != 0 +#include "../common/libc_wasi.c" +#endif + #if BH_HAS_DLFCN #include #endif @@ -69,21 +73,7 @@ print_help() printf(" --disable-bounds-checks Disable bounds checks for memory accesses\n"); #endif #if WASM_ENABLE_LIBC_WASI != 0 - printf(" --env= Pass wasi environment variables with \"key=value\"\n"); - printf(" to the program, for example:\n"); - printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); - printf(" --dir= Grant wasi access to the given host directories\n"); - printf(" to the program, for example:\n"); - printf(" --dir= --dir=\n"); - printf(" --addr-pool= Grant wasi access to the given network addresses in\n"); - printf(" CIRD notation to the program, seperated with ',',\n"); - printf(" for example:\n"); - printf(" --addr-pool=1.2.3.4/15,2.3.4.5/16\n"); - printf(" --allow-resolve= Allow the lookup of the specific domain name or domain\n"); - printf(" name suffixes using a wildcard, for example:\n"); - printf(" --allow-resolve=example.com # allow the lookup of the specific domain\n"); - printf(" --allow-resolve=*.example.com # allow the lookup of all subdomains\n"); - printf(" --allow-resolve=* # allow any lookup\n"); + libc_wasi_print_help(); #endif #if BH_HAS_DLFCN printf(" --native-lib= Register native libraries to the WASM module, which\n"); @@ -262,25 +252,6 @@ resolve_segue_flags(char *str_flags) } #endif /* end of WASM_ENABLE_JIT != 0 */ -#if WASM_ENABLE_LIBC_WASI != 0 -static bool -validate_env_str(char *env) -{ - char *p = env; - int key_len = 0; - - while (*p != '\0' && *p != '=') { - key_len++; - p++; - } - - if (*p != '=' || key_len == 0) - return false; - - return true; -} -#endif - #if BH_HAS_DLFCN typedef uint32 (*get_native_lib_func)(char **p_module_name, NativeSymbol **p_native_symbols); @@ -493,14 +464,7 @@ main(int argc, char *argv[]) bool disable_bounds_checks = false; #endif #if WASM_ENABLE_LIBC_WASI != 0 - const char *dir_list[8] = { NULL }; - uint32 dir_list_size = 0; - const char *env_list[8] = { NULL }; - uint32 env_list_size = 0; - const char *addr_pool[8] = { NULL }; - uint32 addr_pool_size = 0; - const char *ns_lookup_pool[8] = { NULL }; - uint32 ns_lookup_pool_size = 0; + libc_wasi_parse_context_t wasi_parse_ctx; #endif #if BH_HAS_DLFCN const char *native_lib_list[8] = { NULL }; @@ -516,6 +480,10 @@ main(int argc, char *argv[]) const char *gen_prof_file = NULL; #endif +#if WASM_ENABLE_LIBC_WASI != 0 + memset(&wasi_parse_ctx, 0, sizeof(wasi_parse_ctx)); +#endif + /* Process options. */ for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) { if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--function")) { @@ -619,70 +587,6 @@ main(int argc, char *argv[]) return print_help(); } #endif /* end of WASM_ENABLE_JIT != 0 */ -#if WASM_ENABLE_LIBC_WASI != 0 - else if (!strncmp(argv[0], "--dir=", 6)) { - if (argv[0][6] == '\0') - return print_help(); - if (dir_list_size >= sizeof(dir_list) / sizeof(char *)) { - printf("Only allow max dir number %d\n", - (int)(sizeof(dir_list) / sizeof(char *))); - return 1; - } - dir_list[dir_list_size++] = argv[0] + 6; - } - else if (!strncmp(argv[0], "--env=", 6)) { - char *tmp_env; - - if (argv[0][6] == '\0') - return print_help(); - if (env_list_size >= sizeof(env_list) / sizeof(char *)) { - printf("Only allow max env number %d\n", - (int)(sizeof(env_list) / sizeof(char *))); - return 1; - } - tmp_env = argv[0] + 6; - if (validate_env_str(tmp_env)) - env_list[env_list_size++] = tmp_env; - else { - printf("Wasm parse env string failed: expect \"key=value\", " - "got \"%s\"\n", - tmp_env); - return print_help(); - } - } - /* TODO: parse the configuration file via --addr-pool-file */ - else if (!strncmp(argv[0], "--addr-pool=", strlen("--addr-pool="))) { - /* like: --addr-pool=100.200.244.255/30 */ - char *token = NULL; - - if ('\0' == argv[0][12]) - return print_help(); - - token = strtok(argv[0] + strlen("--addr-pool="), ","); - while (token) { - if (addr_pool_size >= sizeof(addr_pool) / sizeof(char *)) { - printf("Only allow max address number %d\n", - (int)(sizeof(addr_pool) / sizeof(char *))); - return 1; - } - - addr_pool[addr_pool_size++] = token; - token = strtok(NULL, ";"); - } - } - else if (!strncmp(argv[0], "--allow-resolve=", 16)) { - if (argv[0][16] == '\0') - return print_help(); - if (ns_lookup_pool_size - >= sizeof(ns_lookup_pool) / sizeof(ns_lookup_pool[0])) { - printf( - "Only allow max ns lookup number %d\n", - (int)(sizeof(ns_lookup_pool) / sizeof(ns_lookup_pool[0]))); - return 1; - } - ns_lookup_pool[ns_lookup_pool_size++] = argv[0] + 16; - } -#endif /* WASM_ENABLE_LIBC_WASI */ #if BH_HAS_DLFCN else if (!strncmp(argv[0], "--native-lib=", 13)) { if (argv[0][13] == '\0') @@ -738,8 +642,22 @@ main(int argc, char *argv[]) patch); return 0; } - else + else { +#if WASM_ENABLE_LIBC_WASI != 0 + libc_wasi_parse_result_t result = + libc_wasi_parse(argv[0], &wasi_parse_ctx); + switch (result) { + case LIBC_WASI_PARSE_RESULT_OK: + continue; + case LIBC_WASI_PARSE_RESULT_NEED_HELP: + return print_help(); + case LIBC_WASI_PARSE_RESULT_BAD_PARAM: + return 1; + } +#else return print_help(); +#endif + } } if (argc == 0) @@ -832,12 +750,7 @@ main(int argc, char *argv[]) } #if WASM_ENABLE_LIBC_WASI != 0 - wasm_runtime_set_wasi_args(wasm_module, dir_list, dir_list_size, NULL, 0, - env_list, env_list_size, argv, argc); - - wasm_runtime_set_wasi_addr_pool(wasm_module, addr_pool, addr_pool_size); - wasm_runtime_set_wasi_ns_lookup_pool(wasm_module, ns_lookup_pool, - ns_lookup_pool_size); + libc_wasi_init(wasm_module, argc, argv, &wasi_parse_ctx); #endif /* instantiate the module */ diff --git a/product-mini/platforms/windows/main.c b/product-mini/platforms/windows/main.c index 0f7fa0b7..ec0647f6 100644 --- a/product-mini/platforms/windows/main.c +++ b/product-mini/platforms/windows/main.c @@ -10,6 +10,10 @@ #include "bh_read_file.h" #include "wasm_export.h" +#if WASM_ENABLE_LIBC_WASI != 0 +#include "../common/libc_wasi.c" +#endif + static int app_argc; static char **app_argv; @@ -48,12 +52,7 @@ print_help() printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" " that runs commands in the form of `FUNC ARG...`\n"); #if WASM_ENABLE_LIBC_WASI != 0 - printf(" --env= Pass wasi environment variables with \"key=value\"\n"); - printf(" to the program, for example:\n"); - printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); - printf(" --dir= Grant wasi access to the given host directories\n"); - printf(" to the program, for example:\n"); - printf(" --dir= --dir=\n"); + libc_wasi_print_help(); #endif #if WASM_ENABLE_MULTI_MODULE != 0 printf(" --module-path= Indicate a module search path. default is current\n" @@ -172,25 +171,6 @@ app_instance_repl(wasm_module_inst_t module_inst) return NULL; } -#if WASM_ENABLE_LIBC_WASI != 0 -static bool -validate_env_str(char *env) -{ - char *p = env; - int key_len = 0; - - while (*p != '\0' && *p != '=') { - key_len++; - p++; - } - - if (*p != '=' || key_len == 0) - return false; - - return true; -} -#endif - #if WASM_ENABLE_GLOBAL_HEAP_POOL != 0 static char global_heap_buf[WASM_GLOBAL_HEAP_SIZE] = { 0 }; #endif @@ -265,16 +245,17 @@ main(int argc, char *argv[]) bool is_repl_mode = false; bool is_xip_file = false; #if WASM_ENABLE_LIBC_WASI != 0 - const char *dir_list[8] = { NULL }; - uint32 dir_list_size = 0; - const char *env_list[8] = { NULL }; - uint32 env_list_size = 0; + libc_wasi_parse_context_t wasi_parse_ctx; #endif #if WASM_ENABLE_DEBUG_INTERP != 0 char *ip_addr = NULL; int instance_port = 0; #endif +#if WASM_ENABLE_LIBC_WASI != 0 + memset(&wasi_parse_ctx, 0, sizeof(wasi_parse_ctx)); +#endif + /* Process options. */ for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) { if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--function")) { @@ -356,38 +337,6 @@ main(int argc, char *argv[]) } } #endif -#if WASM_ENABLE_LIBC_WASI != 0 - else if (!strncmp(argv[0], "--dir=", 6)) { - if (argv[0][6] == '\0') - return print_help(); - if (dir_list_size >= sizeof(dir_list) / sizeof(char *)) { - printf("Only allow max dir number %d\n", - (int)(sizeof(dir_list) / sizeof(char *))); - return 1; - } - dir_list[dir_list_size++] = argv[0] + 6; - } - else if (!strncmp(argv[0], "--env=", 6)) { - char *tmp_env; - - if (argv[0][6] == '\0') - return print_help(); - if (env_list_size >= sizeof(env_list) / sizeof(char *)) { - printf("Only allow max env number %d\n", - (int)(sizeof(env_list) / sizeof(char *))); - return 1; - } - tmp_env = argv[0] + 6; - if (validate_env_str(tmp_env)) - env_list[env_list_size++] = tmp_env; - else { - printf("Wasm parse env string failed: expect \"key=value\", " - "got \"%s\"\n", - tmp_env); - return print_help(); - } - } -#endif /* WASM_ENABLE_LIBC_WASI */ #if WASM_ENABLE_MULTI_MODULE != 0 else if (!strncmp(argv[0], MODULE_PATH, strlen(MODULE_PATH))) { module_search_path = handle_module_path(argv[0]); @@ -423,8 +372,22 @@ main(int argc, char *argv[]) patch); return 0; } - else + else { +#if WASM_ENABLE_LIBC_WASI != 0 + libc_wasi_parse_result_t result = + libc_wasi_parse(argv[0], &wasi_parse_ctx); + switch (result) { + case LIBC_WASI_PARSE_RESULT_OK: + continue; + case LIBC_WASI_PARSE_RESULT_NEED_HELP: + return print_help(); + case LIBC_WASI_PARSE_RESULT_BAD_PARAM: + return 1; + } +#else return print_help(); +#endif + } } if (argc == 0) @@ -507,8 +470,7 @@ main(int argc, char *argv[]) } #if WASM_ENABLE_LIBC_WASI != 0 - wasm_runtime_set_wasi_args(wasm_module, dir_list, dir_list_size, NULL, 0, - env_list, env_list_size, argv, argc); + libc_wasi_init(wasm_module, argc, argv, &wasi_parse_ctx); #endif /* instantiate the module */