From e1d0c27ef9382b1395e983ca3a113e524fe7d2e1 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Mon, 3 Apr 2023 15:55:24 +0800 Subject: [PATCH] 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. --- core/iwasm/interpreter/wasm_loader.c | 16 ++++++++++++++-- core/iwasm/interpreter/wasm_mini_loader.c | 18 +++++++++++++----- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index d3128dbd0..a3c4f4224 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/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"); diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index 3a983b293..aa5e18f6a 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/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