-
Notifications
You must be signed in to change notification settings - Fork 628
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WAMR fails names.wast spec test #3858
Comments
Hi, this is a limitation and we decided not to support it, see: Is there any actual use case from you? |
My team is evaluating several WASM engines for use in various projects. One of my tasks is to get the spec tests running with our internal CI, and to determine which tests we should skip/ignore. While I'm not sure why a user would need NULs in their export/import names, it is part of the spec. Should the engine not strive for spec compliance where reasonably possible? This seems like not much additional work. |
The string is stored into const string set, and is also emitted into AOT file, and loaded again in aot loader. All the operations assume the string is null terminated, it may be very complex to change their behaviors and it is easy to make things wrong. A workaround that I can think is to change the character diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c
index cc3b4bb9..3f753763 100644
--- a/core/iwasm/common/wasm_runtime_common.c
+++ b/core/iwasm/common/wasm_runtime_common.c
@@ -2277,6 +2277,32 @@ wasm_runtime_lookup_function(WASMModuleInstanceCommon *const module_inst,
return NULL;
}
+WASMFunctionInstanceCommon *
+wasm_runtime_lookup_function_raw(WASMModuleInstanceCommon *const module_inst,
+ const char *name, uint32 len)
+{
+ WASMFunctionInstanceCommon *func;
+ char *name_c_str;
+ uint32 i;
+
+ if (!(name_c_str = wasm_runtime_malloc(len + 1))) {
+ return NULL;
+ }
+
+ bh_memcpy_s(name_c_str, len, name, len);
+ name_c_str[len] = '\0';
+
+ for (i = 0; i < len; i++) {
+ if (name_c_str[i] == '\0')
+ name_c_str[i] = 0x80;
+ }
+
+ func = wasm_runtime_lookup_function(module_inst, name_c_str);
+
+ wasm_runtime_free(name_c_str);
+ return func;
+}
+
uint32
wasm_func_get_param_count(WASMFunctionInstanceCommon *const func_inst,
WASMModuleInstanceCommon *const module_inst)
diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h
index fb2c7940..58f869b4 100644
--- a/core/iwasm/common/wasm_runtime_common.h
+++ b/core/iwasm/common/wasm_runtime_common.h
@@ -616,6 +616,10 @@ WASM_RUNTIME_API_EXTERN WASMFunctionInstanceCommon *
wasm_runtime_lookup_function(WASMModuleInstanceCommon *const module_inst,
const char *name);
+WASM_RUNTIME_API_EXTERN WASMFunctionInstanceCommon *
+wasm_runtime_lookup_function_raw(WASMModuleInstanceCommon *const module_inst,
+ const char *name, uint32 len);
+
/* Internal API */
WASMFuncType *
wasm_runtime_get_function_type(const WASMFunctionInstanceCommon *function,
diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h
index dfb6b802..aaab591e 100644
--- a/core/iwasm/include/wasm_export.h
+++ b/core/iwasm/include/wasm_export.h
@@ -793,6 +793,10 @@ WASM_RUNTIME_API_EXTERN wasm_function_inst_t
wasm_runtime_lookup_function(const wasm_module_inst_t module_inst,
const char *name);
+wasm_function_inst_t
+wasm_runtime_lookup_function_raw(const wasm_module_inst_t module_inst,
+ const char *name, uint32 len);
+
/**
* Get parameter count of the function instance
*
diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c
index f6d5e103..47883a7b 100644
--- a/core/iwasm/interpreter/wasm_runtime.c
+++ b/core/iwasm/interpreter/wasm_runtime.c
@@ -4870,12 +4870,7 @@ wasm_check_utf8_str(const uint8 *str, uint32 len)
while (p < p_end) {
chr = *p;
- if (chr == 0) {
- LOG_WARNING(
- "LIMITATION: a string which contains '\\00' is unsupported");
- return false;
- }
- else if (chr < 0x80) {
+ if (chr < 0x80) {
p++;
}
else if (chr >= 0xC2 && chr <= 0xDF && p + 1 < p_end) {
@@ -4936,6 +4931,7 @@ wasm_const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module,
uint32 error_buf_size)
{
StringNode *node, *node_next;
+ uint32 i;
if (!wasm_check_utf8_str(str, len)) {
set_error_buf(error_buf, error_buf_size, "invalid UTF-8 encoding");
@@ -4946,6 +4942,11 @@ wasm_const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module,
return "";
}
else if (is_load_from_file_buf) {
+ for (i = 0; i < len; i++) {
+ if (str[i] == '\0')
+ ((char *)str)[i] = 0x80;
+ }
+
/* As the file buffer can be referred to after loading, we use
the previous byte of leb encoded size to adjust the string:
move string 1 byte backward and then append '\0' */
@@ -4977,6 +4978,11 @@ wasm_const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module,
bh_memcpy_s(node->str, len + 1, str, len);
node->str[len] = '\0';
+ for (i = 0; i < len; i++) {
+ if (node->str[i] == '\0')
+ node->str[i] = 0x80;
+ }
+
if (!module->const_str_list) {
/* set as head */
module->const_str_list = node; |
if you mean to expose wasm_runtime_lookup_function_raw to users, i guess it should perform utf-8 validation on the user-given name before escaping 0. |
Totally agree, thanks. |
Subject of the issue
WAMR currently fails the names.wast spec test, specifically because the spec permits module exports with names containing NUL bytes, but WAMR does not.
Test case
Run
names.wast
through iwasm using the spec test runner scripts.Your environment
Steps to reproduce
names.wast
spec through the spec test runner. Specifically, we have:and later
Expected behavior
The tests should pass.
Actual behavior
This fails, because the
wasm_lookup_function
function stops searching when it sees the null byte at the beginning of the function.Extra Info
I have the beginnings of a proposed fix which adds a
size_t name_len
field wherever export names are stored. This will change the AOT module representation, I don't know how much of a big deal this is.The patch below modifies the loader to feed the export name size through to the new
name_len
field. It also adds awasm_runtime_lookup_function_raw
function that takes the extra size_t parameter.I am curious if there is any interest in pursuing this change, or if WAMR deliberately does not want to support this aspect of the specification.
The text was updated successfully, but these errors were encountered: