Просмотр исходного кода

Add import subtyping validation (#1308)

According to import subtyping validation:
  https://webassembly.github.io/spec/core/valid/types.html#import-subtyping
wasm-c-api needs to check types when linking.
liang.he 3 лет назад
Родитель
Сommit
1ee0d90d81
2 измененных файлов с 72 добавлено и 15 удалено
  1. 71 14
      core/iwasm/common/wasm_c_api.c
  2. 1 1
      samples/wasm-c-api/src/callback_chain.c

+ 71 - 14
core/iwasm/common/wasm_c_api.c

@@ -669,6 +669,48 @@ wasm_functype_results(const wasm_functype_t *func_type)
     return func_type->results;
 }
 
+static bool
+cmp_val_kind_with_val_type(wasm_valkind_t v_k, uint8 v_t)
+{
+    return (v_k == WASM_I32 && v_t == VALUE_TYPE_I32)
+           || (v_k == WASM_I64 && v_t == VALUE_TYPE_I64)
+           || (v_k == WASM_F32 && v_t == VALUE_TYPE_F32)
+           || (v_k == WASM_F64 && v_t == VALUE_TYPE_F64)
+           || (v_k == WASM_ANYREF && v_t == VALUE_TYPE_EXTERNREF)
+           || (v_k == WASM_FUNCREF && v_t == VALUE_TYPE_FUNCREF);
+}
+
+/*
+ *to compare a function type of wasm-c-api with a function type of wasm_runtime
+ */
+static bool
+wasm_functype_same_internal(const wasm_functype_t *type,
+                            const WASMType *type_intl)
+{
+    uint32 i = 0;
+
+    if (!type || !type_intl || type->params->num_elems != type_intl->param_count
+        || type->results->num_elems != type_intl->result_count)
+        return false;
+
+    for (i = 0; i < type->params->num_elems; i++) {
+        wasm_valtype_t *v_t = type->params->data[i];
+        if (!cmp_val_kind_with_val_type(wasm_valtype_kind(v_t),
+                                        type_intl->types[i]))
+            return false;
+    }
+
+    for (i = 0; i < type->results->num_elems; i++) {
+        wasm_valtype_t *v_t = type->results->data[i];
+        if (!cmp_val_kind_with_val_type(
+                wasm_valtype_kind(v_t),
+                type_intl->types[i + type->params->num_elems]))
+            return false;
+    }
+
+    return true;
+}
+
 wasm_globaltype_t *
 wasm_globaltype_new(own wasm_valtype_t *val_type, wasm_mutability_t mut)
 {
@@ -3812,6 +3854,11 @@ interp_link_func(const wasm_instance_t *inst, const WASMModule *module_interp,
     imported_func_interp = module_interp->import_functions + func_idx_rt;
     bh_assert(imported_func_interp);
 
+    /* type comparison */
+    if (!wasm_functype_same_internal(
+            import->type, imported_func_interp->u.function.func_type))
+        return false;
+
     imported_func_interp->u.function.call_conv_wasm_c_api = true;
     imported_func_interp->u.function.wasm_c_api_with_env = import->with_env;
     if (import->with_env) {
@@ -3840,25 +3887,25 @@ interp_link_global(const WASMModule *module_interp, uint16 global_idx_rt,
     imported_global_interp = module_interp->import_globals + global_idx_rt;
     bh_assert(imported_global_interp);
 
+    if (!cmp_val_kind_with_val_type(wasm_valtype_kind(import->type->val_type),
+                                    imported_global_interp->u.global.type))
+        return false;
+
     /* set init value */
     switch (wasm_valtype_kind(import->type->val_type)) {
         case WASM_I32:
-            bh_assert(VALUE_TYPE_I32 == imported_global_interp->u.global.type);
             imported_global_interp->u.global.global_data_linked.i32 =
                 import->init->of.i32;
             break;
         case WASM_I64:
-            bh_assert(VALUE_TYPE_I64 == imported_global_interp->u.global.type);
             imported_global_interp->u.global.global_data_linked.i64 =
                 import->init->of.i64;
             break;
         case WASM_F32:
-            bh_assert(VALUE_TYPE_F32 == imported_global_interp->u.global.type);
             imported_global_interp->u.global.global_data_linked.f32 =
                 import->init->of.f32;
             break;
         case WASM_F64:
-            bh_assert(VALUE_TYPE_F64 == imported_global_interp->u.global.type);
             imported_global_interp->u.global.global_data_linked.f64 =
                 import->init->of.f64;
             break;
@@ -3888,20 +3935,22 @@ interp_link(const wasm_instance_t *inst, const WASMModule *module_interp,
         switch (import_rt->kind) {
             case IMPORT_KIND_FUNC:
             {
-                if (!interp_link_func(inst, module_interp, import_func_i++,
+                if (!interp_link_func(inst, module_interp, import_func_i,
                                       wasm_extern_as_func(import))) {
+                    LOG_WARNING("link #%d function failed", import_func_i);
                     goto failed;
                 }
-
+                import_func_i++;
                 break;
             }
             case IMPORT_KIND_GLOBAL:
             {
-                if (!interp_link_global(module_interp, import_global_i++,
+                if (!interp_link_global(module_interp, import_global_i,
                                         wasm_extern_as_global(import))) {
+                    LOG_WARNING("link #%d global failed", import_global_i);
                     goto failed;
                 }
-
+                import_global_i++;
                 break;
             }
             case IMPORT_KIND_MEMORY:
@@ -4021,6 +4070,10 @@ aot_link_func(const wasm_instance_t *inst, const AOTModule *module_aot,
     import_aot_func = module_aot->import_funcs + import_func_idx_rt;
     bh_assert(import_aot_func);
 
+    /* type comparison */
+    if (!wasm_functype_same_internal(import->type, import_aot_func->func_type))
+        return false;
+
     import_aot_func->call_conv_wasm_c_api = true;
     import_aot_func->wasm_c_api_with_env = import->with_env;
     if (import->with_env) {
@@ -4051,21 +4104,21 @@ aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt,
     val_type = wasm_globaltype_content(import->type);
     bh_assert(val_type);
 
+    if (!cmp_val_kind_with_val_type(wasm_valtype_kind(val_type),
+                                    import_aot_global->type))
+        return false;
+
     switch (wasm_valtype_kind(val_type)) {
         case WASM_I32:
-            bh_assert(VALUE_TYPE_I32 == import_aot_global->type);
             import_aot_global->global_data_linked.i32 = import->init->of.i32;
             break;
         case WASM_I64:
-            bh_assert(VALUE_TYPE_I64 == import_aot_global->type);
             import_aot_global->global_data_linked.i64 = import->init->of.i64;
             break;
         case WASM_F32:
-            bh_assert(VALUE_TYPE_F32 == import_aot_global->type);
             import_aot_global->global_data_linked.f32 = import->init->of.f32;
             break;
         case WASM_F64:
-            bh_assert(VALUE_TYPE_F64 == import_aot_global->type);
             import_aot_global->global_data_linked.f64 = import->init->of.f64;
             break;
         default:
@@ -4103,17 +4156,21 @@ aot_link(const wasm_instance_t *inst, const AOTModule *module_aot,
             case WASM_EXTERN_FUNC:
                 bh_assert(import_func_i < module_aot->import_func_count);
                 func = wasm_extern_as_func((wasm_extern_t *)import);
-                if (!aot_link_func(inst, module_aot, import_func_i++, func)) {
+                if (!aot_link_func(inst, module_aot, import_func_i, func)) {
+                    LOG_WARNING("link #%d function failed", import_func_i);
                     goto failed;
                 }
+                import_func_i++;
 
                 break;
             case WASM_EXTERN_GLOBAL:
                 bh_assert(import_global_i < module_aot->import_global_count);
                 global = wasm_extern_as_global((wasm_extern_t *)import);
-                if (!aot_link_global(module_aot, import_global_i++, global)) {
+                if (!aot_link_global(module_aot, import_global_i, global)) {
+                    LOG_WARNING("link #%d global failed", import_global_i);
                     goto failed;
                 }
+                import_global_i++;
 
                 break;
             case WASM_EXTERN_MEMORY:

+ 1 - 1
samples/wasm-c-api/src/callback_chain.c

@@ -25,7 +25,7 @@ call_wasm_function(uint32_t export_id, const wasm_val_vec_t *args,
 #define FUNCTION_TYPE_NIL_I32 wasm_functype_new_0_1(wasm_valtype_new_i32())
 // (i32, i32) -> nil
 #define FUNCTION_TYPE_I32X2_NIL \
-    wasm_functype_new_1_1(wasm_valtype_new_i32(), wasm_valtype_new_i32())
+    wasm_functype_new_2_0(wasm_valtype_new_i32(), wasm_valtype_new_i32())
 
 /* IMPORT FUNCTION LIST */
 #define IMPORT_FUNCTION_LIST(V)            \