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.
This commit is contained in:
Wenyong Huang 2023-04-03 15:55:24 +08:00 committed by GitHub
parent 7701b379e4
commit e1d0c27ef9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 7 deletions

View File

@ -8222,12 +8222,13 @@ re_scan:
goto fail; 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; WASMTableSeg *table_seg = module->table_segments;
bool func_declared = false; bool func_declared = false;
uint32 j; 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++) { for (i = 0; i < module->table_seg_count; i++, table_seg++) {
if (table_seg->elem_type == VALUE_TYPE_FUNCREF if (table_seg->elem_type == VALUE_TYPE_FUNCREF
&& wasm_elem_is_declarative(table_seg->mode)) { && 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) { if (!func_declared) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"undeclared function reference"); "undeclared function reference");

View File

@ -6384,12 +6384,13 @@ re_scan:
goto fail; 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; WASMTableSeg *table_seg = module->table_segments;
bool func_declared = false; bool func_declared = false;
uint32 j; 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++) { for (i = 0; i < module->table_seg_count; i++, table_seg++) {
if (table_seg->elem_type == VALUE_TYPE_FUNCREF if (table_seg->elem_type == VALUE_TYPE_FUNCREF
&& wasm_elem_is_declarative(table_seg->mode)) { && wasm_elem_is_declarative(table_seg->mode)) {
@ -6402,11 +6403,18 @@ re_scan:
} }
} }
if (!func_declared) { if (!func_declared) {
set_error_buf(error_buf, error_buf_size, /* Check whether the function is exported */
"undeclared function reference"); for (i = 0; i < module->export_count; i++) {
goto fail; 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 #if WASM_ENABLE_FAST_INTERP != 0
emit_uint32(loader_ctx, func_idx); emit_uint32(loader_ctx, func_idx);