Skip to content

Commit f31e5d3

Browse files
srberardlum1n0us
authored andcommitted
security: fixes parsing issue for invalid branch_hint sections
Signed-off-by: Stephen Berard <stephen.berard@outlook.com>
1 parent fe9db73 commit f31e5d3

1 file changed

Lines changed: 53 additions & 2 deletions

File tree

core/iwasm/interpreter/wasm_loader.c

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5567,6 +5567,27 @@ handle_name_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
55675567
#endif
55685568

55695569
#if WASM_ENABLE_BRANCH_HINTS != 0
5570+
/**
5571+
* Count the number of branch instructions for the specified function.
5572+
*/
5573+
static uint32
5574+
calculate_num_branch_instructions(const WASMFunction *func)
5575+
{
5576+
const uint8 *code = func->code;
5577+
const uint8 *code_end = code + func->code_size;
5578+
uint32 max_hints = 0;
5579+
5580+
while (code < code_end) {
5581+
uint8 opcode = *code++;
5582+
5583+
if (opcode == WASM_OP_IF || opcode == WASM_OP_BR_IF) {
5584+
max_hints++;
5585+
}
5586+
}
5587+
5588+
return max_hints;
5589+
}
5590+
55705591
static bool
55715592
handle_branch_hint_section(const uint8 *buf, const uint8 *buf_end,
55725593
WASMModule *module, char *error_buf,
@@ -5601,22 +5622,50 @@ handle_branch_hint_section(const uint8 *buf, const uint8 *buf_end,
56015622

56025623
uint32 num_hints;
56035624
read_leb_uint32(buf, buf_end, num_hints);
5625+
5626+
/* Ensure that num_hints doesn't exceed the actual number of branch instructions */
5627+
WASMFunction *func =
5628+
module->functions[func_idx - module->import_function_count];
5629+
uint32 max_branch_instructions =
5630+
calculate_num_branch_instructions(func);
5631+
if (num_hints > max_branch_instructions) {
5632+
set_error_buf_v(
5633+
error_buf, error_buf_size,
5634+
"invalid number of branch hints: expected at most %u, got %u",
5635+
max_branch_instructions, num_hints);
5636+
goto fail;
5637+
}
5638+
56045639
struct WASMCompilationHintBranchHint *new_hints = loader_malloc(
56055640
sizeof(struct WASMCompilationHintBranchHint) * num_hints, error_buf,
56065641
error_buf_size);
5642+
if (!new_hints) {
5643+
goto fail;
5644+
}
56075645
for (uint32 j = 0; j < num_hints; ++j) {
56085646
struct WASMCompilationHintBranchHint *new_hint = &new_hints[j];
56095647
new_hint->next = NULL;
56105648
new_hint->type = WASM_COMPILATION_BRANCH_HINT;
56115649
read_leb_uint32(buf, buf_end, new_hint->offset);
56125650

5651+
/* Validate offset is within the function's code bounds */
5652+
if (new_hint->offset >= func->code_size) {
5653+
set_error_buf_v(error_buf, error_buf_size,
5654+
"invalid branch hint offset: %u exceeds function "
5655+
"code size %u",
5656+
new_hint->offset, func->code_size);
5657+
goto fail;
5658+
}
5659+
56135660
uint32 size;
56145661
read_leb_uint32(buf, buf_end, size);
56155662
if (size != 1) {
56165663
set_error_buf_v(error_buf, error_buf_size,
56175664
"invalid branch hint size, expected 1, got %d.",
56185665
size);
5619-
wasm_runtime_free(new_hint);
5666+
/* Do not free new_hints here - any hints already linked into
5667+
* the module structure will be freed during module cleanup.
5668+
* Freeing here would cause a double-free. */
56205669
goto fail;
56215670
}
56225671

@@ -5629,7 +5678,9 @@ handle_branch_hint_section(const uint8 *buf, const uint8 *buf_end,
56295678
set_error_buf_v(error_buf, error_buf_size,
56305679
"invalid branch hint, expected 0 or 1, got %d",
56315680
data);
5632-
wasm_runtime_free(new_hint);
5681+
/* Do not free new_hints here - any hints already linked into
5682+
* the module structure will be freed during module cleanup.
5683+
* Freeing here would cause a double-free. */
56335684
goto fail;
56345685
}
56355686

0 commit comments

Comments
 (0)