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)
|
char *error_buf, uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
/* if ctx->frame_csp equals ctx->frame_csp_bottom,
|
/* 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;
|
uint32 depth = ctx->frame_csp > ctx->frame_csp_bottom ? 1 : 0;
|
||||||
BranchBlock *cur_block = ctx->frame_csp - depth;
|
BranchBlock *cur_block = ctx->frame_csp - depth;
|
||||||
int32 available_stack_cell =
|
int32 available_stack_cell =
|
||||||
(int32)(ctx->stack_cell_num - cur_block->stack_cell_num);
|
(int32)(ctx->stack_cell_num - cur_block->stack_cell_num);
|
||||||
|
uint32 cell_num_to_pop;
|
||||||
|
|
||||||
/* Directly return success if current block is in stack
|
/* 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)
|
if (available_stack_cell <= 0 && cur_block->is_stack_polymorphic)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (type == VALUE_TYPE_VOID)
|
if (type == VALUE_TYPE_VOID)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (is_32bit_type(type)) {
|
/* Change type to ANY when the stack top is ANY, so as to avoid
|
||||||
/* Check the offset stack bottom to ensure the frame offset
|
popping unneeded offsets, e.g. if type is I64/F64, we may pop
|
||||||
stack will not go underflow. But we don't thrown error
|
two offsets */
|
||||||
and return true here, because the error msg should be
|
if (available_stack_cell > 0 && *(ctx->frame_ref - 1) == VALUE_TYPE_ANY)
|
||||||
given in wasm_loader_pop_frame_ref */
|
type = VALUE_TYPE_ANY;
|
||||||
if (!check_offset_pop(ctx, 1))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
ctx->frame_offset -= 1;
|
cell_num_to_pop = wasm_value_type_cell_num(type);
|
||||||
if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
|
|
||||||
&& (*(ctx->frame_offset) < ctx->max_dynamic_offset))
|
/* Check the offset stack bottom to ensure the frame offset
|
||||||
ctx->dynamic_offset -= 1;
|
stack will not go underflow. But we don't thrown error
|
||||||
}
|
and return true here, because the error msg should be
|
||||||
else {
|
given in wasm_loader_pop_frame_ref */
|
||||||
if (!check_offset_pop(ctx, 2))
|
if (!check_offset_pop(ctx, cell_num_to_pop))
|
||||||
return true;
|
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));
|
emit_operand(ctx, *(ctx->frame_offset));
|
||||||
|
|
||||||
(void)error_buf;
|
(void)error_buf;
|
||||||
@ -10893,6 +10892,12 @@ wasm_loader_get_custom_section(WASMModule *module, const char *name,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define HANDLE_OPCODE(opcode) #opcode
|
||||||
|
DEFINE_GOTO_TABLE(const char *, op_mnemonics);
|
||||||
|
#undef HANDLE_OPCODE
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
|
wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
|
||||||
uint32 cur_func_idx, char *error_buf,
|
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)
|
char *error_buf, uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
/* if ctx->frame_csp equals ctx->frame_csp_bottom,
|
/* 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;
|
uint32 depth = ctx->frame_csp > ctx->frame_csp_bottom ? 1 : 0;
|
||||||
BranchBlock *cur_block = ctx->frame_csp - depth;
|
BranchBlock *cur_block = ctx->frame_csp - depth;
|
||||||
int32 available_stack_cell =
|
int32 available_stack_cell =
|
||||||
(int32)(ctx->stack_cell_num - cur_block->stack_cell_num);
|
(int32)(ctx->stack_cell_num - cur_block->stack_cell_num);
|
||||||
|
uint32 cell_num_to_pop;
|
||||||
|
|
||||||
/* Directly return success if current block is in stack
|
/* 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)
|
if (available_stack_cell <= 0 && cur_block->is_stack_polymorphic)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (type == VALUE_TYPE_VOID)
|
if (type == VALUE_TYPE_VOID)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (is_32bit_type(type)) {
|
/* Change type to ANY when the stack top is ANY, so as to avoid
|
||||||
/* Check the offset stack bottom to ensure the frame offset
|
popping unneeded offsets, e.g. if type is I64/F64, we may pop
|
||||||
stack will not go underflow. But we don't thrown error
|
two offsets */
|
||||||
and return true here, because the error msg should be
|
if (available_stack_cell > 0 && *(ctx->frame_ref - 1) == VALUE_TYPE_ANY)
|
||||||
given in wasm_loader_pop_frame_ref */
|
type = VALUE_TYPE_ANY;
|
||||||
if (!check_offset_pop(ctx, 1))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
ctx->frame_offset -= 1;
|
cell_num_to_pop = wasm_value_type_cell_num(type);
|
||||||
if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
|
|
||||||
&& (*(ctx->frame_offset) < ctx->max_dynamic_offset))
|
/* Check the offset stack bottom to ensure the frame offset
|
||||||
ctx->dynamic_offset -= 1;
|
stack will not go underflow. But we don't thrown error
|
||||||
}
|
and return true here, because the error msg should be
|
||||||
else {
|
given in wasm_loader_pop_frame_ref */
|
||||||
if (!check_offset_pop(ctx, 2))
|
if (!check_offset_pop(ctx, cell_num_to_pop))
|
||||||
return true;
|
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));
|
emit_operand(ctx, *(ctx->frame_offset));
|
||||||
|
|
||||||
|
(void)error_buf;
|
||||||
|
(void)error_buf_size;
|
||||||
return true;
|
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",
|
"stdout content": "WASM module load failed: data count and data section have inconsistent lengths",
|
||||||
"description": "Check data segment count"
|
"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