wasm loader: Fix pop invalid offset count when stack top is ANY (#3516)
In wasm_loader_pop_frame_offset, when the stack is in polymorphic state and the stack top operand is VALUE_TYPE_ANY, if we popping I64/F64 operand, we should pop one offset but not two offsets. The issue was reported in #3513 and #3514.
This commit is contained in:
@ -9370,42 +9370,41 @@ wasm_loader_pop_frame_offset(WASMLoaderContext *ctx, uint8 type,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
/* if ctx->frame_csp equals ctx->frame_csp_bottom,
|
||||
then current block is the function block */
|
||||
then current block is the function block */
|
||||
uint32 depth = ctx->frame_csp > ctx->frame_csp_bottom ? 1 : 0;
|
||||
BranchBlock *cur_block = ctx->frame_csp - depth;
|
||||
int32 available_stack_cell =
|
||||
(int32)(ctx->stack_cell_num - cur_block->stack_cell_num);
|
||||
uint32 cell_num_to_pop;
|
||||
|
||||
/* Directly return success if current block is in stack
|
||||
* polymorphic state while stack is empty. */
|
||||
polymorphic state while stack is empty. */
|
||||
if (available_stack_cell <= 0 && cur_block->is_stack_polymorphic)
|
||||
return true;
|
||||
|
||||
if (type == VALUE_TYPE_VOID)
|
||||
return true;
|
||||
|
||||
if (is_32bit_type(type)) {
|
||||
/* Check the offset stack bottom to ensure the frame offset
|
||||
stack will not go underflow. But we don't thrown error
|
||||
and return true here, because the error msg should be
|
||||
given in wasm_loader_pop_frame_ref */
|
||||
if (!check_offset_pop(ctx, 1))
|
||||
return true;
|
||||
/* Change type to ANY when the stack top is ANY, so as to avoid
|
||||
popping unneeded offsets, e.g. if type is I64/F64, we may pop
|
||||
two offsets */
|
||||
if (available_stack_cell > 0 && *(ctx->frame_ref - 1) == VALUE_TYPE_ANY)
|
||||
type = VALUE_TYPE_ANY;
|
||||
|
||||
ctx->frame_offset -= 1;
|
||||
if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
|
||||
&& (*(ctx->frame_offset) < ctx->max_dynamic_offset))
|
||||
ctx->dynamic_offset -= 1;
|
||||
}
|
||||
else {
|
||||
if (!check_offset_pop(ctx, 2))
|
||||
return true;
|
||||
cell_num_to_pop = wasm_value_type_cell_num(type);
|
||||
|
||||
/* Check the offset stack bottom to ensure the frame offset
|
||||
stack will not go underflow. But we don't thrown error
|
||||
and return true here, because the error msg should be
|
||||
given in wasm_loader_pop_frame_ref */
|
||||
if (!check_offset_pop(ctx, cell_num_to_pop))
|
||||
return true;
|
||||
|
||||
ctx->frame_offset -= cell_num_to_pop;
|
||||
if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
|
||||
&& (*(ctx->frame_offset) < ctx->max_dynamic_offset))
|
||||
ctx->dynamic_offset -= cell_num_to_pop;
|
||||
|
||||
ctx->frame_offset -= 2;
|
||||
if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
|
||||
&& (*(ctx->frame_offset) < ctx->max_dynamic_offset))
|
||||
ctx->dynamic_offset -= 2;
|
||||
}
|
||||
emit_operand(ctx, *(ctx->frame_offset));
|
||||
|
||||
(void)error_buf;
|
||||
@ -10893,6 +10892,12 @@ wasm_loader_get_custom_section(WASMModule *module, const char *name,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define HANDLE_OPCODE(opcode) #opcode
|
||||
DEFINE_GOTO_TABLE(const char *, op_mnemonics);
|
||||
#undef HANDLE_OPCODE
|
||||
#endif
|
||||
|
||||
static bool
|
||||
wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
|
||||
uint32 cur_func_idx, char *error_buf,
|
||||
|
||||
@ -4924,43 +4924,45 @@ wasm_loader_pop_frame_offset(WASMLoaderContext *ctx, uint8 type,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
/* if ctx->frame_csp equals ctx->frame_csp_bottom,
|
||||
then current block is the function block */
|
||||
then current block is the function block */
|
||||
uint32 depth = ctx->frame_csp > ctx->frame_csp_bottom ? 1 : 0;
|
||||
BranchBlock *cur_block = ctx->frame_csp - depth;
|
||||
int32 available_stack_cell =
|
||||
(int32)(ctx->stack_cell_num - cur_block->stack_cell_num);
|
||||
uint32 cell_num_to_pop;
|
||||
|
||||
/* Directly return success if current block is in stack
|
||||
* polymorphic state while stack is empty. */
|
||||
polymorphic state while stack is empty. */
|
||||
if (available_stack_cell <= 0 && cur_block->is_stack_polymorphic)
|
||||
return true;
|
||||
|
||||
if (type == VALUE_TYPE_VOID)
|
||||
return true;
|
||||
|
||||
if (is_32bit_type(type)) {
|
||||
/* Check the offset stack bottom to ensure the frame offset
|
||||
stack will not go underflow. But we don't thrown error
|
||||
and return true here, because the error msg should be
|
||||
given in wasm_loader_pop_frame_ref */
|
||||
if (!check_offset_pop(ctx, 1))
|
||||
return true;
|
||||
/* Change type to ANY when the stack top is ANY, so as to avoid
|
||||
popping unneeded offsets, e.g. if type is I64/F64, we may pop
|
||||
two offsets */
|
||||
if (available_stack_cell > 0 && *(ctx->frame_ref - 1) == VALUE_TYPE_ANY)
|
||||
type = VALUE_TYPE_ANY;
|
||||
|
||||
ctx->frame_offset -= 1;
|
||||
if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
|
||||
&& (*(ctx->frame_offset) < ctx->max_dynamic_offset))
|
||||
ctx->dynamic_offset -= 1;
|
||||
}
|
||||
else {
|
||||
if (!check_offset_pop(ctx, 2))
|
||||
return true;
|
||||
cell_num_to_pop = wasm_value_type_cell_num(type);
|
||||
|
||||
/* Check the offset stack bottom to ensure the frame offset
|
||||
stack will not go underflow. But we don't thrown error
|
||||
and return true here, because the error msg should be
|
||||
given in wasm_loader_pop_frame_ref */
|
||||
if (!check_offset_pop(ctx, cell_num_to_pop))
|
||||
return true;
|
||||
|
||||
ctx->frame_offset -= cell_num_to_pop;
|
||||
if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
|
||||
&& (*(ctx->frame_offset) < ctx->max_dynamic_offset))
|
||||
ctx->dynamic_offset -= cell_num_to_pop;
|
||||
|
||||
ctx->frame_offset -= 2;
|
||||
if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
|
||||
&& (*(ctx->frame_offset) < ctx->max_dynamic_offset))
|
||||
ctx->dynamic_offset -= 2;
|
||||
}
|
||||
emit_operand(ctx, *(ctx->frame_offset));
|
||||
|
||||
(void)error_buf;
|
||||
(void)error_buf_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
BIN
tests/regression/ba-issues/issues/issue-3513/iwasm_poc_04.wasm
Normal file
BIN
tests/regression/ba-issues/issues/issue-3513/iwasm_poc_04.wasm
Normal file
Binary file not shown.
BIN
tests/regression/ba-issues/issues/issue-3514/iwasm_poc_05.wasm
Normal file
BIN
tests/regression/ba-issues/issues/issue-3514/iwasm_poc_05.wasm
Normal file
Binary file not shown.
@ -1722,6 +1722,38 @@
|
||||
"stdout content": "WASM module load failed: data count and data section have inconsistent lengths",
|
||||
"description": "Check data segment count"
|
||||
}
|
||||
},
|
||||
{
|
||||
"deprecated": false,
|
||||
"ids": [
|
||||
3513
|
||||
],
|
||||
"runtime": "iwasm-default-wasi-disabled",
|
||||
"file": "iwasm_poc_04.wasm",
|
||||
"mode": "fast-interp",
|
||||
"options": "-f main",
|
||||
"argument": "",
|
||||
"expected return": {
|
||||
"ret code": 0,
|
||||
"stdout content": "",
|
||||
"description": "no sanitizer 'heap-buffer-overflow'"
|
||||
}
|
||||
},
|
||||
{
|
||||
"deprecated": false,
|
||||
"ids": [
|
||||
3514
|
||||
],
|
||||
"runtime": "iwasm-default-wasi-disabled",
|
||||
"file": "iwasm_poc_05.wasm",
|
||||
"mode": "fast-interp",
|
||||
"options": "-f main",
|
||||
"argument": "",
|
||||
"expected return": {
|
||||
"ret code": 0,
|
||||
"stdout content": "",
|
||||
"description": "no sanitizer 'heap-buffer-overflow'"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user