Skip to content

Commit 169e164

Browse files
authored
Fix wasm loader handling opcode br_table (#3176)
Fix the errors reported in the sanitizer test of nightly run CI. When the stack is in polymorphic state, the stack operands may be changed after pop and push operations (e.g. stack is empty but pop op can succeed in polymorphic, and the push op can push a new operand to stack), this may impact the following checks to other target blocks of the br_table opcode.
1 parent 88bfbcf commit 169e164

File tree

2 files changed

+251
-38
lines changed

2 files changed

+251
-38
lines changed

core/iwasm/interpreter/wasm_loader.c

Lines changed: 136 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9713,13 +9713,6 @@ reserve_block_ret(WASMLoaderContext *loader_ctx, uint8 opcode,
97139713
GET_LOCAL_REFTYPE(); \
97149714
} while (0)
97159715

9716-
#define CHECK_BR(depth) \
9717-
do { \
9718-
if (!wasm_loader_check_br(loader_ctx, depth, error_buf, \
9719-
error_buf_size)) \
9720-
goto fail; \
9721-
} while (0)
9722-
97239716
static bool
97249717
check_memory(WASMModule *module, char *error_buf, uint32 error_buf_size)
97259718
{
@@ -9920,6 +9913,27 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth,
99209913
bool is_type_multi_byte;
99219914
#endif
99229915

9916+
uint8 *frame_ref_old = loader_ctx->frame_ref;
9917+
uint8 *frame_ref_after_popped = NULL;
9918+
uint8 frame_ref_tmp[4] = { 0 };
9919+
uint8 *frame_ref_buf = frame_ref_tmp;
9920+
uint32 stack_cell_num_old = loader_ctx->stack_cell_num;
9921+
#if WASM_ENABLE_GC != 0
9922+
WASMRefTypeMap *frame_reftype_map_old = loader_ctx->frame_reftype_map;
9923+
WASMRefTypeMap *frame_reftype_map_after_popped = NULL;
9924+
WASMRefTypeMap frame_reftype_map_tmp[4] = { 0 };
9925+
WASMRefTypeMap *frame_reftype_map_buf = frame_reftype_map_tmp;
9926+
uint32 reftype_map_num_old = loader_ctx->reftype_map_num;
9927+
#endif
9928+
#if WASM_ENABLE_FAST_INTERP != 0
9929+
int16 *frame_offset_old = loader_ctx->frame_offset;
9930+
int16 *frame_offset_after_popped = NULL;
9931+
int16 frame_offset_tmp[4] = { 0 };
9932+
int16 *frame_offset_buf = frame_offset_tmp;
9933+
uint16 dynamic_offset_old = (loader_ctx->frame_csp - 1)->dynamic_offset;
9934+
#endif
9935+
bool ret = false;
9936+
99239937
bh_assert(loader_ctx->csp_num > 0);
99249938
if (loader_ctx->csp_num - 1 < depth) {
99259939
set_error_buf(error_buf, error_buf_size,
@@ -9956,7 +9970,7 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth,
99569970
/* If the stack is in polymorphic state, just clear the stack
99579971
* and then re-push the values to make the stack top values
99589972
* match block type. */
9959-
if (cur_block->is_stack_polymorphic && !is_br_table) {
9973+
if (cur_block->is_stack_polymorphic) {
99609974
#if WASM_ENABLE_GC != 0
99619975
int32 j = reftype_map_count - 1;
99629976
#endif
@@ -9975,6 +9989,52 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth,
99759989
#endif
99769990
POP_TYPE(types[i]);
99779991
}
9992+
9993+
/* Backup stack data since it may be changed in the below
9994+
push operations, and the stack data may be used when
9995+
checking other target blocks of opcode br_table */
9996+
if (is_br_table) {
9997+
uint64 total_size;
9998+
9999+
frame_ref_after_popped = loader_ctx->frame_ref;
10000+
total_size = (uint64)sizeof(uint8)
10001+
* (frame_ref_old - frame_ref_after_popped);
10002+
if (total_size > sizeof(frame_ref_tmp)
10003+
&& !(frame_ref_buf = loader_malloc(total_size, error_buf,
10004+
error_buf_size))) {
10005+
goto fail;
10006+
}
10007+
bh_memcpy_s(frame_ref_buf, (uint32)total_size,
10008+
frame_ref_after_popped, (uint32)total_size);
10009+
10010+
#if WASM_ENABLE_GC != 0
10011+
frame_reftype_map_after_popped = loader_ctx->frame_reftype_map;
10012+
total_size =
10013+
(uint64)sizeof(WASMRefTypeMap)
10014+
* (frame_reftype_map_old - frame_reftype_map_after_popped);
10015+
if (total_size > sizeof(frame_reftype_map_tmp)
10016+
&& !(frame_reftype_map_buf = loader_malloc(
10017+
total_size, error_buf, error_buf_size))) {
10018+
goto fail;
10019+
}
10020+
bh_memcpy_s(frame_reftype_map_buf, (uint32)total_size,
10021+
frame_reftype_map_after_popped, (uint32)total_size);
10022+
#endif
10023+
10024+
#if WASM_ENABLE_FAST_INTERP != 0
10025+
frame_offset_after_popped = loader_ctx->frame_offset;
10026+
total_size = (uint64)sizeof(int16)
10027+
* (frame_offset_old - frame_offset_after_popped);
10028+
if (total_size > sizeof(frame_offset_tmp)
10029+
&& !(frame_offset_buf = loader_malloc(total_size, error_buf,
10030+
error_buf_size))) {
10031+
goto fail;
10032+
}
10033+
bh_memcpy_s(frame_offset_buf, (uint32)total_size,
10034+
frame_offset_after_popped, (uint32)total_size);
10035+
#endif
10036+
}
10037+
997810038
#if WASM_ENABLE_GC != 0
997910039
j = 0;
998010040
#endif
@@ -9995,7 +10055,55 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth,
999510055
#endif
999610056
PUSH_TYPE(types[i]);
999710057
}
9998-
return true;
10058+
10059+
#if WASM_ENABLE_FAST_INTERP != 0
10060+
emit_br_info(target_block);
10061+
#endif
10062+
10063+
/* Restore the stack data, note that frame_ref_bottom,
10064+
frame_reftype_map_bottom, frame_offset_bottom may be
10065+
re-allocated in the above push operations */
10066+
if (is_br_table) {
10067+
uint32 total_size;
10068+
10069+
/* The stack operand num should not be smaller than before
10070+
after pop and push operations */
10071+
bh_assert(loader_ctx->stack_cell_num >= stack_cell_num_old);
10072+
loader_ctx->stack_cell_num = stack_cell_num_old;
10073+
loader_ctx->frame_ref =
10074+
loader_ctx->frame_ref_bottom + stack_cell_num_old;
10075+
total_size = (uint32)sizeof(uint8)
10076+
* (frame_ref_old - frame_ref_after_popped);
10077+
bh_memcpy_s((uint8 *)loader_ctx->frame_ref - total_size, total_size,
10078+
frame_ref_buf, total_size);
10079+
10080+
#if WASM_ENABLE_GC != 0
10081+
/* The stack operand num should not be smaller than before
10082+
after pop and push operations */
10083+
bh_assert(loader_ctx->reftype_map_num >= reftype_map_num_old);
10084+
loader_ctx->reftype_map_num = reftype_map_num_old;
10085+
loader_ctx->frame_reftype_map =
10086+
loader_ctx->frame_reftype_map_bottom + reftype_map_num_old;
10087+
total_size =
10088+
(uint32)sizeof(WASMRefTypeMap)
10089+
* (frame_reftype_map_old - frame_reftype_map_after_popped);
10090+
bh_memcpy_s((uint8 *)loader_ctx->frame_reftype_map - total_size,
10091+
total_size, frame_reftype_map_buf, total_size);
10092+
#endif
10093+
10094+
#if WASM_ENABLE_FAST_INTERP != 0
10095+
loader_ctx->frame_offset =
10096+
loader_ctx->frame_offset_bottom + stack_cell_num_old;
10097+
total_size = (uint32)sizeof(int16)
10098+
* (frame_offset_old - frame_offset_after_popped);
10099+
bh_memcpy_s((uint8 *)loader_ctx->frame_offset - total_size,
10100+
total_size, frame_offset_buf, total_size);
10101+
(loader_ctx->frame_csp - 1)->dynamic_offset = dynamic_offset_old;
10102+
#endif
10103+
}
10104+
10105+
ret = true;
10106+
goto cleanup_and_return;
999910107
}
1000010108

1000110109
available_stack_cell =
@@ -10031,7 +10139,7 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth,
1003110139
ref_type,
1003210140
#endif
1003310141
error_buf, error_buf_size)) {
10034-
return false;
10142+
goto fail;
1003510143
}
1003610144
cell_num = wasm_value_type_cell_num(types[i]);
1003710145
frame_ref -= cell_num;
@@ -10045,10 +10153,26 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth,
1004510153
#endif
1004610154
}
1004710155

10048-
return true;
10156+
#if WASM_ENABLE_FAST_INTERP != 0
10157+
emit_br_info(target_block);
10158+
#endif
1004910159

10160+
ret = true;
10161+
10162+
cleanup_and_return:
1005010163
fail:
10051-
return false;
10164+
if (frame_ref_buf && frame_ref_buf != frame_ref_tmp)
10165+
wasm_runtime_free(frame_ref_buf);
10166+
#if WASM_ENABLE_GC != 0
10167+
if (frame_reftype_map_buf && frame_reftype_map_buf != frame_reftype_map_tmp)
10168+
wasm_runtime_free(frame_reftype_map_buf);
10169+
#endif
10170+
#if WASM_ENABLE_FAST_INTERP != 0
10171+
if (frame_offset_buf && frame_offset_buf != frame_offset_tmp)
10172+
wasm_runtime_free(frame_offset_tmp);
10173+
#endif
10174+
10175+
return ret;
1005210176
}
1005310177

1005410178
static BranchBlock *
@@ -10066,9 +10190,6 @@ check_branch_block(WASMLoaderContext *loader_ctx, uint8 **p_buf, uint8 *buf_end,
1006610190
}
1006710191

1006810192
frame_csp_tmp = loader_ctx->frame_csp - depth - 1;
10069-
#if WASM_ENABLE_FAST_INTERP != 0
10070-
emit_br_info(frame_csp_tmp);
10071-
#endif
1007210193

1007310194
*p_buf = p;
1007410195
return frame_csp_tmp;

0 commit comments

Comments
 (0)