Add more checks about the imports of wasm_instance_new (#1843)

Check whether the `imports` argument is NULL in wasm_instance_new and check
the import count of each kind.

Fix issue reported by https://github.com/bytecodealliance/wasm-micro-runtime/issues/1833
This commit is contained in:
liang.he 2023-01-03 17:16:49 +08:00 committed by GitHub
parent d5aa354d41
commit bf2be805f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 102 additions and 63 deletions

View File

@ -3,6 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/ */
#include "bh_log.h"
#include "wasm_c_api_internal.h" #include "wasm_c_api_internal.h"
#include "bh_assert.h" #include "bh_assert.h"
@ -275,10 +276,14 @@ WASM_DEFINE_VEC_OWN(store, wasm_store_delete)
WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete) WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete)
#ifndef NDEBUG #ifndef NDEBUG
#if WAMR_BUILD_MEMORY_PROFILING != 0
#define WASM_C_DUMP_PROC_MEM() LOG_PROC_MEM() #define WASM_C_DUMP_PROC_MEM() LOG_PROC_MEM()
#else #else
#define WASM_C_DUMP_PROC_MEM() (void)0 #define WASM_C_DUMP_PROC_MEM() (void)0
#endif #endif
#else
#define WASM_C_DUMP_PROC_MEM() (void)0
#endif
/* Runtime Environment */ /* Runtime Environment */
own wasm_config_t * own wasm_config_t *
@ -4345,7 +4350,7 @@ interp_link_global(const WASMModule *module_interp, uint16 global_idx_rt,
return true; return true;
} }
static uint32 static bool
interp_link(const wasm_instance_t *inst, const WASMModule *module_interp, interp_link(const wasm_instance_t *inst, const WASMModule *module_interp,
wasm_extern_t *imports[]) wasm_extern_t *imports[])
{ {
@ -4390,11 +4395,11 @@ interp_link(const wasm_instance_t *inst, const WASMModule *module_interp,
} }
} }
return i; return true;
failed: failed:
LOG_DEBUG("%s failed", __FUNCTION__); LOG_DEBUG("%s failed", __FUNCTION__);
return (uint32)-1; return false;
} }
static bool static bool
@ -4557,7 +4562,7 @@ failed:
return false; return false;
} }
static uint32 static bool
aot_link(const wasm_instance_t *inst, const AOTModule *module_aot, aot_link(const wasm_instance_t *inst, const AOTModule *module_aot,
wasm_extern_t *imports[]) wasm_extern_t *imports[])
{ {
@ -4605,11 +4610,11 @@ aot_link(const wasm_instance_t *inst, const AOTModule *module_aot,
} }
} }
return i; return true;
failed: failed:
LOG_DEBUG("%s failed", __FUNCTION__); LOG_DEBUG("%s failed", __FUNCTION__);
return (uint32)-1; return false;
} }
static bool static bool
@ -4713,6 +4718,57 @@ wasm_instance_new(wasm_store_t *store, const wasm_module_t *module,
KILOBYTE(32), KILOBYTE(32)); KILOBYTE(32), KILOBYTE(32));
} }
static bool
compare_imports(const wasm_module_t *module, const wasm_extern_vec_t *imports)
{
unsigned import_func_count = 0;
unsigned import_global_count = 0;
unsigned import_memory_count = 0;
unsigned import_table_count = 0;
unsigned i = 0;
for (i = 0; imports && i < imports->num_elems; i++) {
wasm_extern_t *import = imports->data[i];
switch (wasm_extern_kind(import)) {
case WASM_EXTERN_FUNC:
import_func_count++;
break;
case WASM_EXTERN_GLOBAL:
import_global_count++;
break;
case WASM_EXTERN_MEMORY:
import_memory_count++;
break;
case WASM_EXTERN_TABLE:
import_table_count++;
break;
default:
UNREACHABLE();
return false;
}
}
#if WASM_ENABLE_INTERP != 0
if ((*module)->module_type == Wasm_Module_Bytecode)
return import_func_count == MODULE_INTERP(module)->import_function_count
&& import_global_count
== MODULE_INTERP(module)->import_global_count
&& import_memory_count
== MODULE_INTERP(module)->import_memory_count
&& import_table_count
== MODULE_INTERP(module)->import_table_count;
#endif
#if WASM_ENABLE_AOT != 0
if ((*module)->module_type == Wasm_Module_AoT)
return import_func_count == MODULE_AOT(module)->import_func_count
&& import_global_count == MODULE_AOT(module)->import_global_count
&& import_memory_count == MODULE_AOT(module)->import_memory_count
&& import_table_count == MODULE_AOT(module)->import_table_count;
#endif
return false;
}
wasm_instance_t * wasm_instance_t *
wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
const wasm_extern_vec_t *imports, const wasm_extern_vec_t *imports,
@ -4721,18 +4777,22 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
{ {
char sub_error_buf[128] = { 0 }; char sub_error_buf[128] = { 0 };
char error_buf[256] = { 0 }; char error_buf[256] = { 0 };
bool import_count_verified = false;
wasm_instance_t *instance = NULL; wasm_instance_t *instance = NULL;
WASMModuleInstance *inst_rt; WASMModuleInstance *inst_rt;
CApiFuncImport *func_import = NULL, **p_func_imports = NULL; CApiFuncImport *func_import = NULL, **p_func_imports = NULL;
uint32 i = 0, import_count = 0, import_func_count = 0; uint32 i = 0, import_func_count = 0;
uint64 total_size; uint64 total_size;
bool processed = false; bool build_exported = false;
bh_assert(singleton_engine); bh_assert(singleton_engine);
if (!module) { if (!module)
return NULL; return NULL;
if (!compare_imports(module, imports)) {
snprintf(sub_error_buf, sizeof(sub_error_buf),
"Failed to match imports");
goto failed;
} }
WASM_C_DUMP_PROC_MEM(); WASM_C_DUMP_PROC_MEM();
@ -4746,43 +4806,28 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
/* link module and imports */ /* link module and imports */
if (imports && imports->num_elems) { if (imports && imports->num_elems) {
bool link = false;
#if WASM_ENABLE_INTERP != 0 #if WASM_ENABLE_INTERP != 0
if ((*module)->module_type == Wasm_Module_Bytecode) { if ((*module)->module_type == Wasm_Module_Bytecode) {
import_count = MODULE_INTERP(module)->import_count; if (!interp_link(instance, MODULE_INTERP(module),
(wasm_extern_t **)imports->data)) {
if (import_count) { snprintf(sub_error_buf, sizeof(sub_error_buf),
uint32 actual_link_import_count = "Failed to validate imports");
interp_link(instance, MODULE_INTERP(module), goto failed;
(wasm_extern_t **)imports->data);
/* make sure a complete import list */
if ((int32)import_count < 0
|| import_count != actual_link_import_count) {
snprintf(sub_error_buf, sizeof(sub_error_buf),
"Failed to validate imports");
goto failed;
}
} }
import_count_verified = true; link = true;
} }
#endif #endif
#if WASM_ENABLE_AOT != 0 #if WASM_ENABLE_AOT != 0
if ((*module)->module_type == Wasm_Module_AoT) { if ((*module)->module_type == Wasm_Module_AoT) {
import_count = MODULE_AOT(module)->import_func_count if (!aot_link(instance, MODULE_AOT(module),
+ MODULE_AOT(module)->import_global_count (wasm_extern_t **)imports->data)) {
+ MODULE_AOT(module)->import_memory_count snprintf(sub_error_buf, sizeof(sub_error_buf),
+ MODULE_AOT(module)->import_table_count; "Failed to validate imports");
goto failed;
if (import_count) {
import_count = aot_link(instance, MODULE_AOT(module),
(wasm_extern_t **)imports->data);
if ((int32)import_count < 0) {
snprintf(sub_error_buf, sizeof(sub_error_buf),
"Failed to validate imports");
goto failed;
}
} }
import_count_verified = true; link = true;
} }
#endif #endif
@ -4790,7 +4835,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
* a wrong combination of module filetype and compilation flags * a wrong combination of module filetype and compilation flags
* also leads to below branch * also leads to below branch
*/ */
if (!import_count_verified) { if (!link) {
snprintf(sub_error_buf, sizeof(sub_error_buf), snprintf(sub_error_buf, sizeof(sub_error_buf),
"Failed to verify import count"); "Failed to verify import count");
goto failed; goto failed;
@ -4809,6 +4854,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
goto failed; goto failed;
} }
/* create the c-api func import list */
inst_rt = (WASMModuleInstance *)instance->inst_comm_rt; inst_rt = (WASMModuleInstance *)instance->inst_comm_rt;
#if WASM_ENABLE_INTERP != 0 #if WASM_ENABLE_INTERP != 0
if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) { if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
@ -4825,7 +4871,6 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
#endif #endif
bh_assert(p_func_imports); bh_assert(p_func_imports);
/* create the c-api func import list */
total_size = (uint64)sizeof(CApiFuncImport) * import_func_count; total_size = (uint64)sizeof(CApiFuncImport) * import_func_count;
if (total_size > 0 if (total_size > 0
&& !(*p_func_imports = func_import = malloc_internal(total_size))) { && !(*p_func_imports = func_import = malloc_internal(total_size))) {
@ -4835,7 +4880,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
} }
/* fill in c-api func import list */ /* fill in c-api func import list */
for (i = 0; i < import_count; i++) { for (i = 0; imports && i < imports->num_elems; i++) {
wasm_func_t *func_host; wasm_func_t *func_host;
wasm_extern_t *in; wasm_extern_t *in;
@ -4857,10 +4902,9 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
func_import++; func_import++;
} }
bh_assert((uint32)(func_import - *p_func_imports) == import_func_count);
/* fill with inst */ /* fill with inst */
for (i = 0; imports && imports->data && i < (uint32)import_count; ++i) { for (i = 0; imports && imports->data && i < imports->num_elems; ++i) {
wasm_extern_t *import = imports->data[i]; wasm_extern_t *import = imports->data[i];
switch (import->kind) { switch (import->kind) {
case WASM_EXTERN_FUNC: case WASM_EXTERN_FUNC:
@ -4903,7 +4947,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
goto failed; goto failed;
} }
processed = true; build_exported = true;
} }
#endif #endif
@ -4927,7 +4971,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
goto failed; goto failed;
} }
processed = true; build_exported = true;
} }
#endif #endif
@ -4935,7 +4979,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
* a wrong combination of module filetype and compilation flags * a wrong combination of module filetype and compilation flags
* leads to below branch * leads to below branch
*/ */
if (!processed) { if (!build_exported) {
snprintf(sub_error_buf, sizeof(sub_error_buf), snprintf(sub_error_buf, sizeof(sub_error_buf),
"Incorrect filetype and compilation flags"); "Incorrect filetype and compilation flags");
goto failed; goto failed;

View File

@ -159,6 +159,9 @@ endif()
check_pie_supported() check_pie_supported()
include(CTest)
enable_testing()
foreach(EX ${EXAMPLES}) foreach(EX ${EXAMPLES})
set(SRC ${CMAKE_CURRENT_LIST_DIR}/src/${EX}.c) set(SRC ${CMAKE_CURRENT_LIST_DIR}/src/${EX}.c)
@ -193,6 +196,12 @@ foreach(EX ${EXAMPLES})
) )
add_dependencies(${EX} ${EX}_AOT) add_dependencies(${EX} ${EX}_AOT)
endif() endif()
# run `ctest --test-dir build`
add_test(NAME Test_${EX}
COMMAND ./${EX}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
endforeach() endforeach()
if (CMAKE_BUILD_TYPE STREQUAL "Debug") if (CMAKE_BUILD_TYPE STREQUAL "Debug")
@ -201,19 +210,5 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
REQUIRED REQUIRED
) )
if(VALGRIND) # run `ctest -T memcheck -V --test-dir build`
foreach(EX ${EXAMPLES}) endif()
add_custom_command(
OUTPUT ${EX}_leak_check.report
DEPENDS ${EX} ${EX}_WASM
COMMAND ${VALGRIND} --tool=memcheck --leak-check=full -- ./${EX} > ${EX}_leak_check.report 2>&1
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
add_custom_target(${EX}_LEAK_TEST ALL
DEPENDS ${EX}_leak_check.report
COMMAND grep "All heap blocks were freed -- no leaks are possible" ${EX}_leak_check.report
COMMENT "Please read ${EX}_leak_check.report when meeting Error"
)
endforeach()
endif (VALGRIND)
endif (CMAKE_BUILD_TYPE STREQUAL "Debug")

View File

@ -238,7 +238,7 @@ main(int argc, const char *argv[])
IMPORT_FUNCTION_LIST(CREATE_WASM_FUNCTION) IMPORT_FUNCTION_LIST(CREATE_WASM_FUNCTION)
#undef CREATE_WASM_FUNCTION #undef CREATE_WASM_FUNCTION
wasm_extern_t *fs[10] = { 0 }; wasm_extern_t *fs[2] = { 0 };
#define ADD_TO_FUNCTION_LIST(name, index, ...) \ #define ADD_TO_FUNCTION_LIST(name, index, ...) \
fs[index] = wasm_func_as_extern(function_##name); fs[index] = wasm_func_as_extern(function_##name);
IMPORT_FUNCTION_LIST(ADD_TO_FUNCTION_LIST) IMPORT_FUNCTION_LIST(ADD_TO_FUNCTION_LIST)