Clone data segments when specified with load args (#3463)

Follow-up on https://github.com/bytecodealliance/wasm-micro-runtime/pull/3389, specifically: https://github.com/bytecodealliance/wasm-micro-runtime/pull/3389#discussion_r1600872451

If we want to free the wasm binary buffer early, we need to clone the data segments into the module.
That's because, in case of [passive data segments](https://webassembly.github.io/threads/core/syntax/modules.html#syntax-data),
they can be referred during wasm execution.
This commit is contained in:
Enrico Loparco
2024-05-27 03:59:24 +02:00
committed by GitHub
parent f378edc408
commit 3b8ef89110
9 changed files with 81 additions and 60 deletions

View File

@ -1740,8 +1740,8 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
static bool
load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
WASMModule *module, char *error_buf,
uint32 error_buf_size)
WASMModule *module, bool clone_data_seg,
char *error_buf, uint32 error_buf_size)
{
const uint8 *p = buf, *p_end = buf_end;
uint32 data_seg_count, i, mem_index, data_seg_len;
@ -1851,7 +1851,19 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
dataseg->data_length = data_seg_len;
CHECK_BUF(p, p_end, data_seg_len);
dataseg->data = (uint8 *)p;
if (clone_data_seg) {
if (!(dataseg->data = loader_malloc(
dataseg->data_length, error_buf, error_buf_size))) {
return false;
}
bh_memcpy_s(dataseg->data, dataseg->data_length, p,
data_seg_len);
}
else {
dataseg->data = (uint8 *)p;
}
dataseg->is_data_cloned = clone_data_seg;
p += data_seg_len;
}
}
@ -2549,8 +2561,8 @@ static void **handle_table;
static bool
load_from_sections(WASMModule *module, WASMSection *sections,
bool is_load_from_file_buf, char *error_buf,
uint32 error_buf_size)
bool is_load_from_file_buf, bool wasm_binary_freeable,
char *error_buf, uint32 error_buf_size)
{
WASMExport *export;
WASMSection *section = sections;
@ -2565,6 +2577,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
uint32 aux_heap_base_global_index = (uint32)-1;
WASMFuncType *func_type;
uint8 malloc_free_io_type = VALUE_TYPE_I32;
bool reuse_const_strings = is_load_from_file_buf && !wasm_binary_freeable;
bool clone_data_seg = is_load_from_file_buf && wasm_binary_freeable;
/* Find code and function sections if have */
while (section) {
@ -2588,7 +2602,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
case SECTION_TYPE_USER:
/* unsupported user section, ignore it. */
if (!load_user_section(buf, buf_end, module,
is_load_from_file_buf, error_buf,
reuse_const_strings, error_buf,
error_buf_size))
return false;
break;
@ -2599,7 +2613,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
break;
case SECTION_TYPE_IMPORT:
if (!load_import_section(buf, buf_end, module,
is_load_from_file_buf, error_buf,
reuse_const_strings, error_buf,
error_buf_size))
return false;
break;
@ -2625,7 +2639,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
break;
case SECTION_TYPE_EXPORT:
if (!load_export_section(buf, buf_end, module,
is_load_from_file_buf, error_buf,
reuse_const_strings, error_buf,
error_buf_size))
return false;
break;
@ -2645,7 +2659,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
return false;
break;
case SECTION_TYPE_DATA:
if (!load_data_segment_section(buf, buf_end, module, error_buf,
if (!load_data_segment_section(buf, buf_end, module,
clone_data_seg, error_buf,
error_buf_size))
return false;
break;
@ -3038,7 +3053,7 @@ wasm_loader_load_from_sections(WASMSection *section_list, char *error_buf,
if (!module)
return NULL;
if (!load_from_sections(module, section_list, false, error_buf,
if (!load_from_sections(module, section_list, false, true, error_buf,
error_buf_size)) {
wasm_loader_unload(module);
return NULL;
@ -3193,7 +3208,7 @@ load(const uint8 *buf, uint32 size, WASMModule *module,
}
if (!create_sections(buf, size, &section_list, error_buf, error_buf_size)
|| !load_from_sections(module, section_list, !wasm_binary_freeable,
|| !load_from_sections(module, section_list, true, wasm_binary_freeable,
error_buf, error_buf_size)) {
destroy_sections(section_list);
return false;
@ -3332,8 +3347,11 @@ wasm_loader_unload(WASMModule *module)
if (module->data_segments) {
for (i = 0; i < module->data_seg_count; i++) {
if (module->data_segments[i])
if (module->data_segments[i]) {
if (module->data_segments[i]->is_data_cloned)
wasm_runtime_free(module->data_segments[i]->data);
wasm_runtime_free(module->data_segments[i]);
}
}
wasm_runtime_free(module->data_segments);
}