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

Fix ref.func forward-declared function check (#2099)

When ref.func opcode refers to a function whose function index no smaller than
current function, the destination func should be forward-declared: it is declared
in the table element segments, or is declared in the export list.
Wenyong Huang 2 лет назад
Родитель
Сommit
e1d0c27ef9
2 измененных файлов с 27 добавлено и 7 удалено
  1. 14 2
      core/iwasm/interpreter/wasm_loader.c
  2. 13 5
      core/iwasm/interpreter/wasm_mini_loader.c

+ 14 - 2
core/iwasm/interpreter/wasm_loader.c

@@ -8222,12 +8222,13 @@ re_scan:
                     goto fail;
                 }
 
-                if (func_idx == cur_func_idx + module->import_function_count) {
+                /* Refer to a forward-declared function */
+                if (func_idx >= cur_func_idx + module->import_function_count) {
                     WASMTableSeg *table_seg = module->table_segments;
                     bool func_declared = false;
                     uint32 j;
 
-                    /* Check whether current function is declared */
+                    /* Check whether the function is declared in table segs */
                     for (i = 0; i < module->table_seg_count; i++, table_seg++) {
                         if (table_seg->elem_type == VALUE_TYPE_FUNCREF
                             && wasm_elem_is_declarative(table_seg->mode)) {
@@ -8239,6 +8240,17 @@ re_scan:
                             }
                         }
                     }
+                    if (!func_declared) {
+                        /* Check whether the function is exported */
+                        for (i = 0; i < module->export_count; i++) {
+                            if (module->exports[i].kind == EXPORT_KIND_FUNC
+                                && module->exports[i].index == func_idx) {
+                                func_declared = true;
+                                break;
+                            }
+                        }
+                    }
+
                     if (!func_declared) {
                         set_error_buf(error_buf, error_buf_size,
                                       "undeclared function reference");

+ 13 - 5
core/iwasm/interpreter/wasm_mini_loader.c

@@ -6384,12 +6384,13 @@ re_scan:
                     goto fail;
                 }
 
-                if (func_idx == cur_func_idx + module->import_function_count) {
+                /* Refer to a forward-declared function */
+                if (func_idx >= cur_func_idx + module->import_function_count) {
                     WASMTableSeg *table_seg = module->table_segments;
                     bool func_declared = false;
                     uint32 j;
 
-                    /* Check whether current function is declared */
+                    /* Check whether the function is declared in table segs */
                     for (i = 0; i < module->table_seg_count; i++, table_seg++) {
                         if (table_seg->elem_type == VALUE_TYPE_FUNCREF
                             && wasm_elem_is_declarative(table_seg->mode)) {
@@ -6402,10 +6403,17 @@ re_scan:
                         }
                     }
                     if (!func_declared) {
-                        set_error_buf(error_buf, error_buf_size,
-                                      "undeclared function reference");
-                        goto fail;
+                        /* Check whether the function is exported */
+                        for (i = 0; i < module->export_count; i++) {
+                            if (module->exports[i].kind == EXPORT_KIND_FUNC
+                                && module->exports[i].index == func_idx) {
+                                func_declared = true;
+                                break;
+                            }
+                        }
                     }
+                    bh_assert(func_declared);
+                    (void)func_declared;
                 }
 
 #if WASM_ENABLE_FAST_INTERP != 0