Skip to content

Commit 18d3630

Browse files
authored
wasm loader: Fix checks for opcode ref.func and opcode else (#3340)
Fix wasm loader integrity checks for opcode ref.func and opcode else: for opcode ref.func, the function must be an import, exported, or present in a table elem segment or global initializer to be used as the operand to ref.func, for opcode else, there must not be an else opcode previously. Reported in #3336 and #3337. And fix mini loader PUSH_MEM_OFFSET/POP_MEM_OFFSET macro definitions due to the introducing of memory64 feature.
1 parent a6e008b commit 18d3630

File tree

2 files changed

+96
-38
lines changed

2 files changed

+96
-38
lines changed

core/iwasm/interpreter/wasm_loader.c

Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4628,7 +4628,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
46284628
bool is_passive = false;
46294629
uint32 mem_flag;
46304630
#endif
4631-
uint8 mem_offset_type;
4631+
uint8 mem_offset_type = VALUE_TYPE_I32;
46324632

46334633
read_leb_uint32(p, p_end, data_seg_count);
46344634

@@ -11335,8 +11335,10 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
1133511335
BlockType block_type;
1133611336

1133711337
if (loader_ctx->csp_num < 2
11338-
|| (loader_ctx->frame_csp - 1)->label_type
11339-
!= LABEL_TYPE_IF) {
11338+
/* the matched if isn't found */
11339+
|| (loader_ctx->frame_csp - 1)->label_type != LABEL_TYPE_IF
11340+
/* duplicated else is found */
11341+
|| (loader_ctx->frame_csp - 1)->else_addr) {
1134011342
set_error_buf(
1134111343
error_buf, error_buf_size,
1134211344
"opcode else found without matched opcode if");
@@ -12408,33 +12410,58 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
1240812410
goto fail;
1240912411
}
1241012412

12411-
/* Refer to a forward-declared function */
12412-
if (func_idx >= cur_func_idx + module->import_function_count) {
12413+
/* Refer to a forward-declared function:
12414+
the function must be an import, exported, or present in
12415+
a table elem segment or global initializer to be used as
12416+
the operand to ref.func */
12417+
if (func_idx >= module->import_function_count) {
1241312418
WASMTableSeg *table_seg = module->table_segments;
1241412419
bool func_declared = false;
1241512420
uint32 j;
1241612421

12417-
/* Check whether the function is declared in table segs,
12418-
note that it doesn't matter whether the table seg's mode
12419-
is passive, active or declarative. */
12420-
for (i = 0; i < module->table_seg_count; i++, table_seg++) {
12421-
if (table_seg->elem_type == VALUE_TYPE_FUNCREF
12422-
#if WASM_ENABLE_GC != 0
12423-
|| (table_seg->elem_type == REF_TYPE_HT_NON_NULLABLE
12424-
&& table_seg->elem_ref_type->ref_ht_common
12425-
.heap_type
12426-
== HEAP_TYPE_FUNC)
12427-
#endif
12428-
) {
12429-
for (j = 0; j < table_seg->value_count; j++) {
12430-
if (table_seg->init_values[j].u.ref_index
12431-
== func_idx) {
12432-
func_declared = true;
12433-
break;
12422+
for (i = 0; i < module->global_count; i++) {
12423+
if (module->globals[i].type == VALUE_TYPE_FUNCREF
12424+
&& module->globals[i].init_expr.init_expr_type
12425+
== INIT_EXPR_TYPE_FUNCREF_CONST
12426+
&& module->globals[i].init_expr.u.u32 == func_idx) {
12427+
func_declared = true;
12428+
break;
12429+
}
12430+
}
12431+
12432+
if (!func_declared) {
12433+
/* Check whether the function is declared in table segs,
12434+
note that it doesn't matter whether the table seg's
12435+
mode is passive, active or declarative. */
12436+
for (i = 0; i < module->table_seg_count;
12437+
i++, table_seg++) {
12438+
if (table_seg->elem_type == VALUE_TYPE_FUNCREF
12439+
#if WASM_ENABLE_GC != 0
12440+
/* elem type is (ref null? func) or
12441+
(ref null? $t) */
12442+
|| ((table_seg->elem_type
12443+
== REF_TYPE_HT_NON_NULLABLE
12444+
|| table_seg->elem_type
12445+
== REF_TYPE_HT_NULLABLE)
12446+
&& (table_seg->elem_ref_type->ref_ht_common
12447+
.heap_type
12448+
== HEAP_TYPE_FUNC
12449+
|| table_seg->elem_ref_type
12450+
->ref_ht_common.heap_type
12451+
> 0))
12452+
#endif
12453+
) {
12454+
for (j = 0; j < table_seg->value_count; j++) {
12455+
if (table_seg->init_values[j].u.ref_index
12456+
== func_idx) {
12457+
func_declared = true;
12458+
break;
12459+
}
1243412460
}
1243512461
}
1243612462
}
1243712463
}
12464+
1243812465
if (!func_declared) {
1243912466
/* Check whether the function is exported */
1244012467
for (i = 0; i < module->export_count; i++) {

core/iwasm/interpreter/wasm_mini_loader.c

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,7 +1776,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
17761776
bool is_passive = false;
17771777
uint32 mem_flag;
17781778
#endif
1779-
uint8 mem_offset_type;
1779+
uint8 mem_offset_type = VALUE_TYPE_I32;
17801780

17811781
read_leb_uint32(p, p_end, data_seg_count);
17821782

@@ -5179,10 +5179,21 @@ wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, void *value,
51795179
goto fail; \
51805180
} while (0)
51815181

5182-
#define PUSH_MEM_OFFSET() PUSH_OFFSET_TYPE(mem_offset_type)
5182+
#define PUSH_MEM_OFFSET() \
5183+
do { \
5184+
if (!wasm_loader_push_frame_ref_offset(loader_ctx, mem_offset_type, \
5185+
disable_emit, operand_offset, \
5186+
error_buf, error_buf_size)) \
5187+
goto fail; \
5188+
} while (0)
51835189
#define PUSH_PAGE_COUNT() PUSH_MEM_OFFSET()
51845190

5185-
#define POP_MEM_OFFSET() POP_OFFSET_TYPE(mem_offset_type)
5191+
#define POP_MEM_OFFSET() \
5192+
do { \
5193+
if (!wasm_loader_pop_frame_ref_offset(loader_ctx, mem_offset_type, \
5194+
error_buf, error_buf_size)) \
5195+
goto fail; \
5196+
} while (0)
51865197

51875198
#define POP_AND_PUSH(type_pop, type_push) \
51885199
do { \
@@ -6203,8 +6214,11 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
62036214
BranchBlock *block = NULL;
62046215
BlockType block_type = (loader_ctx->frame_csp - 1)->block_type;
62056216
bh_assert(loader_ctx->csp_num >= 2
6217+
/* the matched if is found */
62066218
&& (loader_ctx->frame_csp - 1)->label_type
6207-
== LABEL_TYPE_IF);
6219+
== LABEL_TYPE_IF
6220+
/* duplicated else isn't found */
6221+
&& !(loader_ctx->frame_csp - 1)->else_addr);
62086222
block = loader_ctx->frame_csp - 1;
62096223

62106224
/* check whether if branch's stack matches its result type */
@@ -6916,26 +6930,43 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
69166930
goto fail;
69176931
}
69186932

6919-
/* Refer to a forward-declared function */
6920-
if (func_idx >= cur_func_idx + module->import_function_count) {
6933+
/* Refer to a forward-declared function:
6934+
the function must be an import, exported, or present in
6935+
a table elem segment or global initializer to be used as
6936+
the operand to ref.func */
6937+
if (func_idx >= module->import_function_count) {
69216938
WASMTableSeg *table_seg = module->table_segments;
69226939
bool func_declared = false;
69236940
uint32 j;
69246941

6925-
/* Check whether the function is declared in table segs,
6926-
note that it doesn't matter whether the table seg's mode
6927-
is passive, active or declarative. */
6928-
for (i = 0; i < module->table_seg_count; i++, table_seg++) {
6929-
if (table_seg->elem_type == VALUE_TYPE_FUNCREF) {
6930-
for (j = 0; j < table_seg->value_count; j++) {
6931-
if (table_seg->init_values[j].u.ref_index
6932-
== func_idx) {
6933-
func_declared = true;
6934-
break;
6942+
for (i = 0; i < module->global_count; i++) {
6943+
if (module->globals[i].type == VALUE_TYPE_FUNCREF
6944+
&& module->globals[i].init_expr.init_expr_type
6945+
== INIT_EXPR_TYPE_FUNCREF_CONST
6946+
&& module->globals[i].init_expr.u.u32 == func_idx) {
6947+
func_declared = true;
6948+
break;
6949+
}
6950+
}
6951+
6952+
if (!func_declared) {
6953+
/* Check whether the function is declared in table segs,
6954+
note that it doesn't matter whether the table seg's
6955+
mode is passive, active or declarative. */
6956+
for (i = 0; i < module->table_seg_count;
6957+
i++, table_seg++) {
6958+
if (table_seg->elem_type == VALUE_TYPE_FUNCREF) {
6959+
for (j = 0; j < table_seg->value_count; j++) {
6960+
if (table_seg->init_values[j].u.ref_index
6961+
== func_idx) {
6962+
func_declared = true;
6963+
break;
6964+
}
69356965
}
69366966
}
69376967
}
69386968
}
6969+
69396970
if (!func_declared) {
69406971
/* Check whether the function is exported */
69416972
for (i = 0; i < module->export_count; i++) {

0 commit comments

Comments
 (0)