Reformat the code according with coding style rules.

This commit is contained in:
Costin Stefan 2026-03-26 00:04:10 +02:00
parent 81cbeb2fd7
commit 29312521d0
30 changed files with 5502 additions and 2618 deletions

View File

@ -53,9 +53,9 @@ bh_static_assert(offsetof(AOTModuleInstance, c_api_func_imports)
bh_static_assert(offsetof(AOTModuleInstance, global_table_data) bh_static_assert(offsetof(AOTModuleInstance, global_table_data)
== 13 * sizeof(uint64) + 128 + 14 * sizeof(uint64) == 13 * sizeof(uint64) + 128 + 14 * sizeof(uint64)
#if WASM_ENABLE_COMPONENT_MODEL != 0 #if WASM_ENABLE_COMPONENT_MODEL != 0
+ sizeof(void *) + sizeof(uint64) + sizeof(void *) + sizeof(uint64)
#endif #endif
); );
bh_static_assert(sizeof(AOTMemoryInstance) == 120); bh_static_assert(sizeof(AOTMemoryInstance) == 120);
bh_static_assert(offsetof(AOTTableInstance, elems) == 24); bh_static_assert(offsetof(AOTTableInstance, elems) == 24);

View File

@ -14,8 +14,13 @@
#include <stdio.h> #include <stdio.h>
// Parse all sections in a WASM component binary // Parse all sections in a WASM component binary
// Each section is dispatched to its own parser and stored in the output structure // Each section is dispatched to its own parser and stored in the output
bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMComponent *out_component, LoadArgs *args, unsigned int depth) { // structure
bool
wasm_component_parse_sections(const uint8_t *buf, uint32_t size,
WASMComponent *out_component, LoadArgs *args,
unsigned int depth)
{
if (!buf || size < 8 || !out_component) { if (!buf || size < 8 || !out_component) {
return false; return false;
} }
@ -30,7 +35,8 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
const uint8_t *end = buf + size; const uint8_t *end = buf + size;
uint32_t section_capacity = 8; uint32_t section_capacity = 8;
WASMComponentSection *sections = wasm_runtime_malloc(section_capacity * sizeof(WASMComponentSection)); WASMComponentSection *sections =
wasm_runtime_malloc(section_capacity * sizeof(WASMComponentSection));
if (!sections) { if (!sections) {
return false; return false;
} }
@ -43,8 +49,8 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
// Read payload length // Read payload length
uint64 payload_len = 0; uint64 payload_len = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &payload_len, if (!read_leb((uint8_t **)&p, end, 32, false, &payload_len, error_buf,
error_buf, sizeof(error_buf))) { sizeof(error_buf))) {
wasm_runtime_free(sections); wasm_runtime_free(sections);
return false; // Error handling return false; // Error handling
} }
@ -57,7 +63,8 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
// Store section info // Store section info
if (section_count == section_capacity) { if (section_count == section_capacity) {
section_capacity *= 2; section_capacity *= 2;
WASMComponentSection *new_sections = wasm_runtime_realloc(sections, section_capacity * sizeof(WASMComponentSection)); WASMComponentSection *new_sections = wasm_runtime_realloc(
sections, section_capacity * sizeof(WASMComponentSection));
if (!new_sections) { if (!new_sections) {
wasm_runtime_free(sections); wasm_runtime_free(sections);
return false; return false;
@ -70,77 +77,109 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
sections[current_section_index].payload = payload_start; sections[current_section_index].payload = payload_start;
sections[current_section_index].payload_len = (uint32_t)payload_len; sections[current_section_index].payload_len = (uint32_t)payload_len;
sections[current_section_index].id = section_id; sections[current_section_index].id = section_id;
sections[current_section_index].parsed.any = NULL; // Initialize parsed union to NULL sections[current_section_index].parsed.any =
NULL; // Initialize parsed union to NULL
section_count++; section_count++;
uint32_t consumed_len = 0; uint32_t consumed_len = 0;
bool parse_success = false; bool parse_success = false;
// LOG_DEBUG("Parsing section: %d | Section size: %d | payload_start: %d\n", section_id, payload_len, payload_start-begin); // LOG_DEBUG("Parsing section: %d | Section size: %d | payload_start:
// %d\n", section_id, payload_len, payload_start-begin);
switch (section_id) { switch (section_id) {
// Section 0: custom section // Section 0: custom section
case WASM_COMP_SECTION_CORE_CUSTOM: { case WASM_COMP_SECTION_CORE_CUSTOM:
{
// Parse custom section (name + data) // Parse custom section (name + data)
WASMComponentCoreCustomSection *custom = wasm_runtime_malloc(sizeof(WASMComponentCoreCustomSection)); WASMComponentCoreCustomSection *custom =
if (custom) memset(custom, 0, sizeof(WASMComponentCoreCustomSection)); wasm_runtime_malloc(sizeof(WASMComponentCoreCustomSection));
if (custom)
memset(custom, 0, sizeof(WASMComponentCoreCustomSection));
parse_success = wasm_component_parse_core_custom_section(&p, (uint32_t)payload_len, custom, error_buf, sizeof(error_buf), &consumed_len); parse_success = wasm_component_parse_core_custom_section(
&p, (uint32_t)payload_len, custom, error_buf,
sizeof(error_buf), &consumed_len);
if (!parse_success || consumed_len != payload_len) { if (!parse_success || consumed_len != payload_len) {
if (custom) { if (custom) {
wasm_runtime_free(custom); wasm_runtime_free(custom);
} }
if (error_buf[0]) { if (error_buf[0]) {
LOG_DEBUG("Error parsing custom section: %s\n", error_buf); LOG_DEBUG("Error parsing custom section: %s\n",
error_buf);
} }
if (consumed_len != payload_len) { if (consumed_len != payload_len) {
LOG_DEBUG("FATAL ERROR: Custom section consumed %u bytes but expected %lu\n", consumed_len, payload_len); LOG_DEBUG("FATAL ERROR: Custom section consumed %u "
"bytes but expected %lu\n",
consumed_len, payload_len);
wasm_runtime_free(sections); wasm_runtime_free(sections);
return false; return false;
} }
} else { }
else {
sections[current_section_index].parsed.core_custom = custom; sections[current_section_index].parsed.core_custom = custom;
} }
break; break;
} }
// Section 1: module section // Section 1: module section
case WASM_COMP_SECTION_CORE_MODULE: { case WASM_COMP_SECTION_CORE_MODULE:
{
// Parse and load the embedded core wasm module // Parse and load the embedded core wasm module
WASMComponentCoreModuleWrapper *module = wasm_runtime_malloc(sizeof(WASMComponentCoreModuleWrapper)); WASMComponentCoreModuleWrapper *module =
if (module) memset(module, 0, sizeof(WASMComponentCoreModuleWrapper)); wasm_runtime_malloc(sizeof(WASMComponentCoreModuleWrapper));
parse_success = wasm_component_parse_core_module_section(&payload_start, (uint32_t)payload_len, module, args, error_buf, sizeof(error_buf),&consumed_len); if (module)
memset(module, 0, sizeof(WASMComponentCoreModuleWrapper));
parse_success = wasm_component_parse_core_module_section(
&payload_start, (uint32_t)payload_len, module, args,
error_buf, sizeof(error_buf), &consumed_len);
if (!parse_success || consumed_len != payload_len) { if (!parse_success || consumed_len != payload_len) {
if (module) { if (module) {
wasm_runtime_free(module); wasm_runtime_free(module);
} }
if (error_buf[0]) { if (error_buf[0]) {
LOG_DEBUG("Error parsing module section: %s\n", error_buf); LOG_DEBUG("Error parsing module section: %s\n",
error_buf);
} }
if (consumed_len != payload_len) { if (consumed_len != payload_len) {
LOG_DEBUG("FATAL ERROR: Module section consumed %u bytes but expected %lu\n", consumed_len, payload_len); LOG_DEBUG("FATAL ERROR: Module section consumed %u "
"bytes but expected %lu\n",
consumed_len, payload_len);
wasm_runtime_free(sections); wasm_runtime_free(sections);
return false; return false;
} }
} else { }
else {
sections[current_section_index].parsed.core_module = module; sections[current_section_index].parsed.core_module = module;
} }
break; break;
} }
// Section 2: instance section // Section 2: instance section
case WASM_COMP_SECTION_CORE_INSTANCE: { case WASM_COMP_SECTION_CORE_INSTANCE:
WASMComponentCoreInstSection *core_instance_section = wasm_runtime_malloc(sizeof(WASMComponentCoreInstSection)); {
if (core_instance_section) memset(core_instance_section, 0, sizeof(WASMComponentCoreInstSection)); WASMComponentCoreInstSection *core_instance_section =
parse_success = wasm_component_parse_core_instance_section(&payload_start, (uint32_t)payload_len, core_instance_section, error_buf, sizeof(error_buf), &consumed_len); wasm_runtime_malloc(sizeof(WASMComponentCoreInstSection));
if (core_instance_section)
memset(core_instance_section, 0,
sizeof(WASMComponentCoreInstSection));
parse_success = wasm_component_parse_core_instance_section(
&payload_start, (uint32_t)payload_len,
core_instance_section, error_buf, sizeof(error_buf),
&consumed_len);
if (parse_success && consumed_len == payload_len) { if (parse_success && consumed_len == payload_len) {
sections[current_section_index].parsed.core_instance_section = core_instance_section; sections[current_section_index]
} else { .parsed.core_instance_section = core_instance_section;
}
else {
if (core_instance_section) { if (core_instance_section) {
wasm_runtime_free(core_instance_section); wasm_runtime_free(core_instance_section);
} }
if (error_buf[0]) { if (error_buf[0]) {
LOG_DEBUG("Error parsing core instances section: %s\n", error_buf); LOG_DEBUG("Error parsing core instances section: %s\n",
error_buf);
} }
if (consumed_len != payload_len) { if (consumed_len != payload_len) {
LOG_DEBUG("FATAL ERROR: Core Instances section consumed %u bytes but expected %lu\n", consumed_len, payload_len); LOG_DEBUG("FATAL ERROR: Core Instances section "
"consumed %u bytes but expected %lu\n",
consumed_len, payload_len);
wasm_runtime_free(sections); wasm_runtime_free(sections);
return false; return false;
} }
@ -148,21 +187,32 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
break; break;
} }
// Section 3: core types section // Section 3: core types section
case WASM_COMP_SECTION_CORE_TYPE: { case WASM_COMP_SECTION_CORE_TYPE:
WASMComponentCoreTypeSection *core_type_section = wasm_runtime_malloc(sizeof(WASMComponentCoreTypeSection)); {
if (core_type_section) memset(core_type_section, 0, sizeof(WASMComponentCoreTypeSection)); WASMComponentCoreTypeSection *core_type_section =
parse_success = wasm_component_parse_core_type_section(&payload_start, (uint32_t)payload_len, core_type_section, error_buf, sizeof(error_buf), &consumed_len); wasm_runtime_malloc(sizeof(WASMComponentCoreTypeSection));
if (core_type_section)
memset(core_type_section, 0,
sizeof(WASMComponentCoreTypeSection));
parse_success = wasm_component_parse_core_type_section(
&payload_start, (uint32_t)payload_len, core_type_section,
error_buf, sizeof(error_buf), &consumed_len);
if (parse_success && consumed_len == payload_len) { if (parse_success && consumed_len == payload_len) {
sections[current_section_index].parsed.core_type_section = core_type_section; sections[current_section_index].parsed.core_type_section =
} else { core_type_section;
}
else {
if (core_type_section) { if (core_type_section) {
wasm_runtime_free(core_type_section); wasm_runtime_free(core_type_section);
} }
if (error_buf[0]) { if (error_buf[0]) {
LOG_DEBUG("Error parsing core types section: %s\n", error_buf); LOG_DEBUG("Error parsing core types section: %s\n",
error_buf);
} }
if (consumed_len != payload_len) { if (consumed_len != payload_len) {
LOG_DEBUG("FATAL ERROR: Core types section consumed %u bytes but expected %lu\n", consumed_len, payload_len); LOG_DEBUG("FATAL ERROR: Core types section consumed %u "
"bytes but expected %lu\n",
consumed_len, payload_len);
wasm_runtime_free(sections); wasm_runtime_free(sections);
return false; return false;
} }
@ -170,11 +220,14 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
break; break;
} }
// Section 4: component section // Section 4: component section
case WASM_COMP_SECTION_COMPONENT: { case WASM_COMP_SECTION_COMPONENT:
{
// Parse and load the embedded component // Parse and load the embedded component
WASMComponent *component = wasm_runtime_malloc(sizeof(WASMComponent)); WASMComponent *component =
wasm_runtime_malloc(sizeof(WASMComponent));
if (!component) { if (!component) {
LOG_DEBUG("Failed to allocate memory for nested component\n"); LOG_DEBUG(
"Failed to allocate memory for nested component\n");
wasm_runtime_free(sections); wasm_runtime_free(sections);
return false; return false;
} }
@ -182,37 +235,56 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
memset(component, 0, sizeof(WASMComponent)); memset(component, 0, sizeof(WASMComponent));
// Parse the nested component sections directly from the payload // Parse the nested component sections directly from the payload
parse_success = wasm_component_parse_sections(payload_start, (uint32_t)payload_len, component, args, depth + 1); parse_success = wasm_component_parse_sections(
payload_start, (uint32_t)payload_len, component, args,
depth + 1);
consumed_len = payload_len; // The entire payload is consumed consumed_len = payload_len; // The entire payload is consumed
if (!parse_success) { if (!parse_success) {
LOG_DEBUG(" Failed to parse nested component, freeing component at %p\n", component); LOG_DEBUG(" Failed to parse nested component, freeing "
"component at %p\n",
component);
wasm_runtime_free(component); wasm_runtime_free(component);
LOG_DEBUG("Error parsing sub component section\n"); LOG_DEBUG("Error parsing sub component section\n");
wasm_runtime_free(sections); wasm_runtime_free(sections);
return false; return false;
} else { }
LOG_DEBUG(" Successfully parsed nested component at %p\n", component); else {
sections[current_section_index].parsed.component = component; LOG_DEBUG(
" Successfully parsed nested component at %p\n",
component);
sections[current_section_index].parsed.component =
component;
} }
break; break;
} }
// Section 5: instances section // Section 5: instances section
case WASM_COMP_SECTION_INSTANCES: { case WASM_COMP_SECTION_INSTANCES:
WASMComponentInstSection *instance_section = wasm_runtime_malloc(sizeof(WASMComponentInstSection)); {
if (instance_section) memset(instance_section, 0, sizeof(WASMComponentInstSection)); WASMComponentInstSection *instance_section =
parse_success = wasm_component_parse_instances_section(&payload_start, (uint32_t)payload_len, instance_section, error_buf, sizeof(error_buf), &consumed_len); wasm_runtime_malloc(sizeof(WASMComponentInstSection));
if (instance_section)
memset(instance_section, 0,
sizeof(WASMComponentInstSection));
parse_success = wasm_component_parse_instances_section(
&payload_start, (uint32_t)payload_len, instance_section,
error_buf, sizeof(error_buf), &consumed_len);
if (parse_success && consumed_len == payload_len) { if (parse_success && consumed_len == payload_len) {
sections[current_section_index].parsed.instance_section = instance_section; sections[current_section_index].parsed.instance_section =
} else { instance_section;
}
else {
if (instance_section) { if (instance_section) {
wasm_runtime_free(instance_section); wasm_runtime_free(instance_section);
} }
if (error_buf[0]) { if (error_buf[0]) {
LOG_DEBUG("Error parsing instances section: %s\n", error_buf); LOG_DEBUG("Error parsing instances section: %s\n",
error_buf);
} }
if (consumed_len != payload_len) { if (consumed_len != payload_len) {
LOG_DEBUG("FATAL ERROR: Instances section consumed %u bytes but expected %lu\n", consumed_len, payload_len); LOG_DEBUG("FATAL ERROR: Instances section consumed %u "
"bytes but expected %lu\n",
consumed_len, payload_len);
wasm_runtime_free(sections); wasm_runtime_free(sections);
return false; return false;
} }
@ -220,22 +292,32 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
break; break;
} }
// Section 6: aliases section for imports/exports // Section 6: aliases section for imports/exports
case WASM_COMP_SECTION_ALIASES: { case WASM_COMP_SECTION_ALIASES:
{
// Parse alias definitions for imports/exports // Parse alias definitions for imports/exports
WASMComponentAliasSection *alias_section = wasm_runtime_malloc(sizeof(WASMComponentAliasSection)); WASMComponentAliasSection *alias_section =
if (alias_section) memset(alias_section, 0, sizeof(WASMComponentAliasSection)); wasm_runtime_malloc(sizeof(WASMComponentAliasSection));
parse_success = wasm_component_parse_alias_section(&payload_start, (uint32_t)payload_len, alias_section, error_buf, sizeof(error_buf), &consumed_len); if (alias_section)
memset(alias_section, 0, sizeof(WASMComponentAliasSection));
parse_success = wasm_component_parse_alias_section(
&payload_start, (uint32_t)payload_len, alias_section,
error_buf, sizeof(error_buf), &consumed_len);
if (parse_success && consumed_len == payload_len) { if (parse_success && consumed_len == payload_len) {
sections[current_section_index].parsed.alias_section = alias_section; sections[current_section_index].parsed.alias_section =
} else { alias_section;
}
else {
if (alias_section) { if (alias_section) {
wasm_runtime_free(alias_section); wasm_runtime_free(alias_section);
} }
if (error_buf[0]) { if (error_buf[0]) {
LOG_DEBUG("Error parsing alias section: %s\n", error_buf); LOG_DEBUG("Error parsing alias section: %s\n",
error_buf);
} }
if (consumed_len != payload_len) { if (consumed_len != payload_len) {
LOG_DEBUG("FATAL ERROR: Alias section consumed %u bytes but expected %lu\n", consumed_len, payload_len); LOG_DEBUG("FATAL ERROR: Alias section consumed %u "
"bytes but expected %lu\n",
consumed_len, payload_len);
wasm_runtime_free(sections); wasm_runtime_free(sections);
return false; return false;
} }
@ -243,21 +325,31 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
break; break;
} }
// Section 7: types section // Section 7: types section
case WASM_COMP_SECTION_TYPE: { case WASM_COMP_SECTION_TYPE:
WASMComponentTypeSection *type_section = wasm_runtime_malloc(sizeof(WASMComponentTypeSection)); {
if (type_section) memset(type_section, 0, sizeof(WASMComponentTypeSection)); WASMComponentTypeSection *type_section =
parse_success = wasm_component_parse_types_section(&payload_start, (uint32_t)payload_len, type_section, error_buf, sizeof(error_buf), &consumed_len); wasm_runtime_malloc(sizeof(WASMComponentTypeSection));
if (type_section)
memset(type_section, 0, sizeof(WASMComponentTypeSection));
parse_success = wasm_component_parse_types_section(
&payload_start, (uint32_t)payload_len, type_section,
error_buf, sizeof(error_buf), &consumed_len);
if (parse_success && consumed_len == payload_len) { if (parse_success && consumed_len == payload_len) {
sections[current_section_index].parsed.type_section = type_section; sections[current_section_index].parsed.type_section =
} else { type_section;
}
else {
if (type_section) { if (type_section) {
wasm_runtime_free(type_section); wasm_runtime_free(type_section);
} }
if (error_buf[0]) { if (error_buf[0]) {
LOG_DEBUG("Error parsing types section: %s\n", error_buf); LOG_DEBUG("Error parsing types section: %s\n",
error_buf);
} }
if (consumed_len != payload_len) { if (consumed_len != payload_len) {
LOG_DEBUG("FATAL ERROR: Types section consumed %u bytes but expected %lu\n", consumed_len, payload_len); LOG_DEBUG("FATAL ERROR: Types section consumed %u "
"bytes but expected %lu\n",
consumed_len, payload_len);
wasm_runtime_free(sections); wasm_runtime_free(sections);
return false; return false;
} }
@ -265,21 +357,31 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
break; break;
} }
// Section 8: canons section // Section 8: canons section
case WASM_COMP_SECTION_CANONS: { case WASM_COMP_SECTION_CANONS:
WASMComponentCanonSection *canon_section = wasm_runtime_malloc(sizeof(WASMComponentCanonSection)); {
if (canon_section) memset(canon_section, 0, sizeof(WASMComponentCanonSection)); WASMComponentCanonSection *canon_section =
parse_success = wasm_component_parse_canons_section(&payload_start, (uint32_t)payload_len, canon_section, error_buf, sizeof(error_buf), &consumed_len); wasm_runtime_malloc(sizeof(WASMComponentCanonSection));
if (canon_section)
memset(canon_section, 0, sizeof(WASMComponentCanonSection));
parse_success = wasm_component_parse_canons_section(
&payload_start, (uint32_t)payload_len, canon_section,
error_buf, sizeof(error_buf), &consumed_len);
if (parse_success && consumed_len == payload_len) { if (parse_success && consumed_len == payload_len) {
sections[current_section_index].parsed.canon_section = canon_section; sections[current_section_index].parsed.canon_section =
} else { canon_section;
}
else {
if (canon_section) { if (canon_section) {
wasm_runtime_free(canon_section); wasm_runtime_free(canon_section);
} }
if (error_buf[0]) { if (error_buf[0]) {
LOG_DEBUG("Error parsing canons section: %s\n", error_buf); LOG_DEBUG("Error parsing canons section: %s\n",
error_buf);
} }
if (consumed_len != payload_len) { if (consumed_len != payload_len) {
LOG_DEBUG("FATAL ERROR: Canons section consumed %u bytes but expected %lu\n", consumed_len, payload_len); LOG_DEBUG("FATAL ERROR: Canons section consumed %u "
"bytes but expected %lu\n",
consumed_len, payload_len);
wasm_runtime_free(sections); wasm_runtime_free(sections);
return false; return false;
} }
@ -287,21 +389,31 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
break; break;
} }
// Section 9: start section // Section 9: start section
case WASM_COMP_SECTION_START: { case WASM_COMP_SECTION_START:
WASMComponentStartSection *start_section = wasm_runtime_malloc(sizeof(WASMComponentStartSection)); {
if (start_section) memset(start_section, 0, sizeof(WASMComponentStartSection)); WASMComponentStartSection *start_section =
parse_success = wasm_component_parse_start_section(&payload_start, (uint32_t)payload_len, start_section, error_buf, sizeof(error_buf), &consumed_len); wasm_runtime_malloc(sizeof(WASMComponentStartSection));
if (start_section)
memset(start_section, 0, sizeof(WASMComponentStartSection));
parse_success = wasm_component_parse_start_section(
&payload_start, (uint32_t)payload_len, start_section,
error_buf, sizeof(error_buf), &consumed_len);
if (parse_success && consumed_len == payload_len) { if (parse_success && consumed_len == payload_len) {
sections[current_section_index].parsed.start_section = start_section; sections[current_section_index].parsed.start_section =
} else { start_section;
}
else {
if (start_section) { if (start_section) {
wasm_runtime_free(start_section); wasm_runtime_free(start_section);
} }
if (error_buf[0]) { if (error_buf[0]) {
LOG_DEBUG("Error parsing start section: %s\n", error_buf); LOG_DEBUG("Error parsing start section: %s\n",
error_buf);
} }
if (consumed_len != payload_len) { if (consumed_len != payload_len) {
LOG_DEBUG("FATAL ERROR: Start section consumed %u bytes but expected %lu\n", consumed_len, payload_len); LOG_DEBUG("FATAL ERROR: Start section consumed %u "
"bytes but expected %lu\n",
consumed_len, payload_len);
wasm_runtime_free(sections); wasm_runtime_free(sections);
return false; return false;
} }
@ -309,22 +421,34 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
break; break;
} }
// Section 10: imports section (component model imports) // Section 10: imports section (component model imports)
case WASM_COMP_SECTION_IMPORTS: { case WASM_COMP_SECTION_IMPORTS:
// Parse all imports: name (simple/versioned) and externdesc (all 6 types) {
WASMComponentImportSection *import_section = wasm_runtime_malloc(sizeof(WASMComponentImportSection)); // Parse all imports: name (simple/versioned) and externdesc
if (import_section) memset(import_section, 0, sizeof(WASMComponentImportSection)); // (all 6 types)
parse_success = wasm_component_parse_imports_section(&payload_start, (uint32_t)payload_len, import_section, error_buf, sizeof(error_buf), &consumed_len); WASMComponentImportSection *import_section =
wasm_runtime_malloc(sizeof(WASMComponentImportSection));
if (import_section)
memset(import_section, 0,
sizeof(WASMComponentImportSection));
parse_success = wasm_component_parse_imports_section(
&payload_start, (uint32_t)payload_len, import_section,
error_buf, sizeof(error_buf), &consumed_len);
if (parse_success && consumed_len == payload_len) { if (parse_success && consumed_len == payload_len) {
sections[current_section_index].parsed.import_section = import_section; sections[current_section_index].parsed.import_section =
} else { import_section;
}
else {
if (import_section) { if (import_section) {
wasm_runtime_free(import_section); wasm_runtime_free(import_section);
} }
if (error_buf[0]) { if (error_buf[0]) {
LOG_DEBUG("Error parsing imports section: %s\n", error_buf); LOG_DEBUG("Error parsing imports section: %s\n",
error_buf);
} }
if (consumed_len != payload_len) { if (consumed_len != payload_len) {
LOG_DEBUG("FATAL ERROR: Imports section consumed %u bytes but expected %lu\n", consumed_len, payload_len); LOG_DEBUG("FATAL ERROR: Imports section consumed %u "
"bytes but expected %lu\n",
consumed_len, payload_len);
wasm_runtime_free(sections); wasm_runtime_free(sections);
return false; return false;
} }
@ -332,21 +456,32 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
break; break;
} }
// Section 11: exports section // Section 11: exports section
case WASM_COMP_SECTION_EXPORTS: { case WASM_COMP_SECTION_EXPORTS:
WASMComponentExportSection *export_section = wasm_runtime_malloc(sizeof(WASMComponentExportSection)); {
if (export_section) memset(export_section, 0, sizeof(WASMComponentExportSection)); WASMComponentExportSection *export_section =
parse_success = wasm_component_parse_exports_section(&payload_start, (uint32_t)payload_len, export_section, error_buf, sizeof(error_buf), &consumed_len); wasm_runtime_malloc(sizeof(WASMComponentExportSection));
if (export_section)
memset(export_section, 0,
sizeof(WASMComponentExportSection));
parse_success = wasm_component_parse_exports_section(
&payload_start, (uint32_t)payload_len, export_section,
error_buf, sizeof(error_buf), &consumed_len);
if (parse_success && consumed_len == payload_len) { if (parse_success && consumed_len == payload_len) {
sections[current_section_index].parsed.export_section = export_section; sections[current_section_index].parsed.export_section =
} else { export_section;
}
else {
if (export_section) { if (export_section) {
wasm_runtime_free(export_section); wasm_runtime_free(export_section);
} }
if (error_buf[0]) { if (error_buf[0]) {
LOG_DEBUG("Error parsing export section: %s\n", error_buf); LOG_DEBUG("Error parsing export section: %s\n",
error_buf);
} }
if (consumed_len != payload_len) { if (consumed_len != payload_len) {
LOG_DEBUG("FATAL ERROR: Exports section consumed %u bytes but expected %lu\n", consumed_len, payload_len); LOG_DEBUG("FATAL ERROR: Exports section consumed %u "
"bytes but expected %lu\n",
consumed_len, payload_len);
wasm_runtime_free(sections); wasm_runtime_free(sections);
return false; return false;
} }
@ -354,21 +489,31 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
break; break;
} }
// Section 12: values section // Section 12: values section
case WASM_COMP_SECTION_VALUES: { case WASM_COMP_SECTION_VALUES:
WASMComponentValueSection *value_section = wasm_runtime_malloc(sizeof(WASMComponentValueSection)); {
if (value_section) memset(value_section, 0, sizeof(WASMComponentValueSection)); WASMComponentValueSection *value_section =
parse_success = wasm_component_parse_values_section(&payload_start, (uint32_t)payload_len, value_section, error_buf, sizeof(error_buf), &consumed_len); wasm_runtime_malloc(sizeof(WASMComponentValueSection));
if (value_section)
memset(value_section, 0, sizeof(WASMComponentValueSection));
parse_success = wasm_component_parse_values_section(
&payload_start, (uint32_t)payload_len, value_section,
error_buf, sizeof(error_buf), &consumed_len);
if (parse_success && consumed_len == payload_len) { if (parse_success && consumed_len == payload_len) {
sections[current_section_index].parsed.value_section = value_section; sections[current_section_index].parsed.value_section =
} else { value_section;
}
else {
if (value_section) { if (value_section) {
wasm_runtime_free(value_section); wasm_runtime_free(value_section);
} }
if (error_buf[0]) { if (error_buf[0]) {
LOG_DEBUG("Error parsing values section: %s\n", error_buf); LOG_DEBUG("Error parsing values section: %s\n",
error_buf);
} }
if (consumed_len != payload_len) { if (consumed_len != payload_len) {
LOG_DEBUG("FATAL ERROR: Values section consumed %u bytes but expected %lu\n", consumed_len, payload_len); LOG_DEBUG("FATAL ERROR: Values section consumed %u "
"bytes but expected %lu\n",
consumed_len, payload_len);
wasm_runtime_free(sections); wasm_runtime_free(sections);
return false; return false;
} }
@ -377,12 +522,13 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
} }
default: default:
// Unknown/unsupported section id // Unknown/unsupported section id
LOG_DEBUG("FATAL ERROR: Unknown/unsupported section (id=%u, size=%lu)\n", section_id, payload_len); LOG_DEBUG("FATAL ERROR: Unknown/unsupported section (id=%u, "
"size=%lu)\n",
section_id, payload_len);
wasm_runtime_free(sections); wasm_runtime_free(sections);
return false; return false;
} }
// Advance the main parser by the consumed amount // Advance the main parser by the consumed amount
p = payload_start + consumed_len; p = payload_start + consumed_len;
@ -399,10 +545,12 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
} }
// Check if Header is Component // Check if Header is Component
bool is_wasm_component(WASMHeader header) { bool
if (header.magic != WASM_MAGIC_NUMBER || is_wasm_component(WASMHeader header)
header.version != WASM_COMPONENT_VERSION || {
header.layer != WASM_COMPONENT_LAYER) { if (header.magic != WASM_MAGIC_NUMBER
|| header.version != WASM_COMPONENT_VERSION
|| header.layer != WASM_COMPONENT_LAYER) {
return false; return false;
} }
@ -410,62 +558,65 @@ bool is_wasm_component(WASMHeader header) {
} }
// Main component free function // Main component free function
void wasm_component_free(WASMComponent *component) { void
if (!component || !component->sections) return; wasm_component_free(WASMComponent *component)
{
if (!component || !component->sections)
return;
for (uint32_t i = 0; i < component->section_count; ++i) { for (uint32_t i = 0; i < component->section_count; ++i) {
WASMComponentSection *sec = &component->sections[i]; WASMComponentSection *sec = &component->sections[i];
switch (sec->id) { switch (sec->id) {
case WASM_COMP_SECTION_CORE_CUSTOM: // Section 0 case WASM_COMP_SECTION_CORE_CUSTOM: // Section 0
wasm_component_free_core_custom_section(sec); wasm_component_free_core_custom_section(sec);
break; break;
case WASM_COMP_SECTION_CORE_MODULE: // Section 1 case WASM_COMP_SECTION_CORE_MODULE: // Section 1
wasm_component_free_core_module_section(sec); wasm_component_free_core_module_section(sec);
break; break;
case WASM_COMP_SECTION_CORE_INSTANCE: // Section 2 case WASM_COMP_SECTION_CORE_INSTANCE: // Section 2
wasm_component_free_core_instance_section(sec); wasm_component_free_core_instance_section(sec);
break; break;
case WASM_COMP_SECTION_CORE_TYPE: // Section 3 case WASM_COMP_SECTION_CORE_TYPE: // Section 3
wasm_component_free_core_type_section(sec); wasm_component_free_core_type_section(sec);
break; break;
case WASM_COMP_SECTION_COMPONENT: // Section 4 case WASM_COMP_SECTION_COMPONENT: // Section 4
wasm_component_free_component_section(sec); wasm_component_free_component_section(sec);
break; break;
case WASM_COMP_SECTION_INSTANCES: // Section 5 case WASM_COMP_SECTION_INSTANCES: // Section 5
wasm_component_free_instances_section(sec); wasm_component_free_instances_section(sec);
break; break;
case WASM_COMP_SECTION_ALIASES: // Section 6 case WASM_COMP_SECTION_ALIASES: // Section 6
wasm_component_free_alias_section(sec); wasm_component_free_alias_section(sec);
break; break;
case WASM_COMP_SECTION_TYPE: // Section 7 case WASM_COMP_SECTION_TYPE: // Section 7
wasm_component_free_types_section(sec); wasm_component_free_types_section(sec);
break; break;
case WASM_COMP_SECTION_CANONS: // Section 8 case WASM_COMP_SECTION_CANONS: // Section 8
wasm_component_free_canons_section(sec); wasm_component_free_canons_section(sec);
break; break;
case WASM_COMP_SECTION_START: // Section 9 case WASM_COMP_SECTION_START: // Section 9
wasm_component_free_start_section(sec); wasm_component_free_start_section(sec);
break; break;
case WASM_COMP_SECTION_IMPORTS: // Section 10 case WASM_COMP_SECTION_IMPORTS: // Section 10
wasm_component_free_imports_section(sec); wasm_component_free_imports_section(sec);
break; break;
case WASM_COMP_SECTION_EXPORTS: // Section 11 case WASM_COMP_SECTION_EXPORTS: // Section 11
wasm_component_free_exports_section(sec); wasm_component_free_exports_section(sec);
break; break;
case WASM_COMP_SECTION_VALUES: // Section 12 case WASM_COMP_SECTION_VALUES: // Section 12
wasm_component_free_values_section(sec); wasm_component_free_values_section(sec);
break; break;

File diff suppressed because it is too large Load Diff

View File

@ -12,12 +12,17 @@
#include "wasm_export.h" #include "wasm_export.h"
#include <stdio.h> #include <stdio.h>
bool parse_single_alias(const uint8_t **payload, const uint8_t *end, WASMComponentAliasDefinition *out, char *error_buf, uint32_t error_buf_size) { bool
parse_single_alias(const uint8_t **payload, const uint8_t *end,
WASMComponentAliasDefinition *out, char *error_buf,
uint32_t error_buf_size)
{
const uint8_t *p = *payload; const uint8_t *p = *payload;
out->sort = wasm_runtime_malloc(sizeof(WASMComponentSort)); out->sort = wasm_runtime_malloc(sizeof(WASMComponentSort));
if (!out->sort) { if (!out->sort) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for alias sort"); set_error_buf_ex(error_buf, error_buf_size,
"Failed to allocate memory for alias sort");
return false; return false;
} }
@ -31,9 +36,11 @@ bool parse_single_alias(const uint8_t **payload, const uint8_t *end, WASMCompone
// Parse alias target using switch // Parse alias target using switch
switch (tag) { switch (tag) {
case WASM_COMP_ALIAS_TARGET_EXPORT: { case WASM_COMP_ALIAS_TARGET_EXPORT:
{
uint64_t instance_idx = 0; uint64_t instance_idx = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &instance_idx, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &instance_idx,
error_buf, error_buf_size)) {
return false; return false;
} }
WASMComponentCoreName *name = NULL; WASMComponentCoreName *name = NULL;
@ -45,27 +52,34 @@ bool parse_single_alias(const uint8_t **payload, const uint8_t *end, WASMCompone
out->target.exported.name = name; out->target.exported.name = name;
break; break;
} }
case WASM_COMP_ALIAS_TARGET_CORE_EXPORT: { case WASM_COMP_ALIAS_TARGET_CORE_EXPORT:
{
uint64_t core_instance_idx = 0; uint64_t core_instance_idx = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &core_instance_idx, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &core_instance_idx,
error_buf, error_buf_size)) {
return false; return false;
} }
WASMComponentCoreName *core_name = NULL; WASMComponentCoreName *core_name = NULL;
if (!parse_core_name(&p, end, &core_name, error_buf, error_buf_size)) { if (!parse_core_name(&p, end, &core_name, error_buf,
error_buf_size)) {
return false; return false;
} }
out->alias_target_type = WASM_COMP_ALIAS_TARGET_CORE_EXPORT; out->alias_target_type = WASM_COMP_ALIAS_TARGET_CORE_EXPORT;
out->target.core_exported.instance_idx = (uint32_t)core_instance_idx; out->target.core_exported.instance_idx =
(uint32_t)core_instance_idx;
out->target.core_exported.name = core_name; out->target.core_exported.name = core_name;
break; break;
} }
case WASM_COMP_ALIAS_TARGET_OUTER: { case WASM_COMP_ALIAS_TARGET_OUTER:
{
uint64_t outer_ct = 0; uint64_t outer_ct = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &outer_ct, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &outer_ct, error_buf,
error_buf_size)) {
return false; return false;
} }
uint64_t outer_idx = 0; uint64_t outer_idx = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &outer_idx, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &outer_idx, error_buf,
error_buf_size)) {
return false; return false;
} }
out->alias_target_type = WASM_COMP_ALIAS_TARGET_OUTER; out->alias_target_type = WASM_COMP_ALIAS_TARGET_OUTER;
@ -78,13 +92,16 @@ bool parse_single_alias(const uint8_t **payload, const uint8_t *end, WASMCompone
|| (out->sort->sort == WASM_COMP_SORT_CORE_SORT || (out->sort->sort == WASM_COMP_SORT_CORE_SORT
&& out->sort->core_sort == WASM_COMP_CORE_SORT_MODULE); && out->sort->core_sort == WASM_COMP_CORE_SORT_MODULE);
if (!valid_outer_sort) { if (!valid_outer_sort) {
set_error_buf_ex(error_buf, error_buf_size, "Outer alias sort must be type, component, or core module"); set_error_buf_ex(
error_buf, error_buf_size,
"Outer alias sort must be type, component, or core module");
return false; return false;
} }
break; break;
} }
default: default:
snprintf(error_buf, error_buf_size, "Unknown alias target type: 0x%02X", tag); snprintf(error_buf, error_buf_size,
"Unknown alias target type: 0x%02X", tag);
return false; return false;
} }
@ -93,10 +110,18 @@ bool parse_single_alias(const uint8_t **payload, const uint8_t *end, WASMCompone
} }
// Section 6: alias section // Section 6: alias section
bool wasm_component_parse_alias_section(const uint8_t **payload, uint32_t payload_len, WASMComponentAliasSection *out, char *error_buf, uint32_t error_buf_size, uint32_t *consumed_len) { bool
wasm_component_parse_alias_section(const uint8_t **payload,
uint32_t payload_len,
WASMComponentAliasSection *out,
char *error_buf, uint32_t error_buf_size,
uint32_t *consumed_len)
{
if (!payload || !*payload || payload_len == 0 || !out) { if (!payload || !*payload || payload_len == 0 || !out) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid payload or output pointer"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = 0; "Invalid payload or output pointer");
if (consumed_len)
*consumed_len = 0;
return false; return false;
} }
@ -106,8 +131,10 @@ bool wasm_component_parse_alias_section(const uint8_t **payload, uint32_t payloa
// Read alias count // Read alias count
uint64_t alias_count_leb = 0; uint64_t alias_count_leb = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &alias_count_leb, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &alias_count_leb, error_buf,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); error_buf_size)) {
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
@ -115,33 +142,43 @@ bool wasm_component_parse_alias_section(const uint8_t **payload, uint32_t payloa
out->count = alias_count; out->count = alias_count;
if (alias_count > 0) { if (alias_count > 0) {
out->aliases = wasm_runtime_malloc(sizeof(WASMComponentAliasDefinition) * alias_count); out->aliases = wasm_runtime_malloc(sizeof(WASMComponentAliasDefinition)
* alias_count);
if (!out->aliases) { if (!out->aliases) {
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Zero-initialize the aliases array // Zero-initialize the aliases array
memset(out->aliases, 0, sizeof(WASMComponentAliasDefinition) * alias_count); memset(out->aliases, 0,
sizeof(WASMComponentAliasDefinition) * alias_count);
for (uint32_t i = 0; i < alias_count; ++i) { for (uint32_t i = 0; i < alias_count; ++i) {
// Allocate memory for the sort field // Allocate memory for the sort field
if (!parse_single_alias(&p, end, &out->aliases[i], error_buf, error_buf_size)) { if (!parse_single_alias(&p, end, &out->aliases[i], error_buf,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to parse alias %d", i); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
set_error_buf_ex(error_buf, error_buf_size,
"Failed to parse alias %d", i);
return false; return false;
} }
} }
} }
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
// If binaries use alias ids, this parser will need to be extended. // If binaries use alias ids, this parser will need to be extended.
return true; return true;
} }
// Individual section free functions // Individual section free functions
void wasm_component_free_alias_section(WASMComponentSection *section) { void
if (!section || !section->parsed.alias_section) return; wasm_component_free_alias_section(WASMComponentSection *section)
{
if (!section || !section->parsed.alias_section)
return;
WASMComponentAliasSection *alias_sec = section->parsed.alias_section; WASMComponentAliasSection *alias_sec = section->parsed.alias_section;
if (alias_sec->aliases) { if (alias_sec->aliases) {

View File

@ -13,16 +13,26 @@
#include <stdio.h> #include <stdio.h>
// Section 4: component section // Section 4: component section
bool wasm_component_parse_component_section(const uint8_t **payload, uint32_t payload_len, WASMComponent *out, char *error_buf, uint32_t error_buf_size, LoadArgs *args, unsigned int depth, uint32_t *consumed_len) { bool
if (consumed_len) *consumed_len = 0; wasm_component_parse_component_section(const uint8_t **payload,
uint32_t payload_len, WASMComponent *out,
char *error_buf, uint32_t error_buf_size,
LoadArgs *args, unsigned int depth,
uint32_t *consumed_len)
{
if (consumed_len)
*consumed_len = 0;
if (!payload || !*payload || payload_len == 0 || !out) { if (!payload || !*payload || payload_len == 0 || !out) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid payload or output pointer"); set_error_buf_ex(error_buf, error_buf_size,
"Invalid payload or output pointer");
return false; return false;
} }
// Check depth limit BEFORE recursive call // Check depth limit BEFORE recursive call
if (depth >= MAX_DEPTH_RECURSION) { if (depth >= MAX_DEPTH_RECURSION) {
set_error_buf_ex(error_buf, error_buf_size, "Max depth of recursion for parsing component reached: %d", depth); set_error_buf_ex(
error_buf, error_buf_size,
"Max depth of recursion for parsing component reached: %d", depth);
return false; return false;
} }
@ -30,19 +40,26 @@ bool wasm_component_parse_component_section(const uint8_t **payload, uint32_t pa
unsigned int new_depth = depth + 1; unsigned int new_depth = depth + 1;
// Parse the nested component with incremented depth // Parse the nested component with incremented depth
bool status = wasm_component_parse_sections(*payload, payload_len, out, args, new_depth); bool status = wasm_component_parse_sections(*payload, payload_len, out,
args, new_depth);
if (!status) { if (!status) {
set_error_buf_ex(error_buf, error_buf_size, "Could not parse sub component with depth: %d", new_depth); set_error_buf_ex(error_buf, error_buf_size,
"Could not parse sub component with depth: %d",
new_depth);
return false; return false;
} }
if (consumed_len) *consumed_len = payload_len; if (consumed_len)
*consumed_len = payload_len;
return true; return true;
} }
// Individual section free functions // Individual section free functions
void wasm_component_free_component_section(WASMComponentSection *section) { void
if (!section || !section->parsed.component) return; wasm_component_free_component_section(WASMComponentSection *section)
{
if (!section || !section->parsed.component)
return;
// Recursively free nested components // Recursively free nested components
wasm_component_free(section->parsed.component); wasm_component_free(section->parsed.component);

View File

@ -14,14 +14,23 @@
#include <stdio.h> #include <stdio.h>
// Section 0: custom section // Section 0: custom section
bool wasm_component_parse_core_custom_section(const uint8_t **payload, uint32_t payload_len, WASMComponentCoreCustomSection *out, char *error_buf, uint32_t error_buf_size, uint32_t *consumed_len) { bool
wasm_component_parse_core_custom_section(const uint8_t **payload,
uint32_t payload_len,
WASMComponentCoreCustomSection *out,
char *error_buf,
uint32_t error_buf_size,
uint32_t *consumed_len)
{
if (out) { if (out) {
// Zero-initialize the output struct // Zero-initialize the output struct
memset(out, 0, sizeof(WASMComponentCoreCustomSection)); memset(out, 0, sizeof(WASMComponentCoreCustomSection));
} }
if (consumed_len) *consumed_len = 0; if (consumed_len)
*consumed_len = 0;
if (!payload || !*payload || payload_len == 0 || !out) { if (!payload || !*payload || payload_len == 0 || !out) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid payload or output pointer"); set_error_buf_ex(error_buf, error_buf_size,
"Invalid payload or output pointer");
return false; return false;
} }
@ -32,42 +41,51 @@ bool wasm_component_parse_core_custom_section(const uint8_t **payload, uint32_t
// Check bounds // Check bounds
if (p >= end) { if (p >= end) {
set_error_buf_ex(error_buf, error_buf_size, "unexpected end"); set_error_buf_ex(error_buf, error_buf_size, "unexpected end");
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Read name length, validate, and copy name // Read name length, validate, and copy name
uint64_t name_len_leb = 0; uint64_t name_len_leb = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &name_len_leb, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &name_len_leb, error_buf,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); error_buf_size)) {
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
name_len = (uint32_t)name_len_leb; name_len = (uint32_t)name_len_leb;
// Validate name length bounds // Validate name length bounds
if (name_len == 0) { if (name_len == 0) {
set_error_buf_ex(error_buf, error_buf_size, "Custom section name cannot be empty"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Custom section name cannot be empty");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
if (p + name_len > end) { if (p + name_len > end) {
set_error_buf_ex(error_buf, error_buf_size, "unexpected end"); set_error_buf_ex(error_buf, error_buf_size, "unexpected end");
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// UTF-8 validation (reuse the same logic as load_user_section) // UTF-8 validation (reuse the same logic as load_user_section)
if (!wasm_check_utf8_str(p, name_len)) { if (!wasm_check_utf8_str(p, name_len)) {
set_error_buf_ex(error_buf, error_buf_size, "invalid UTF-8 encoding"); set_error_buf_ex(error_buf, error_buf_size, "invalid UTF-8 encoding");
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Allocate and copy the section name // Allocate and copy the section name
out->name = (char *)wasm_runtime_malloc(name_len + 1); out->name = (char *)wasm_runtime_malloc(name_len + 1);
if (!out->name) { if (!out->name) {
set_error_buf_ex(error_buf, error_buf_size, "Memory allocation failed for custom section name"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Memory allocation failed for custom section name");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
@ -88,8 +106,11 @@ bool wasm_component_parse_core_custom_section(const uint8_t **payload, uint32_t
} }
// Individual section free functions // Individual section free functions
void wasm_component_free_core_custom_section(WASMComponentSection *section) { void
if (!section || !section->parsed.core_custom) return; wasm_component_free_core_custom_section(WASMComponentSection *section)
{
if (!section || !section->parsed.core_custom)
return;
if (section->parsed.core_custom->name) { if (section->parsed.core_custom->name) {
wasm_runtime_free(section->parsed.core_custom->name); wasm_runtime_free(section->parsed.core_custom->name);

View File

@ -12,14 +12,23 @@
#include "wasm_export.h" #include "wasm_export.h"
#include <stdio.h> #include <stdio.h>
// Section 2: core:instance ::= ie:<core:instanceexpr> => (instance ie) // Section 2: core:instance ::= ie:<core:instanceexpr> => (instance ie)
// core:instanceexpr ::= 0x00 m:<moduleidx> arg*:vec(<core:instantiatearg>) => (instantiate m arg*) // core:instanceexpr ::= 0x00 m:<moduleidx> arg*:vec(<core:instantiatearg>) =>
// core:instantiatearg ::= n:<core:name> 0x12 i:<instanceidx> => (with n (instance i)) // (instantiate m arg*) core:instantiatearg ::= n:<core:name> 0x12
bool wasm_component_parse_core_instance_section(const uint8_t **payload, uint32_t payload_len, WASMComponentCoreInstSection *out, char *error_buf, uint32_t error_buf_size, uint32_t *consumed_len) { // i:<instanceidx> => (with n (instance i))
bool
wasm_component_parse_core_instance_section(const uint8_t **payload,
uint32_t payload_len,
WASMComponentCoreInstSection *out,
char *error_buf,
uint32_t error_buf_size,
uint32_t *consumed_len)
{
if (!payload || !*payload || payload_len == 0 || !out) { if (!payload || !*payload || payload_len == 0 || !out) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid payload or output pointer"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = 0; "Invalid payload or output pointer");
if (consumed_len)
*consumed_len = 0;
return false; return false;
} }
@ -27,207 +36,301 @@ bool wasm_component_parse_core_instance_section(const uint8_t **payload, uint32_
const uint8_t *end = *payload + payload_len; const uint8_t *end = *payload + payload_len;
uint64_t instance_count = 0; uint64_t instance_count = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &instance_count, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &instance_count, error_buf,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); error_buf_size)) {
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
out->count = (uint32_t)instance_count; out->count = (uint32_t)instance_count;
if (instance_count > 0) { if (instance_count > 0) {
out->instances = wasm_runtime_malloc(sizeof(WASMComponentCoreInst) * instance_count); out->instances =
wasm_runtime_malloc(sizeof(WASMComponentCoreInst) * instance_count);
if (!out->instances) { if (!out->instances) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for core instances"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Failed to allocate memory for core instances");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Initialize all instances to zero to avoid garbage data // Initialize all instances to zero to avoid garbage data
memset(out->instances, 0, sizeof(WASMComponentCoreInst) * instance_count); memset(out->instances, 0,
sizeof(WASMComponentCoreInst) * instance_count);
for (uint32_t i = 0; i < instance_count; ++i) { for (uint32_t i = 0; i < instance_count; ++i) {
// Check bounds before reading tag // Check bounds before reading tag
if (p >= end) { if (p >= end) {
set_error_buf_ex(error_buf, error_buf_size, "Buffer overflow when reading instance tag"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Buffer overflow when reading instance tag");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
uint8_t tag = *p++; uint8_t tag = *p++;
out->instances[i].instance_expression_tag = tag; out->instances[i].instance_expression_tag = tag;
switch (tag) { switch (tag) {
case WASM_COMP_INSTANCE_EXPRESSION_WITH_ARGS: { case WASM_COMP_INSTANCE_EXPRESSION_WITH_ARGS:
{
// 0x00 m:<moduleidx> arg*:vec(<core:instantiatearg>) // 0x00 m:<moduleidx> arg*:vec(<core:instantiatearg>)
uint64_t module_idx = 0; uint64_t module_idx = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &module_idx, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &module_idx,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); error_buf, error_buf_size)) {
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
out->instances[i].expression.with_args.idx = (uint32_t)module_idx; out->instances[i].expression.with_args.idx =
(uint32_t)module_idx;
uint64_t arg_len = 0; uint64_t arg_len = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &arg_len, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &arg_len,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); error_buf, error_buf_size)) {
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
out->instances[i].expression.with_args.arg_len = (uint32_t)arg_len; out->instances[i].expression.with_args.arg_len =
(uint32_t)arg_len;
if (arg_len > 0) { if (arg_len > 0) {
out->instances[i].expression.with_args.args = wasm_runtime_malloc(sizeof(WASMComponentInstArg) * arg_len); out->instances[i].expression.with_args.args =
wasm_runtime_malloc(sizeof(WASMComponentInstArg)
* arg_len);
if (!out->instances[i].expression.with_args.args) { if (!out->instances[i].expression.with_args.args) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for core instantiate args"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Failed to allocate memory for "
"core instantiate args");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Initialize args to zero // Initialize args to zero
memset(out->instances[i].expression.with_args.args, 0, sizeof(WASMComponentInstArg) * arg_len); memset(out->instances[i].expression.with_args.args, 0,
sizeof(WASMComponentInstArg) * arg_len);
for (uint32_t j = 0; j < arg_len; ++j) { for (uint32_t j = 0; j < arg_len; ++j) {
// core:instantiatearg ::= n:<core:name> 0x12 i:<instanceidx> // core:instantiatearg ::= n:<core:name> 0x12
// Parse core:name (LEB128 length + UTF-8 bytes) // i:<instanceidx> Parse core:name (LEB128 length +
// UTF-8 bytes)
// Check bounds before parsing name // Check bounds before parsing name
if (p >= end) { if (p >= end) {
set_error_buf_ex(error_buf, error_buf_size, "Buffer overflow when parsing core name"); set_error_buf_ex(
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); error_buf, error_buf_size,
"Buffer overflow when parsing core name");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
WASMComponentCoreName *core_name = NULL; WASMComponentCoreName *core_name = NULL;
if (!parse_core_name(&p, end, &core_name, error_buf, error_buf_size)) { if (!parse_core_name(&p, end, &core_name, error_buf,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); error_buf_size)) {
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Store the name in the instantiate arg structure // Store the name in the instantiate arg structure
out->instances[i].expression.with_args.args[j].name = core_name; out->instances[i]
.expression.with_args.args[j]
.name = core_name;
// Check bounds before reading 0x12 // Check bounds before reading 0x12
if (p >= end) { if (p >= end) {
set_error_buf_ex(error_buf, error_buf_size, "Buffer overflow when reading 0x12 flag"); set_error_buf_ex(
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); error_buf, error_buf_size,
"Buffer overflow when reading 0x12 flag");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Verify 0x12 for core:instantiatearg // Verify 0x12 for core:instantiatearg
if(*p++ != 0x12){ if (*p++ != 0x12) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to read 0x12 flag identifier for core instantiatearg field"); set_error_buf_ex(
error_buf, error_buf_size,
"Failed to read 0x12 flag identifier for "
"core instantiatearg field");
free_core_name(core_name); free_core_name(core_name);
wasm_runtime_free(core_name); wasm_runtime_free(core_name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// i:<instanceidx> - this is a core instance index // i:<instanceidx> - this is a core instance index
uint64_t instance_idx = 0; uint64_t instance_idx = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &instance_idx, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false,
&instance_idx, error_buf,
error_buf_size)) {
free_core_name(core_name); free_core_name(core_name);
wasm_runtime_free(core_name); wasm_runtime_free(core_name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
out->instances[i].expression.with_args.args[j].idx.instance_idx = (uint32_t)instance_idx; out->instances[i]
.expression.with_args.args[j]
.idx.instance_idx = (uint32_t)instance_idx;
} }
} else { }
else {
out->instances[i].expression.with_args.args = NULL; out->instances[i].expression.with_args.args = NULL;
} }
break; break;
} }
case WASM_COMP_INSTANCE_EXPRESSION_WITHOUT_ARGS: { case WASM_COMP_INSTANCE_EXPRESSION_WITHOUT_ARGS:
{
// 0x01 e*:vec(<core:inlineexport>) => e* // 0x01 e*:vec(<core:inlineexport>) => e*
uint64_t inline_expr_len = 0; uint64_t inline_expr_len = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &inline_expr_len, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); &inline_expr_len, error_buf,
error_buf_size)) {
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
out->instances[i].expression.without_args.inline_expr_len = (uint32_t)inline_expr_len; out->instances[i].expression.without_args.inline_expr_len =
(uint32_t)inline_expr_len;
if (inline_expr_len > 0) { if (inline_expr_len > 0) {
out->instances[i].expression.without_args.inline_expr = wasm_runtime_malloc(sizeof(WASMComponentInlineExport) * inline_expr_len); out->instances[i].expression.without_args.inline_expr =
if (!out->instances[i].expression.without_args.inline_expr) { wasm_runtime_malloc(
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for core inline exports"); sizeof(WASMComponentInlineExport)
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); * inline_expr_len);
if (!out->instances[i]
.expression.without_args.inline_expr) {
set_error_buf_ex(error_buf, error_buf_size,
"Failed to allocate memory for "
"core inline exports");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Initialize inline exports to zero // Initialize inline exports to zero
memset(out->instances[i].expression.without_args.inline_expr, 0, sizeof(WASMComponentInlineExport) * inline_expr_len); memset(out->instances[i]
.expression.without_args.inline_expr,
0,
sizeof(WASMComponentInlineExport)
* inline_expr_len);
for (uint32_t j = 0; j < inline_expr_len; j++) { for (uint32_t j = 0; j < inline_expr_len; j++) {
// core:inlineexport ::= n:<core:name> si:<core:sortidx> // core:inlineexport ::= n:<core:name>
// si:<core:sortidx>
WASMComponentCoreName *name = NULL; WASMComponentCoreName *name = NULL;
// Debug: Check if we're about to go out of bounds // Debug: Check if we're about to go out of bounds
if (p >= end) { if (p >= end) {
set_error_buf_ex(error_buf, error_buf_size, "Buffer overflow in inline exports parsing"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Buffer overflow in inline "
"exports parsing");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Parse core:name using the existing parse_core_name function // Parse core:name using the existing
bool name_parse_success = parse_core_name(&p, end, &name, error_buf, error_buf_size); // parse_core_name function
bool name_parse_success = parse_core_name(
&p, end, &name, error_buf, error_buf_size);
if (!name_parse_success) { if (!name_parse_success) {
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
out->instances[i].expression.without_args.inline_expr[j].name = name; out->instances[i]
.expression.without_args.inline_expr[j]
.name = name;
// Check bounds before parsing sort index // Check bounds before parsing sort index
if (p >= end) { if (p >= end) {
set_error_buf_ex(error_buf, error_buf_size, "Buffer overflow when parsing core sort idx"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Buffer overflow when parsing "
"core sort idx");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Parse core:sortidx (must use is_core=true for core instances) // Parse core:sortidx (must use is_core=true for
WASMComponentSortIdx *sort_idx = wasm_runtime_malloc(sizeof(WASMComponentSortIdx)); // core instances)
WASMComponentSortIdx *sort_idx =
wasm_runtime_malloc(
sizeof(WASMComponentSortIdx));
if (!sort_idx) { if (!sort_idx) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for core sort idx"); set_error_buf_ex(error_buf, error_buf_size,
"Failed to allocate memory "
"for core sort idx");
free_core_name(name); free_core_name(name);
wasm_runtime_free(name); wasm_runtime_free(name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Zero-initialize sort_idx // Zero-initialize sort_idx
memset(sort_idx, 0, sizeof(WASMComponentSortIdx)); memset(sort_idx, 0, sizeof(WASMComponentSortIdx));
bool status = parse_sort_idx(&p, end, sort_idx, error_buf, error_buf_size, true); bool status =
parse_sort_idx(&p, end, sort_idx, error_buf,
error_buf_size, true);
if (!status) { if (!status) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to parse core sort idx"); set_error_buf_ex(
error_buf, error_buf_size,
"Failed to parse core sort idx");
wasm_runtime_free(sort_idx); wasm_runtime_free(sort_idx);
free_core_name(name); free_core_name(name);
wasm_runtime_free(name); wasm_runtime_free(name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
out->instances[i].expression.without_args.inline_expr[j].sort_idx = sort_idx; out->instances[i]
.expression.without_args.inline_expr[j]
.sort_idx = sort_idx;
} }
} else { }
out->instances[i].expression.without_args.inline_expr = NULL; else {
out->instances[i].expression.without_args.inline_expr =
NULL;
} }
break; break;
} }
default: { default:
set_error_buf_ex(error_buf, error_buf_size, "Unknown core instance expression tag: 0x%02X", tag); {
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); set_error_buf_ex(
error_buf, error_buf_size,
"Unknown core instance expression tag: 0x%02X", tag);
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
} }
} }
} }
if (consumed_len) *consumed_len = payload_len; if (consumed_len)
*consumed_len = payload_len;
return true; return true;
} }
// Individual section free functions // Individual section free functions
void wasm_component_free_core_instance_section(WASMComponentSection *section) { void
if (!section || !section->parsed.core_instance_section) return; wasm_component_free_core_instance_section(WASMComponentSection *section)
{
if (!section || !section->parsed.core_instance_section)
return;
WASMComponentCoreInstSection *core_instance_sec = section->parsed.core_instance_section; WASMComponentCoreInstSection *core_instance_sec =
section->parsed.core_instance_section;
if (core_instance_sec->instances) { if (core_instance_sec->instances) {
for (uint32_t j = 0; j < core_instance_sec->count; ++j) { for (uint32_t j = 0; j < core_instance_sec->count; ++j) {
WASMComponentCoreInst *instance = &core_instance_sec->instances[j]; WASMComponentCoreInst *instance = &core_instance_sec->instances[j];
@ -235,8 +338,10 @@ void wasm_component_free_core_instance_section(WASMComponentSection *section) {
switch (instance->instance_expression_tag) { switch (instance->instance_expression_tag) {
case WASM_COMP_INSTANCE_EXPRESSION_WITH_ARGS: case WASM_COMP_INSTANCE_EXPRESSION_WITH_ARGS:
if (instance->expression.with_args.args) { if (instance->expression.with_args.args) {
for (uint32_t k = 0; k < instance->expression.with_args.arg_len; ++k) { for (uint32_t k = 0;
WASMComponentInstArg *arg = &instance->expression.with_args.args[k]; k < instance->expression.with_args.arg_len; ++k) {
WASMComponentInstArg *arg =
&instance->expression.with_args.args[k];
// Free core name // Free core name
if (arg->name) { if (arg->name) {
@ -252,8 +357,13 @@ void wasm_component_free_core_instance_section(WASMComponentSection *section) {
case WASM_COMP_INSTANCE_EXPRESSION_WITHOUT_ARGS: case WASM_COMP_INSTANCE_EXPRESSION_WITHOUT_ARGS:
if (instance->expression.without_args.inline_expr) { if (instance->expression.without_args.inline_expr) {
for (uint32_t k = 0; k < instance->expression.without_args.inline_expr_len; ++k) { for (uint32_t k = 0;
WASMComponentInlineExport *inline_export = &instance->expression.without_args.inline_expr[k]; k < instance->expression.without_args
.inline_expr_len;
++k) {
WASMComponentInlineExport *inline_export =
&instance->expression.without_args
.inline_expr[k];
// Free core export name // Free core export name
if (inline_export->name) { if (inline_export->name) {
@ -265,14 +375,16 @@ void wasm_component_free_core_instance_section(WASMComponentSection *section) {
// Free core sort index // Free core sort index
if (inline_export->sort_idx) { if (inline_export->sort_idx) {
if (inline_export->sort_idx->sort) { if (inline_export->sort_idx->sort) {
wasm_runtime_free(inline_export->sort_idx->sort); wasm_runtime_free(
inline_export->sort_idx->sort);
inline_export->sort_idx->sort = NULL; inline_export->sort_idx->sort = NULL;
} }
wasm_runtime_free(inline_export->sort_idx); wasm_runtime_free(inline_export->sort_idx);
inline_export->sort_idx = NULL; inline_export->sort_idx = NULL;
} }
} }
wasm_runtime_free(instance->expression.without_args.inline_expr); wasm_runtime_free(
instance->expression.without_args.inline_expr);
instance->expression.without_args.inline_expr = NULL; instance->expression.without_args.inline_expr = NULL;
} }
break; break;

View File

@ -13,30 +13,46 @@
#include <stdio.h> #include <stdio.h>
// Section 1: module section // Section 1: module section
bool wasm_component_parse_core_module_section(const uint8_t **payload, uint32_t payload_len, WASMComponentCoreModuleWrapper *out, LoadArgs *args, char *error_buf, uint32_t error_buf_size, uint32_t *consumed_len) { bool
if (consumed_len) *consumed_len = 0; wasm_component_parse_core_module_section(const uint8_t **payload,
uint32_t payload_len,
WASMComponentCoreModuleWrapper *out,
LoadArgs *args, char *error_buf,
uint32_t error_buf_size,
uint32_t *consumed_len)
{
if (consumed_len)
*consumed_len = 0;
if (!payload || !*payload || payload_len == 0 || !out) { if (!payload || !*payload || payload_len == 0 || !out) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid payload or output pointer"); set_error_buf_ex(error_buf, error_buf_size,
"Invalid payload or output pointer");
return false; return false;
} }
LOG_DEBUG(" Module section: embedded Core WebAssembly module\n"); LOG_DEBUG(" Module section: embedded Core WebAssembly module\n");
// Use the core wasm loader to parse the module // Use the core wasm loader to parse the module
wasm_module_t mod = wasm_runtime_load_ex((uint8 *)*payload, payload_len, args, error_buf, error_buf_size); wasm_module_t mod = wasm_runtime_load_ex((uint8 *)*payload, payload_len,
args, error_buf, error_buf_size);
if (!mod) { if (!mod) {
LOG_DEBUG(" Failed to load embedded core wasm module: %s\n", error_buf); LOG_DEBUG(" Failed to load embedded core wasm module: %s\n",
error_buf);
return false; return false;
} }
// Print some basic info about the embedded module // Print some basic info about the embedded module
LOG_DEBUG(" Types: %u function types\n", wasm_runtime_get_import_count(mod)); LOG_DEBUG(" Types: %u function types\n",
LOG_DEBUG(" Exports: %u exports\n", wasm_runtime_get_export_count(mod)); wasm_runtime_get_import_count(mod));
LOG_DEBUG(" Exports: %u exports\n",
wasm_runtime_get_export_count(mod));
#if WASM_ENABLE_INTERP != 0 #if WASM_ENABLE_INTERP != 0
LOG_DEBUG(" Functions: %u functions\n", wasm_runtime_get_function_count(mod)); LOG_DEBUG(" Functions: %u functions\n",
wasm_runtime_get_function_count(mod));
LOG_DEBUG(" Tables: %u tables\n", wasm_runtime_get_table_count(mod)); LOG_DEBUG(" Tables: %u tables\n", wasm_runtime_get_table_count(mod));
LOG_DEBUG(" Memories: %u memories\n", wasm_runtime_get_memories_count(mod)); LOG_DEBUG(" Memories: %u memories\n",
LOG_DEBUG(" Globals: %u globals\n", wasm_runtime_get_globals_count(mod)); wasm_runtime_get_memories_count(mod));
LOG_DEBUG(" Globals: %u globals\n",
wasm_runtime_get_globals_count(mod));
#endif #endif
// Check if the module has imports // Check if the module has imports
@ -46,18 +62,19 @@ bool wasm_component_parse_core_module_section(const uint8_t **payload, uint32_t
for (int32_t i = 0; i < import_count; i++) { for (int32_t i = 0; i < import_count; i++) {
wasm_import_t import; wasm_import_t import;
wasm_runtime_get_import_type(mod, i, &import); wasm_runtime_get_import_type(mod, i, &import);
LOG_DEBUG(" Import %u: module=\"%s\", name=\"%s\", kind=%u\n", LOG_DEBUG(
i, " Import %u: module=\"%s\", name=\"%s\", kind=%u\n", i,
import.module_name ? import.module_name : "<null>", import.module_name ? import.module_name : "<null>",
import.name ? import.name : "<null>", import.name ? import.name : "<null>", import.kind);
import.kind);
// Print more details about the import // Print more details about the import
if (import.module_name && strlen(import.module_name) == 0) { if (import.module_name && strlen(import.module_name) == 0) {
LOG_DEBUG(" WARNING: Empty module name - this will cause 'unknown import' error\n"); LOG_DEBUG(" WARNING: Empty module name - this will "
"cause 'unknown import' error\n");
} }
if (import.name && strlen(import.name) == 0) { if (import.name && strlen(import.name) == 0) {
LOG_DEBUG(" WARNING: Empty field name - this will cause 'unknown import' error\n"); LOG_DEBUG(" WARNING: Empty field name - this will "
"cause 'unknown import' error\n");
} }
} }
} }
@ -69,32 +86,36 @@ bool wasm_component_parse_core_module_section(const uint8_t **payload, uint32_t
for (int32_t i = 0; i < export_count; i++) { for (int32_t i = 0; i < export_count; i++) {
wasm_export_t export; wasm_export_t export;
wasm_runtime_get_export_type(mod, i, &export); wasm_runtime_get_export_type(mod, i, &export);
LOG_DEBUG(" Export %u: name=\"%s\", kind= %u\n", LOG_DEBUG(" Export %u: name=\"%s\", kind= %u\n", i,
i, export.name ? export.name : "<null>", export.kind);
export.name ? export.name : "<null>",
export.kind);
// Print more details about the export // Print more details about the export
if (export.name && strlen(export.name) == 0) { if (export.name && strlen(export.name) == 0) {
LOG_DEBUG(" WARNING: Empty field name - this will cause 'unknown export' error\n"); LOG_DEBUG(" WARNING: Empty field name - this will "
"cause 'unknown export' error\n");
} }
} }
} }
// Store the module pointer directly instead of copying // Store the module pointer directly instead of copying
out->module_handle = (void*)mod; out->module_handle = (void *)mod;
out->module = NULL; // We don't need the actual module structure for now out->module = NULL; // We don't need the actual module structure for now
if (consumed_len) *consumed_len = payload_len; if (consumed_len)
*consumed_len = payload_len;
return true; return true;
} }
// Individual section free functions // Individual section free functions
void wasm_component_free_core_module_section(WASMComponentSection *section) { void
if (!section || !section->parsed.core_module) return; wasm_component_free_core_module_section(WASMComponentSection *section)
{
if (!section || !section->parsed.core_module)
return;
// Use the proper wasm_runtime_unload function to free the module // Use the proper wasm_runtime_unload function to free the module
if (section->parsed.core_module->module_handle) { if (section->parsed.core_module->module_handle) {
wasm_runtime_unload((wasm_module_t)section->parsed.core_module->module_handle); wasm_runtime_unload(
(wasm_module_t)section->parsed.core_module->module_handle);
section->parsed.core_module->module_handle = NULL; section->parsed.core_module->module_handle = NULL;
} }
wasm_runtime_free(section->parsed.core_module); wasm_runtime_free(section->parsed.core_module);

View File

@ -12,14 +12,20 @@
#include "wasm_export.h" #include "wasm_export.h"
#include <stdio.h> #include <stdio.h>
bool parse_core_limits(const uint8_t **payload, const uint8_t *end, WASMComponentCoreLimits *out, char *error_buf, uint32_t error_buf_size) { bool
parse_core_limits(const uint8_t **payload, const uint8_t *end,
WASMComponentCoreLimits *out, char *error_buf,
uint32_t error_buf_size)
{
const uint8_t *p = *payload; const uint8_t *p = *payload;
uint8_t tag = *p++; uint8_t tag = *p++;
switch (tag) { switch (tag) {
case WASM_CORE_LIMITS_MIN: { case WASM_CORE_LIMITS_MIN:
{
uint64_t min = 0; uint64_t min = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &min, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &min, error_buf,
error_buf_size)) {
return false; return false;
} }
@ -27,14 +33,17 @@ bool parse_core_limits(const uint8_t **payload, const uint8_t *end, WASMComponen
out->lim.limits.min = (uint32_t)min; out->lim.limits.min = (uint32_t)min;
break; break;
} }
case WASM_CORE_LIMITS_MAX: { case WASM_CORE_LIMITS_MAX:
{
uint64_t min = 0; uint64_t min = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &min, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &min, error_buf,
error_buf_size)) {
return false; return false;
} }
uint64_t max = 0; uint64_t max = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &max, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &max, error_buf,
error_buf_size)) {
return false; return false;
} }
@ -43,8 +52,10 @@ bool parse_core_limits(const uint8_t **payload, const uint8_t *end, WASMComponen
out->lim.limits_max.max = (uint32_t)max; out->lim.limits_max.max = (uint32_t)max;
break; break;
} }
default: { default:
set_error_buf_ex(error_buf, error_buf_size, "Invalid limits tag: %02x", tag); {
set_error_buf_ex(error_buf, error_buf_size,
"Invalid limits tag: %02x", tag);
return false; return false;
} }
} }
@ -53,11 +64,15 @@ bool parse_core_limits(const uint8_t **payload, const uint8_t *end, WASMComponen
return true; return true;
} }
static bool parse_core_heaptype(const uint8_t **payload, const uint8_t *end, WASMComponentCoreHeapType *out, char *error_buf, uint32_t error_buf_size) static bool
parse_core_heaptype(const uint8_t **payload, const uint8_t *end,
WASMComponentCoreHeapType *out, char *error_buf,
uint32_t error_buf_size)
{ {
const uint8_t *p = *payload; const uint8_t *p = *payload;
if (p >= end) { if (p >= end) {
set_error_buf_ex(error_buf, error_buf_size, "Unexpected end while parsing heaptype"); set_error_buf_ex(error_buf, error_buf_size,
"Unexpected end while parsing heaptype");
return false; return false;
} }
@ -73,11 +88,14 @@ static bool parse_core_heaptype(const uint8_t **payload, const uint8_t *end, WAS
// Otherwise, parse as (positive) s33 index; we store as u32 // Otherwise, parse as (positive) s33 index; we store as u32
uint64_t idx = 0; uint64_t idx = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &idx, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &idx, error_buf,
error_buf_size)) {
return false; return false;
} }
if (!is_valid_core_heap_type_index(idx)) { if (!is_valid_core_heap_type_index(idx)) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid heaptype index: %llu", (unsigned long long)idx); set_error_buf_ex(error_buf, error_buf_size,
"Invalid heaptype index: %llu",
(unsigned long long)idx);
return false; return false;
} }
@ -87,7 +105,11 @@ static bool parse_core_heaptype(const uint8_t **payload, const uint8_t *end, WAS
return true; return true;
} }
bool parse_core_valtype(const uint8_t **payload, const uint8_t *end, WASMComponentCoreValType *out, char *error_buf, uint32_t error_buf_size) { bool
parse_core_valtype(const uint8_t **payload, const uint8_t *end,
WASMComponentCoreValType *out, char *error_buf,
uint32_t error_buf_size)
{
const uint8_t *p = *payload; const uint8_t *p = *payload;
uint8_t tag = *p++; uint8_t tag = *p++;
@ -113,29 +135,34 @@ bool parse_core_valtype(const uint8_t **payload, const uint8_t *end, WASMCompone
// - ht:absheaptype (0x6A..0x73) => short-form (ref null ht) // - ht:absheaptype (0x6A..0x73) => short-form (ref null ht)
if (tag == 0x63 || tag == 0x64) { if (tag == 0x63 || tag == 0x64) {
WASMComponentCoreHeapType heap_type; WASMComponentCoreHeapType heap_type;
if (!parse_core_heaptype(&p, end, &heap_type, error_buf, error_buf_size)) { if (!parse_core_heaptype(&p, end, &heap_type, error_buf,
error_buf_size)) {
return false; return false;
} }
if (heap_type.tag == WASM_CORE_HEAP_TYPE_ABSTRACT) { if (heap_type.tag == WASM_CORE_HEAP_TYPE_ABSTRACT) {
if (heap_type.heap_type.abstract_type == WASM_CORE_ABS_HEAP_TYPE_FUNC) { if (heap_type.heap_type.abstract_type
== WASM_CORE_ABS_HEAP_TYPE_FUNC) {
out->tag = WASM_CORE_VALTYPE_REF; out->tag = WASM_CORE_VALTYPE_REF;
out->type.ref_type = WASM_CORE_REFTYPE_FUNC_REF; out->type.ref_type = WASM_CORE_REFTYPE_FUNC_REF;
*payload = p; *payload = p;
return true; return true;
} }
if (heap_type.heap_type.abstract_type == WASM_CORE_ABS_HEAP_TYPE_EXTERN) { if (heap_type.heap_type.abstract_type
== WASM_CORE_ABS_HEAP_TYPE_EXTERN) {
out->tag = WASM_CORE_VALTYPE_REF; out->tag = WASM_CORE_VALTYPE_REF;
out->type.ref_type = WASM_CORE_REFTYPE_EXTERN_REF; out->type.ref_type = WASM_CORE_REFTYPE_EXTERN_REF;
*payload = p; *payload = p;
return true; return true;
} }
} }
set_error_buf_ex(error_buf, error_buf_size, "Unsupported reftype heaptype for core valtype"); set_error_buf_ex(error_buf, error_buf_size,
"Unsupported reftype heaptype for core valtype");
return false; return false;
} }
// Short-form absheaptype for (ref null ht) // Short-form absheaptype for (ref null ht)
if (tag >= WASM_CORE_ABS_HEAP_TYPE_ARRAY && tag <= WASM_CORE_ABS_HEAP_TYPE_NOFUNC) { if (tag >= WASM_CORE_ABS_HEAP_TYPE_ARRAY
&& tag <= WASM_CORE_ABS_HEAP_TYPE_NOFUNC) {
if (tag == WASM_CORE_ABS_HEAP_TYPE_FUNC) { if (tag == WASM_CORE_ABS_HEAP_TYPE_FUNC) {
out->tag = WASM_CORE_VALTYPE_REF; out->tag = WASM_CORE_VALTYPE_REF;
out->type.ref_type = WASM_CORE_REFTYPE_FUNC_REF; out->type.ref_type = WASM_CORE_REFTYPE_FUNC_REF;
@ -148,22 +175,31 @@ bool parse_core_valtype(const uint8_t **payload, const uint8_t *end, WASMCompone
*payload = p; *payload = p;
return true; return true;
} }
set_error_buf_ex(error_buf, error_buf_size, "Unsupported short-form absheaptype %02x for core valtype", tag); set_error_buf_ex(
error_buf, error_buf_size,
"Unsupported short-form absheaptype %02x for core valtype", tag);
return false; return false;
} }
set_error_buf_ex(error_buf, error_buf_size, "Invalid core valtype tag: %02x", tag); set_error_buf_ex(error_buf, error_buf_size,
"Invalid core valtype tag: %02x", tag);
return false; return false;
} }
bool parse_core_import_desc(const uint8_t **payload, const uint8_t *end, WASMComponentCoreImportDesc *out, char *error_buf, uint32_t error_buf_size) { bool
parse_core_import_desc(const uint8_t **payload, const uint8_t *end,
WASMComponentCoreImportDesc *out, char *error_buf,
uint32_t error_buf_size)
{
const uint8_t *p = *payload; const uint8_t *p = *payload;
uint8_t tag = *p++; uint8_t tag = *p++;
switch (tag) { switch (tag) {
case WASM_CORE_IMPORTDESC_FUNC: { case WASM_CORE_IMPORTDESC_FUNC:
{
uint64_t func_type_idx = 0; uint64_t func_type_idx = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &func_type_idx, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &func_type_idx,
error_buf, error_buf_size)) {
return false; return false;
} }
@ -172,25 +208,33 @@ bool parse_core_import_desc(const uint8_t **payload, const uint8_t *end, WASMCom
break; break;
} }
case WASM_CORE_IMPORTDESC_TABLE: { case WASM_CORE_IMPORTDESC_TABLE:
{
uint8_t ref_type_tag = *p++; uint8_t ref_type_tag = *p++;
if (ref_type_tag == WASM_CORE_REFTYPE_FUNC_REF) { if (ref_type_tag == WASM_CORE_REFTYPE_FUNC_REF) {
out->type = WASM_CORE_IMPORTDESC_TABLE; out->type = WASM_CORE_IMPORTDESC_TABLE;
out->desc.table_type.ref_type = WASM_CORE_REFTYPE_FUNC_REF; out->desc.table_type.ref_type = WASM_CORE_REFTYPE_FUNC_REF;
} else if (ref_type_tag == WASM_CORE_REFTYPE_EXTERN_REF) { }
else if (ref_type_tag == WASM_CORE_REFTYPE_EXTERN_REF) {
out->type = WASM_CORE_IMPORTDESC_TABLE; out->type = WASM_CORE_IMPORTDESC_TABLE;
out->desc.table_type.ref_type = WASM_CORE_REFTYPE_EXTERN_REF; out->desc.table_type.ref_type = WASM_CORE_REFTYPE_EXTERN_REF;
} else { }
set_error_buf_ex(error_buf, error_buf_size, "Invalid reference type tag: %02x", ref_type_tag); else {
set_error_buf_ex(error_buf, error_buf_size,
"Invalid reference type tag: %02x",
ref_type_tag);
return false; return false;
} }
WASMComponentCoreLimits *limits = wasm_runtime_malloc(sizeof(WASMComponentCoreLimits)); WASMComponentCoreLimits *limits =
wasm_runtime_malloc(sizeof(WASMComponentCoreLimits));
if (!limits) { if (!limits) {
set_error_buf_ex(error_buf, error_buf_size, "OOM allocating table limits"); set_error_buf_ex(error_buf, error_buf_size,
"OOM allocating table limits");
return false; return false;
} }
if (!parse_core_limits(&p, end, limits, error_buf, error_buf_size)) { if (!parse_core_limits(&p, end, limits, error_buf,
error_buf_size)) {
wasm_runtime_free(limits); wasm_runtime_free(limits);
return false; return false;
} }
@ -200,13 +244,17 @@ bool parse_core_import_desc(const uint8_t **payload, const uint8_t *end, WASMCom
break; break;
} }
case WASM_CORE_IMPORTDESC_MEMORY: { case WASM_CORE_IMPORTDESC_MEMORY:
WASMComponentCoreLimits *limits = wasm_runtime_malloc(sizeof(WASMComponentCoreLimits)); {
WASMComponentCoreLimits *limits =
wasm_runtime_malloc(sizeof(WASMComponentCoreLimits));
if (!limits) { if (!limits) {
set_error_buf_ex(error_buf, error_buf_size, "OOM allocating memory limits"); set_error_buf_ex(error_buf, error_buf_size,
"OOM allocating memory limits");
return false; return false;
} }
if (!parse_core_limits(&p, end, limits, error_buf, error_buf_size)) { if (!parse_core_limits(&p, end, limits, error_buf,
error_buf_size)) {
wasm_runtime_free(limits); wasm_runtime_free(limits);
return false; return false;
} }
@ -216,8 +264,10 @@ bool parse_core_import_desc(const uint8_t **payload, const uint8_t *end, WASMCom
break; break;
} }
case WASM_CORE_IMPORTDESC_GLOBAL: { case WASM_CORE_IMPORTDESC_GLOBAL:
if (!parse_core_valtype(&p, end, &out->desc.global_type.val_type, error_buf, error_buf_size)) { {
if (!parse_core_valtype(&p, end, &out->desc.global_type.val_type,
error_buf, error_buf_size)) {
return false; return false;
} }
@ -225,17 +275,22 @@ bool parse_core_import_desc(const uint8_t **payload, const uint8_t *end, WASMCom
uint8_t mutable_tag = *p++; uint8_t mutable_tag = *p++;
if (mutable_tag == WASM_CORE_GLOBAL_MUTABLE) { if (mutable_tag == WASM_CORE_GLOBAL_MUTABLE) {
out->desc.global_type.is_mutable = true; out->desc.global_type.is_mutable = true;
} else if (mutable_tag == WASM_CORE_GLOBAL_IMMUTABLE) { }
else if (mutable_tag == WASM_CORE_GLOBAL_IMMUTABLE) {
out->desc.global_type.is_mutable = false; out->desc.global_type.is_mutable = false;
} else { }
set_error_buf_ex(error_buf, error_buf_size, "Invalid mutable tag: %02x", mutable_tag); else {
set_error_buf_ex(error_buf, error_buf_size,
"Invalid mutable tag: %02x", mutable_tag);
return false; return false;
} }
break; break;
} }
default: { default:
set_error_buf_ex(error_buf, error_buf_size, "Invalid import descriptor tag: %02x", tag); {
set_error_buf_ex(error_buf, error_buf_size,
"Invalid import descriptor tag: %02x", tag);
return false; return false;
} }
} }
@ -244,7 +299,11 @@ bool parse_core_import_desc(const uint8_t **payload, const uint8_t *end, WASMCom
return true; return true;
} }
bool parse_core_import(const uint8_t **payload, const uint8_t *end, WASMComponentCoreImport *out, char *error_buf, uint32_t error_buf_size) { bool
parse_core_import(const uint8_t **payload, const uint8_t *end,
WASMComponentCoreImport *out, char *error_buf,
uint32_t error_buf_size)
{
const uint8_t *p = *payload; const uint8_t *p = *payload;
WASMComponentCoreName *mod_name = NULL; WASMComponentCoreName *mod_name = NULL;
@ -261,12 +320,15 @@ bool parse_core_import(const uint8_t **payload, const uint8_t *end, WASMComponen
out->nm = nm_name; out->nm = nm_name;
WASMComponentCoreImportDesc *import_desc = wasm_runtime_malloc(sizeof(WASMComponentCoreImportDesc)); WASMComponentCoreImportDesc *import_desc =
wasm_runtime_malloc(sizeof(WASMComponentCoreImportDesc));
if (!import_desc) { if (!import_desc) {
set_error_buf_ex(error_buf, error_buf_size, "OOM allocating import desc"); set_error_buf_ex(error_buf, error_buf_size,
"OOM allocating import desc");
return false; return false;
} }
if (!parse_core_import_desc(&p, end, import_desc, error_buf, error_buf_size)) { if (!parse_core_import_desc(&p, end, import_desc, error_buf,
error_buf_size)) {
wasm_runtime_free(import_desc); wasm_runtime_free(import_desc);
return false; return false;
} }
@ -277,26 +339,34 @@ bool parse_core_import(const uint8_t **payload, const uint8_t *end, WASMComponen
return true; return true;
} }
bool parse_alias_target(const uint8_t **payload, const uint8_t *end, WASMComponentCoreAliasTarget *out, char *error_buf, uint32_t error_buf_size) { bool
parse_alias_target(const uint8_t **payload, const uint8_t *end,
WASMComponentCoreAliasTarget *out, char *error_buf,
uint32_t error_buf_size)
{
const uint8_t *p = *payload; const uint8_t *p = *payload;
uint8_t tag = *p++; uint8_t tag = *p++;
if (tag == 0x01) { if (tag == 0x01) {
uint64_t ct_leb = 0; uint64_t ct_leb = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &ct_leb, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &ct_leb, error_buf,
error_buf_size)) {
return false; return false;
} }
out->ct = (uint32_t)ct_leb; out->ct = (uint32_t)ct_leb;
uint64_t index_leb = 0; uint64_t index_leb = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &index_leb, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &index_leb, error_buf,
error_buf_size)) {
return false; return false;
} }
out->index = (uint32_t)index_leb; out->index = (uint32_t)index_leb;
} else { }
set_error_buf_ex(error_buf, error_buf_size, "Invalid alias target tag: %02x", tag); else {
set_error_buf_ex(error_buf, error_buf_size,
"Invalid alias target tag: %02x", tag);
return false; return false;
} }
@ -304,7 +374,11 @@ bool parse_alias_target(const uint8_t **payload, const uint8_t *end, WASMCompone
return true; return true;
} }
bool parse_core_alias(const uint8_t **payload, const uint8_t *end, WASMComponentCoreAlias *out, char *error_buf, uint32_t error_buf_size) { bool
parse_core_alias(const uint8_t **payload, const uint8_t *end,
WASMComponentCoreAlias *out, char *error_buf,
uint32_t error_buf_size)
{
const uint8_t *p = *payload; const uint8_t *p = *payload;
/* no leading tag here; core:alias is parsed inside moduledecl */ /* no leading tag here; core:alias is parsed inside moduledecl */
@ -312,8 +386,10 @@ bool parse_core_alias(const uint8_t **payload, const uint8_t *end, WASMComponent
return false; return false;
} }
if (!parse_alias_target(&p, end, &out->alias_target, error_buf, error_buf_size)) { if (!parse_alias_target(&p, end, &out->alias_target, error_buf,
set_error_buf_ex(error_buf, error_buf_size, "Failed to parse alias target"); error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size,
"Failed to parse alias target");
return false; return false;
} }
@ -321,7 +397,11 @@ bool parse_core_alias(const uint8_t **payload, const uint8_t *end, WASMComponent
return true; return true;
} }
bool parse_core_export_decl(const uint8_t **payload, const uint8_t *end, WASMComponentCoreExportDecl *out, char *error_buf, uint32_t error_buf_size) { bool
parse_core_export_decl(const uint8_t **payload, const uint8_t *end,
WASMComponentCoreExportDecl *out, char *error_buf,
uint32_t error_buf_size)
{
const uint8_t *p = *payload; const uint8_t *p = *payload;
/* core:exportdecl ::= nm:<core:name> d:<core:exportdesc> */ /* core:exportdecl ::= nm:<core:name> d:<core:exportdesc> */
WASMComponentCoreName *mod_name = NULL; WASMComponentCoreName *mod_name = NULL;
@ -330,12 +410,15 @@ bool parse_core_export_decl(const uint8_t **payload, const uint8_t *end, WASMCom
} }
out->name = mod_name; out->name = mod_name;
WASMComponentCoreImportDesc *export_desc = wasm_runtime_malloc(sizeof(WASMComponentCoreImportDesc)); WASMComponentCoreImportDesc *export_desc =
wasm_runtime_malloc(sizeof(WASMComponentCoreImportDesc));
if (!export_desc) { if (!export_desc) {
set_error_buf_ex(error_buf, error_buf_size, "OOM allocating export desc"); set_error_buf_ex(error_buf, error_buf_size,
"OOM allocating export desc");
return false; return false;
} }
if (!parse_core_import_desc(&p, end, export_desc, error_buf, error_buf_size)) { if (!parse_core_import_desc(&p, end, export_desc, error_buf,
error_buf_size)) {
wasm_runtime_free(export_desc); wasm_runtime_free(export_desc);
return false; return false;
} }
@ -346,69 +429,98 @@ bool parse_core_export_decl(const uint8_t **payload, const uint8_t *end, WASMCom
return true; return true;
} }
bool parse_core_module_decl(const uint8_t **payload, const uint8_t *end, WASMComponentCoreModuleDecl *out, char *error_buf, uint32_t error_buf_size) { bool
parse_core_module_decl(const uint8_t **payload, const uint8_t *end,
WASMComponentCoreModuleDecl *out, char *error_buf,
uint32_t error_buf_size)
{
const uint8_t *p = *payload; const uint8_t *p = *payload;
uint8_t tag = *p++; uint8_t tag = *p++;
out->tag = tag; out->tag = tag;
switch (tag) { switch (tag) {
case WASM_CORE_MODULEDECL_IMPORT: { case WASM_CORE_MODULEDECL_IMPORT:
out->decl.import_decl.import = wasm_runtime_malloc(sizeof(WASMComponentCoreImport)); {
out->decl.import_decl.import =
wasm_runtime_malloc(sizeof(WASMComponentCoreImport));
if (!out->decl.import_decl.import) { if (!out->decl.import_decl.import) {
set_error_buf_ex(error_buf, error_buf_size, "OOM allocating module import decl"); set_error_buf_ex(error_buf, error_buf_size,
"OOM allocating module import decl");
return false; return false;
} }
if (!parse_core_import(&p, end, out->decl.import_decl.import, error_buf, error_buf_size)) { if (!parse_core_import(&p, end, out->decl.import_decl.import,
error_buf, error_buf_size)) {
return false; return false;
} }
break; break;
} }
case WASM_CORE_MODULEDECL_TYPE: { case WASM_CORE_MODULEDECL_TYPE:
out->decl.type_decl.type = wasm_runtime_malloc(sizeof(WASMComponentCoreType)); {
out->decl.type_decl.type =
wasm_runtime_malloc(sizeof(WASMComponentCoreType));
if (!out->decl.type_decl.type) { if (!out->decl.type_decl.type) {
set_error_buf_ex(error_buf, error_buf_size, "OOM allocating module type decl"); set_error_buf_ex(error_buf, error_buf_size,
"OOM allocating module type decl");
return false; return false;
} }
out->decl.type_decl.type->deftype = wasm_runtime_malloc(sizeof(WASMComponentCoreDefType)); out->decl.type_decl.type->deftype =
wasm_runtime_malloc(sizeof(WASMComponentCoreDefType));
if (!out->decl.type_decl.type->deftype) { if (!out->decl.type_decl.type->deftype) {
set_error_buf_ex(error_buf, error_buf_size, "OOM allocating core deftype"); set_error_buf_ex(error_buf, error_buf_size,
"OOM allocating core deftype");
return false; return false;
} }
if (!parse_single_core_type(&p, end, out->decl.type_decl.type->deftype, error_buf, error_buf_size)) { if (!parse_single_core_type(&p, end,
set_error_buf_ex(error_buf, error_buf_size, "Failed to parse type declaration"); out->decl.type_decl.type->deftype,
error_buf, error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size,
"Failed to parse type declaration");
return false; return false;
} }
break; break;
} }
case WASM_CORE_MODULEDECL_ALIAS: { case WASM_CORE_MODULEDECL_ALIAS:
out->decl.alias_decl.alias = wasm_runtime_malloc(sizeof(WASMComponentCoreAlias)); {
out->decl.alias_decl.alias =
wasm_runtime_malloc(sizeof(WASMComponentCoreAlias));
if (!out->decl.alias_decl.alias) { if (!out->decl.alias_decl.alias) {
set_error_buf_ex(error_buf, error_buf_size, "OOM allocating module alias decl"); set_error_buf_ex(error_buf, error_buf_size,
"OOM allocating module alias decl");
return false; return false;
} }
if (!parse_core_alias(&p, end, out->decl.alias_decl.alias, error_buf, error_buf_size)) { if (!parse_core_alias(&p, end, out->decl.alias_decl.alias,
set_error_buf_ex(error_buf, error_buf_size, "Failed to parse alias declaration"); error_buf, error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size,
"Failed to parse alias declaration");
return false; return false;
} }
break; break;
} }
case WASM_CORE_MODULEDECL_EXPORT: { case WASM_CORE_MODULEDECL_EXPORT:
out->decl.export_decl.export_decl = wasm_runtime_malloc(sizeof(WASMComponentCoreExportDecl)); {
out->decl.export_decl.export_decl =
wasm_runtime_malloc(sizeof(WASMComponentCoreExportDecl));
if (!out->decl.export_decl.export_decl) { if (!out->decl.export_decl.export_decl) {
set_error_buf_ex(error_buf, error_buf_size, "OOM allocating module export decl"); set_error_buf_ex(error_buf, error_buf_size,
"OOM allocating module export decl");
return false; return false;
} }
if (!parse_core_export_decl(&p, end, out->decl.export_decl.export_decl, error_buf, error_buf_size)) { if (!parse_core_export_decl(&p, end,
set_error_buf_ex(error_buf, error_buf_size, "Failed to parse export declaration"); out->decl.export_decl.export_decl,
error_buf, error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size,
"Failed to parse export declaration");
return false; return false;
} }
break; break;
} }
default: { default:
set_error_buf_ex(error_buf, error_buf_size, "Invalid module declaration tag: %02x", tag); {
set_error_buf_ex(error_buf, error_buf_size,
"Invalid module declaration tag: %02x", tag);
return false; return false;
} }
} }
@ -416,11 +528,16 @@ bool parse_core_module_decl(const uint8_t **payload, const uint8_t *end, WASMCom
return true; return true;
} }
bool parse_core_moduletype(const uint8_t **payload, const uint8_t *end, WASMComponentCoreModuleType *out, char *error_buf, uint32_t error_buf_size) { bool
parse_core_moduletype(const uint8_t **payload, const uint8_t *end,
WASMComponentCoreModuleType *out, char *error_buf,
uint32_t error_buf_size)
{
const uint8_t *p = *payload; const uint8_t *p = *payload;
// Expect vec(moduledecl): count then that many moduledecl // Expect vec(moduledecl): count then that many moduledecl
uint64_t count_leb = 0; uint64_t count_leb = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &count_leb, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &count_leb, error_buf,
error_buf_size)) {
return false; return false;
} }
@ -428,16 +545,20 @@ bool parse_core_moduletype(const uint8_t **payload, const uint8_t *end, WASMComp
out->decl_count = count; out->decl_count = count;
if (count > 0) { if (count > 0) {
out->declarations = wasm_runtime_malloc(sizeof(WASMComponentCoreModuleDecl) * count); out->declarations =
wasm_runtime_malloc(sizeof(WASMComponentCoreModuleDecl) * count);
if (!out->declarations) { if (!out->declarations) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for declarations"); set_error_buf_ex(error_buf, error_buf_size,
"Failed to allocate memory for declarations");
return false; return false;
} }
// Zero-initialize declarations array // Zero-initialize declarations array
memset(out->declarations, 0, sizeof(WASMComponentCoreModuleDecl) * count); memset(out->declarations, 0,
sizeof(WASMComponentCoreModuleDecl) * count);
for (uint32_t i = 0; i < count; i++) { for (uint32_t i = 0; i < count; i++) {
if (!parse_core_module_decl(&p, end, &out->declarations[i], error_buf, error_buf_size)) { if (!parse_core_module_decl(&p, end, &out->declarations[i],
error_buf, error_buf_size)) {
return false; return false;
} }
} }
@ -447,10 +568,15 @@ bool parse_core_moduletype(const uint8_t **payload, const uint8_t *end, WASMComp
return true; return true;
} }
bool parse_single_core_type(const uint8_t **payload, const uint8_t *end, WASMComponentCoreDefType *out, char *error_buf, uint32_t error_buf_size) { bool
parse_single_core_type(const uint8_t **payload, const uint8_t *end,
WASMComponentCoreDefType *out, char *error_buf,
uint32_t error_buf_size)
{
const uint8_t *p = *payload; const uint8_t *p = *payload;
if (p >= end) { if (p >= end) {
set_error_buf_ex(error_buf, error_buf_size, "Unexpected end while parsing core:deftype"); set_error_buf_ex(error_buf, error_buf_size,
"Unexpected end while parsing core:deftype");
return false; return false;
} }
@ -460,12 +586,15 @@ bool parse_single_core_type(const uint8_t **payload, const uint8_t *end, WASMCom
if (b0 == 0x50) { if (b0 == 0x50) {
p++; // consume 0x50 p++; // consume 0x50
out->tag = WASM_CORE_DEFTYPE_MODULETYPE; out->tag = WASM_CORE_DEFTYPE_MODULETYPE;
out->type.moduletype = wasm_runtime_malloc(sizeof(WASMComponentCoreModuleType)); out->type.moduletype =
wasm_runtime_malloc(sizeof(WASMComponentCoreModuleType));
if (!out->type.moduletype) { if (!out->type.moduletype) {
set_error_buf_ex(error_buf, error_buf_size, "OOM allocating core moduletype"); set_error_buf_ex(error_buf, error_buf_size,
"OOM allocating core moduletype");
return false; return false;
} }
if (!parse_core_moduletype(&p, end, out->type.moduletype, error_buf, error_buf_size)) { if (!parse_core_moduletype(&p, end, out->type.moduletype, error_buf,
error_buf_size)) {
return false; return false;
} }
*payload = p; *payload = p;
@ -474,42 +603,57 @@ bool parse_single_core_type(const uint8_t **payload, const uint8_t *end, WASMCom
// 2) rectype (GC): 0x4E ... // 2) rectype (GC): 0x4E ...
if (b0 == 0x4E) { if (b0 == 0x4E) {
set_error_buf_ex(error_buf, error_buf_size, "WebAssembly 3.0 core:rectype (0x4E ...) not supported"); set_error_buf_ex(
error_buf, error_buf_size,
"WebAssembly 3.0 core:rectype (0x4E ...) not supported");
return false; return false;
} }
// 3) subtype (GC): 0x00 followed by {0x50,0x4F,0x5E,0x5F,0x60} // 3) subtype (GC): 0x00 followed by {0x50,0x4F,0x5E,0x5F,0x60}
if (b0 == 0x00) { if (b0 == 0x00) {
if (p + 1 >= end) { if (p + 1 >= end) {
set_error_buf_ex(error_buf, error_buf_size, "Unexpected end of data after 0x00"); set_error_buf_ex(error_buf, error_buf_size,
"Unexpected end of data after 0x00");
return false; return false;
} }
uint8_t b1 = *(p + 1); uint8_t b1 = *(p + 1);
if (b1 == 0x50 || b1 == 0x4F || b1 == 0x5E || b1 == 0x5F || b1 == 0x60) { if (b1 == 0x50 || b1 == 0x4F || b1 == 0x5E || b1 == 0x5F
set_error_buf_ex(error_buf, error_buf_size, "WebAssembly 3.0 core:subtype (0x00 0x%02x ...) not supported", b1); || b1 == 0x60) {
set_error_buf_ex(
error_buf, error_buf_size,
"WebAssembly 3.0 core:subtype (0x00 0x%02x ...) not supported",
b1);
return false; return false;
} }
} }
// Otherwise invalid in this context // Otherwise invalid in this context
set_error_buf_ex(error_buf, error_buf_size, "Invalid core:deftype tag: %02x", b0); set_error_buf_ex(error_buf, error_buf_size,
"Invalid core:deftype tag: %02x", b0);
return false; return false;
} }
// Section 3: type section (component model type section, not the core wasm type section) // Section 3: type section (component model type section, not the core wasm type
bool wasm_component_parse_core_type_section(const uint8_t **payload, uint32_t payload_len, WASMComponentCoreTypeSection *out, char *error_buf, uint32_t error_buf_size, uint32_t *consumed_len) { // section)
bool
wasm_component_parse_core_type_section(const uint8_t **payload,
uint32_t payload_len,
WASMComponentCoreTypeSection *out,
char *error_buf, uint32_t error_buf_size,
uint32_t *consumed_len)
{
if (!payload || !*payload || payload_len == 0) { if (!payload || !*payload || payload_len == 0) {
return false; return false;
} }
if (consumed_len) *consumed_len = 0; if (consumed_len)
*consumed_len = 0;
const uint8_t *p = *payload; const uint8_t *p = *payload;
const uint8_t *end = *payload + payload_len; const uint8_t *end = *payload + payload_len;
uint64_t count_leb = 0; uint64_t count_leb = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &count_leb, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &count_leb, error_buf,
error_buf_size)) {
return false; return false;
} }
@ -519,19 +663,23 @@ bool wasm_component_parse_core_type_section(const uint8_t **payload, uint32_t pa
if (count > 0) { if (count > 0) {
out->types = wasm_runtime_malloc(sizeof(WASMComponentCoreType) * count); out->types = wasm_runtime_malloc(sizeof(WASMComponentCoreType) * count);
if (!out->types) { if (!out->types) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for types"); set_error_buf_ex(error_buf, error_buf_size,
"Failed to allocate memory for types");
return false; return false;
} }
memset(out->types, 0, sizeof(WASMComponentCoreType) * count); memset(out->types, 0, sizeof(WASMComponentCoreType) * count);
for (uint32_t i = 0; i < count; i++) { for (uint32_t i = 0; i < count; i++) {
WASMComponentCoreDefType *dt = wasm_runtime_malloc(sizeof(WASMComponentCoreDefType)); WASMComponentCoreDefType *dt =
wasm_runtime_malloc(sizeof(WASMComponentCoreDefType));
if (!dt) { if (!dt) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for core deftype"); set_error_buf_ex(error_buf, error_buf_size,
"Failed to allocate memory for core deftype");
return false; return false;
} }
memset(dt, 0, sizeof(WASMComponentCoreDefType)); memset(dt, 0, sizeof(WASMComponentCoreDefType));
if (!parse_single_core_type(&p, end, dt, error_buf, error_buf_size)) { if (!parse_single_core_type(&p, end, dt, error_buf,
error_buf_size)) {
wasm_runtime_free(dt); wasm_runtime_free(dt);
return false; return false;
} }
@ -539,17 +687,21 @@ bool wasm_component_parse_core_type_section(const uint8_t **payload, uint32_t pa
} }
} }
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return true; return true;
} }
// Individual section free functions // Individual section free functions
void wasm_component_free_core_type_section(WASMComponentSection *section) { void
wasm_component_free_core_type_section(WASMComponentSection *section)
{
if (!section || !section->parsed.core_type_section) { if (!section || !section->parsed.core_type_section) {
return; return;
} }
WASMComponentCoreTypeSection *core_type_section = section->parsed.core_type_section; WASMComponentCoreTypeSection *core_type_section =
section->parsed.core_type_section;
if (core_type_section->types) { if (core_type_section->types) {
for (uint32_t i = 0; i < core_type_section->count; i++) { for (uint32_t i = 0; i < core_type_section->count; i++) {
@ -566,7 +718,9 @@ void wasm_component_free_core_type_section(WASMComponentSection *section) {
} }
// Helper functions for freeing core structures // Helper functions for freeing core structures
void free_core_import_desc(WASMComponentCoreImportDesc *import_desc) { void
free_core_import_desc(WASMComponentCoreImportDesc *import_desc)
{
if (!import_desc) { if (!import_desc) {
return; return;
} }
@ -592,7 +746,9 @@ void free_core_import_desc(WASMComponentCoreImportDesc *import_desc) {
} }
} }
void free_core_import(WASMComponentCoreImport *import) { void
free_core_import(WASMComponentCoreImport *import)
{
if (!import) { if (!import) {
return; return;
} }
@ -613,7 +769,9 @@ void free_core_import(WASMComponentCoreImport *import) {
} }
} }
void free_core_export_decl(WASMComponentCoreExportDecl *export_decl) { void
free_core_export_decl(WASMComponentCoreExportDecl *export_decl)
{
if (!export_decl) { if (!export_decl) {
return; return;
} }
@ -629,7 +787,9 @@ void free_core_export_decl(WASMComponentCoreExportDecl *export_decl) {
} }
} }
void free_core_module_decl(WASMComponentCoreModuleDecl *module_decl) { void
free_core_module_decl(WASMComponentCoreModuleDecl *module_decl)
{
if (!module_decl) { if (!module_decl) {
return; return;
} }
@ -654,14 +814,17 @@ void free_core_module_decl(WASMComponentCoreModuleDecl *module_decl) {
break; break;
case WASM_CORE_MODULEDECL_EXPORT: case WASM_CORE_MODULEDECL_EXPORT:
if (module_decl->decl.export_decl.export_decl) { if (module_decl->decl.export_decl.export_decl) {
free_core_export_decl(module_decl->decl.export_decl.export_decl); free_core_export_decl(
module_decl->decl.export_decl.export_decl);
wasm_runtime_free(module_decl->decl.export_decl.export_decl); wasm_runtime_free(module_decl->decl.export_decl.export_decl);
} }
break; break;
} }
} }
void free_core_moduletype(WASMComponentCoreModuleType *moduletype) { void
free_core_moduletype(WASMComponentCoreModuleType *moduletype)
{
if (!moduletype) { if (!moduletype) {
return; return;
} }
@ -674,7 +837,9 @@ void free_core_moduletype(WASMComponentCoreModuleType *moduletype) {
} }
} }
void free_core_deftype(WASMComponentCoreDefType *deftype) { void
free_core_deftype(WASMComponentCoreDefType *deftype)
{
if (!deftype) { if (!deftype) {
return; return;
} }
@ -686,12 +851,12 @@ void free_core_deftype(WASMComponentCoreDefType *deftype) {
wasm_runtime_free(deftype->type.rectype); wasm_runtime_free(deftype->type.rectype);
} }
break; break;
case WASM_CORE_DEFTYPE_SUBTYPE: case WASM_CORE_DEFTYPE_SUBTYPE:
if (deftype->type.subtype) { if (deftype->type.subtype) {
free_core_module_subtype(deftype->type.subtype); free_core_module_subtype(deftype->type.subtype);
wasm_runtime_free(deftype->type.subtype); wasm_runtime_free(deftype->type.subtype);
} }
break; break;
case WASM_CORE_DEFTYPE_MODULETYPE: case WASM_CORE_DEFTYPE_MODULETYPE:
if (deftype->type.moduletype) { if (deftype->type.moduletype) {
free_core_moduletype(deftype->type.moduletype); free_core_moduletype(deftype->type.moduletype);
@ -701,7 +866,9 @@ void free_core_deftype(WASMComponentCoreDefType *deftype) {
} }
} }
void free_core_type(WASMComponentCoreType *type) { void
free_core_type(WASMComponentCoreType *type)
{
if (!type) { if (!type) {
return; return;
} }
@ -712,7 +879,9 @@ void free_core_type(WASMComponentCoreType *type) {
} }
} }
void free_core_type_section(WASMComponentCoreTypeSection *section) { void
free_core_type_section(WASMComponentCoreTypeSection *section)
{
if (!section) { if (!section) {
return; return;
} }
@ -726,7 +895,9 @@ void free_core_type_section(WASMComponentCoreTypeSection *section) {
} }
// Additional helper functions for freeing core structures // Additional helper functions for freeing core structures
void free_core_functype(WASMComponentCoreFuncType *functype) { void
free_core_functype(WASMComponentCoreFuncType *functype)
{
if (!functype) { if (!functype) {
return; return;
} }
@ -740,7 +911,9 @@ void free_core_functype(WASMComponentCoreFuncType *functype) {
} }
} }
void free_core_rectype(WASMComponentCoreRecType *rectype) { void
free_core_rectype(WASMComponentCoreRecType *rectype)
{
if (!rectype) { if (!rectype) {
return; return;
} }
@ -753,7 +926,9 @@ void free_core_rectype(WASMComponentCoreRecType *rectype) {
} }
} }
void free_core_resulttype(WASMComponentCoreResultType *resulttype) { void
free_core_resulttype(WASMComponentCoreResultType *resulttype)
{
if (!resulttype) { if (!resulttype) {
return; return;
} }
@ -763,7 +938,9 @@ void free_core_resulttype(WASMComponentCoreResultType *resulttype) {
} }
} }
void free_core_structtype(WASMComponentCoreStructType *structtype) { void
free_core_structtype(WASMComponentCoreStructType *structtype)
{
if (!structtype) { if (!structtype) {
return; return;
} }
@ -773,7 +950,9 @@ void free_core_structtype(WASMComponentCoreStructType *structtype) {
} }
} }
void free_core_comptype(WASMComponentCoreCompType *comptype) { void
free_core_comptype(WASMComponentCoreCompType *comptype)
{
if (!comptype) { if (!comptype) {
return; return;
} }
@ -793,7 +972,9 @@ void free_core_comptype(WASMComponentCoreCompType *comptype) {
} }
} }
void free_core_subtype(WASMComponentCoreSubType *subtype) { void
free_core_subtype(WASMComponentCoreSubType *subtype)
{
if (!subtype) { if (!subtype) {
return; return;
} }
@ -806,7 +987,9 @@ void free_core_subtype(WASMComponentCoreSubType *subtype) {
free_core_comptype(&subtype->comptype); free_core_comptype(&subtype->comptype);
} }
void free_core_module_subtype(WASMComponentCoreModuleSubType *module_subtype) { void
free_core_module_subtype(WASMComponentCoreModuleSubType *module_subtype)
{
if (!module_subtype) { if (!module_subtype) {
return; return;
} }

View File

@ -8,10 +8,14 @@
static bool is_component = false; static bool is_component = false;
bool is_component_runtime() { bool
is_component_runtime()
{
return is_component; return is_component;
} }
void set_component_runtime(bool type) { void
set_component_runtime(bool type)
{
is_component = type; is_component = type;
} }

View File

@ -8,7 +8,9 @@
#include "stdbool.h" #include "stdbool.h"
bool is_component_runtime(); bool
void set_component_runtime(bool type); is_component_runtime();
void
set_component_runtime(bool type);
#endif #endif

View File

@ -13,10 +13,18 @@
#include <stdio.h> #include <stdio.h>
// Section 11: exports section // Section 11: exports section
bool wasm_component_parse_exports_section(const uint8_t **payload, uint32_t payload_len,WASMComponentExportSection *out, char *error_buf, uint32_t error_buf_size, uint32_t *consumed_len){ bool
wasm_component_parse_exports_section(const uint8_t **payload,
uint32_t payload_len,
WASMComponentExportSection *out,
char *error_buf, uint32_t error_buf_size,
uint32_t *consumed_len)
{
if (!payload || !*payload || payload_len == 0 || !out) { if (!payload || !*payload || payload_len == 0 || !out) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid payload or output pointer"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = 0; "Invalid payload or output pointer");
if (consumed_len)
*consumed_len = 0;
return false; return false;
} }
@ -24,14 +32,19 @@ bool wasm_component_parse_exports_section(const uint8_t **payload, uint32_t payl
const uint8_t *end = *payload + payload_len; const uint8_t *end = *payload + payload_len;
if (p >= end) { if (p >= end) {
set_error_buf_ex(error_buf, error_buf_size, "Unexpected end of buffer when reading exports count"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Unexpected end of buffer when reading exports count");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
uint64_t export_count_leb = 0; uint64_t export_count_leb = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &export_count_leb, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &export_count_leb, error_buf,
set_error_buf_ex(error_buf, error_buf_size, "Failed to read exports count"); error_buf_size)) {
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); set_error_buf_ex(error_buf, error_buf_size,
"Failed to read exports count");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
@ -39,111 +52,156 @@ bool wasm_component_parse_exports_section(const uint8_t **payload, uint32_t payl
out->count = export_count; out->count = export_count;
if (export_count > 0) { if (export_count > 0) {
out->exports = wasm_runtime_malloc(sizeof(WASMComponentExport) * export_count); out->exports =
wasm_runtime_malloc(sizeof(WASMComponentExport) * export_count);
if (!out->exports) { if (!out->exports) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for exports"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Failed to allocate memory for exports");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Ensure all fields (including optional extern_desc) are initialized to NULL/0 // Ensure all fields (including optional extern_desc) are initialized to
// NULL/0
memset(out->exports, 0, sizeof(WASMComponentExport) * export_count); memset(out->exports, 0, sizeof(WASMComponentExport) * export_count);
// Parsing every export // Parsing every export
for (uint32_t i = 0; i < export_count; i++) { for (uint32_t i = 0; i < export_count; i++) {
// Parsing 'exportname' // Parsing 'exportname'
if (p >= end) { if (p >= end) {
set_error_buf_ex(error_buf, error_buf_size, "Unexpected end of buffer when reading export name for export %u", i); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Unexpected end of buffer when reading export "
"name for export %u",
i);
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
WASMComponentExportName *export_name = wasm_runtime_malloc(sizeof(WASMComponentExportName)); WASMComponentExportName *export_name =
wasm_runtime_malloc(sizeof(WASMComponentExportName));
if (!export_name) { if (!export_name) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for export_name"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Failed to allocate memory for export_name");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
bool status = parse_component_export_name(&p, end, export_name, error_buf, error_buf_size); bool status = parse_component_export_name(
&p, end, export_name, error_buf, error_buf_size);
if (!status) { if (!status) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to parse component name for export %u", i); set_error_buf_ex(error_buf, error_buf_size,
"Failed to parse component name for export %u",
i);
wasm_runtime_free(export_name); wasm_runtime_free(export_name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
out->exports[i].export_name = export_name; out->exports[i].export_name = export_name;
// Parsing 'sortidx' // Parsing 'sortidx'
out->exports[i].sort_idx = wasm_runtime_malloc(sizeof(WASMComponentSortIdx)); out->exports[i].sort_idx =
wasm_runtime_malloc(sizeof(WASMComponentSortIdx));
if (!out->exports[i].sort_idx) { if (!out->exports[i].sort_idx) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for sort_idx"); set_error_buf_ex(error_buf, error_buf_size,
"Failed to allocate memory for sort_idx");
wasm_runtime_free(export_name); wasm_runtime_free(export_name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
status = parse_sort_idx(&p, end, out->exports[i].sort_idx, error_buf, error_buf_size, false); status = parse_sort_idx(&p, end, out->exports[i].sort_idx,
error_buf, error_buf_size, false);
if (!status) { if (!status) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to parse sort_idx for export %u", i); set_error_buf_ex(error_buf, error_buf_size,
"Failed to parse sort_idx for export %u", i);
wasm_runtime_free(out->exports[i].sort_idx); wasm_runtime_free(out->exports[i].sort_idx);
wasm_runtime_free(export_name); wasm_runtime_free(export_name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
LOG_DEBUG("Export section: name = \"%s\", sort idx = %d\n", out->exports[i].export_name->exported.simple.name->name, out->exports[i].sort_idx->sort->sort); LOG_DEBUG("Export section: name = \"%s\", sort idx = %d\n",
out->exports[i].export_name->exported.simple.name->name,
out->exports[i].sort_idx->sort->sort);
// Parsing 'externdesc' (OPTIONAL) // Parsing 'externdesc' (OPTIONAL)
if (p >= end) { if (p >= end) {
LOG_DEBUG("Parsing Extern desc\n"); LOG_DEBUG("Parsing Extern desc\n");
set_error_buf_ex(error_buf, error_buf_size, "Unexpected end of buffer when reading optional extern_desc for export %u", i); set_error_buf_ex(error_buf, error_buf_size,
"Unexpected end of buffer when reading "
"optional extern_desc for export %u",
i);
wasm_runtime_free(out->exports[i].sort_idx->sort); wasm_runtime_free(out->exports[i].sort_idx->sort);
wasm_runtime_free(out->exports[i].sort_idx); wasm_runtime_free(out->exports[i].sort_idx);
wasm_runtime_free(export_name); wasm_runtime_free(export_name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
uint8_t opt_extern_desc = *p++; uint8_t opt_extern_desc = *p++;
if (opt_extern_desc == WASM_COMP_OPTIONAL_TRUE) { if (opt_extern_desc == WASM_COMP_OPTIONAL_TRUE) {
if (p >= end) { if (p >= end) {
set_error_buf_ex(error_buf, error_buf_size, "Unexpected end of buffer when parsing extern_desc for export %u", i); set_error_buf_ex(error_buf, error_buf_size,
"Unexpected end of buffer when parsing "
"extern_desc for export %u",
i);
wasm_runtime_free(out->exports[i].sort_idx->sort); wasm_runtime_free(out->exports[i].sort_idx->sort);
wasm_runtime_free(out->exports[i].sort_idx); wasm_runtime_free(out->exports[i].sort_idx);
wasm_runtime_free(export_name); wasm_runtime_free(export_name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
WASMComponentExternDesc *extern_desc = wasm_runtime_malloc(sizeof(WASMComponentExternDesc)); WASMComponentExternDesc *extern_desc =
bool extern_status = parse_extern_desc(&p, end, extern_desc, error_buf, error_buf_size); wasm_runtime_malloc(sizeof(WASMComponentExternDesc));
bool extern_status = parse_extern_desc(
&p, end, extern_desc, error_buf, error_buf_size);
if (!extern_status) { if (!extern_status) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to parse extern_desc for export %u", i); set_error_buf_ex(
error_buf, error_buf_size,
"Failed to parse extern_desc for export %u", i);
wasm_runtime_free(extern_desc); wasm_runtime_free(extern_desc);
wasm_runtime_free(out->exports[i].sort_idx->sort); wasm_runtime_free(out->exports[i].sort_idx->sort);
wasm_runtime_free(out->exports[i].sort_idx); wasm_runtime_free(out->exports[i].sort_idx);
wasm_runtime_free(export_name); wasm_runtime_free(export_name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
out->exports[i].extern_desc = extern_desc; out->exports[i].extern_desc = extern_desc;
LOG_DEBUG("Extern desc added\n"); LOG_DEBUG("Extern desc added\n");
} else if (opt_extern_desc == WASM_COMP_OPTIONAL_FALSE) { }
else if (opt_extern_desc == WASM_COMP_OPTIONAL_FALSE) {
// Explicitly mark absence of extern_desc // Explicitly mark absence of extern_desc
out->exports[i].extern_desc = NULL; out->exports[i].extern_desc = NULL;
LOG_DEBUG("Extern desc set to NULL\n"); LOG_DEBUG("Extern desc set to NULL\n");
} else { }
set_error_buf_ex(error_buf, error_buf_size, "Malformed binary: invalid optional tag 0x%02x", opt_extern_desc); else {
set_error_buf_ex(
error_buf, error_buf_size,
"Malformed binary: invalid optional tag 0x%02x",
opt_extern_desc);
return false; return false;
} }
} }
} }
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return true; return true;
} }
// Individual section free functions // Individual section free functions
void wasm_component_free_exports_section(WASMComponentSection *section) { void
if (!section || !section->parsed.export_section) return; wasm_component_free_exports_section(WASMComponentSection *section)
{
if (!section || !section->parsed.export_section)
return;
WASMComponentExportSection *export_sec = section->parsed.export_section; WASMComponentExportSection *export_sec = section->parsed.export_section;
if (export_sec->exports) { if (export_sec->exports) {

File diff suppressed because it is too large Load Diff

View File

@ -13,10 +13,18 @@
#include <stdio.h> #include <stdio.h>
// Section 10: imports section // Section 10: imports section
bool wasm_component_parse_imports_section(const uint8_t **payload, uint32_t payload_len, WASMComponentImportSection *out, char *error_buf, uint32_t error_buf_size, uint32_t *consumed_len) { bool
wasm_component_parse_imports_section(const uint8_t **payload,
uint32_t payload_len,
WASMComponentImportSection *out,
char *error_buf, uint32_t error_buf_size,
uint32_t *consumed_len)
{
if (!payload || !*payload || payload_len == 0 || !out) { if (!payload || !*payload || payload_len == 0 || !out) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid payload or output pointer"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = 0; "Invalid payload or output pointer");
if (consumed_len)
*consumed_len = 0;
return false; return false;
} }
@ -26,8 +34,10 @@ bool wasm_component_parse_imports_section(const uint8_t **payload, uint32_t payl
// import ::= in:<importname'> ed:<externdesc> => (import in ed) // import ::= in:<importname'> ed:<externdesc> => (import in ed)
// Read the count of imports (LEB128-encoded) // Read the count of imports (LEB128-encoded)
uint64_t import_count_leb = 0; uint64_t import_count_leb = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &import_count_leb, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &import_count_leb, error_buf,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); error_buf_size)) {
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
@ -35,10 +45,13 @@ bool wasm_component_parse_imports_section(const uint8_t **payload, uint32_t payl
out->count = import_count; out->count = import_count;
if (import_count > 0) { if (import_count > 0) {
out->imports = wasm_runtime_malloc(sizeof(WASMComponentImport) * import_count); out->imports =
wasm_runtime_malloc(sizeof(WASMComponentImport) * import_count);
if (!out->imports) { if (!out->imports) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for imports"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Failed to allocate memory for imports");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
@ -46,49 +59,67 @@ bool wasm_component_parse_imports_section(const uint8_t **payload, uint32_t payl
memset(out->imports, 0, sizeof(WASMComponentImport) * import_count); memset(out->imports, 0, sizeof(WASMComponentImport) * import_count);
for (uint32_t i = 0; i < import_count; ++i) { for (uint32_t i = 0; i < import_count; ++i) {
// importname' ::= 0x00 len:<u32> in:<importname> => in (if len = |in|) // importname' ::= 0x00 len:<u32> in:<importname> => in (if len =
// | 0x01 len:<u32> in:<importname> vs:<versionsuffix'> => in vs (if len = |in|) // |in|)
// | 0x01 len:<u32> in:<importname> vs:<versionsuffix'>
// => in vs (if len = |in|)
// Parse import name (simple or versioned) // Parse import name (simple or versioned)
WASMComponentImportName *import_name = wasm_runtime_malloc(sizeof(WASMComponentImportName)); WASMComponentImportName *import_name =
wasm_runtime_malloc(sizeof(WASMComponentImportName));
if (!import_name) { if (!import_name) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for import_name"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Failed to allocate memory for import_name");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Initialize the struct to zero to avoid garbage data // Initialize the struct to zero to avoid garbage data
memset(import_name, 0, sizeof(WASMComponentImportName)); memset(import_name, 0, sizeof(WASMComponentImportName));
bool status = parse_component_import_name(&p, end, import_name, error_buf, error_buf_size); bool status = parse_component_import_name(
&p, end, import_name, error_buf, error_buf_size);
if (!status) { if (!status) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to parse component name for import %u", i); set_error_buf_ex(error_buf, error_buf_size,
"Failed to parse component name for import %u",
i);
wasm_runtime_free(import_name); wasm_runtime_free(import_name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// externdesc ::= 0x00 0x11 i:<core:typeidx> => (core module (type i)) // externdesc ::= 0x00 0x11 i:<core:typeidx> => (core module (type
// i))
// | 0x01 i:<typeidx> => (func (type i)) // | 0x01 i:<typeidx> => (func (type i))
// | 0x02 b:<valuebound> => (value b) // | 0x02 b:<valuebound> => (value b)
// | 0x03 b:<typebound> => (type b) // | 0x03 b:<typebound> => (type b)
// | 0x04 i:<typeidx> => (component (type i)) // | 0x04 i:<typeidx> => (component (type i))
// | 0x05 i:<typeidx> => (instance (type i)) // | 0x05 i:<typeidx> => (instance (type i))
// Parse externdesc (core module, func, value, type, component, instance) // Parse externdesc (core module, func, value, type, component,
WASMComponentExternDesc *extern_desc = wasm_runtime_malloc(sizeof(WASMComponentExternDesc)); // instance)
WASMComponentExternDesc *extern_desc =
wasm_runtime_malloc(sizeof(WASMComponentExternDesc));
if (!extern_desc) { if (!extern_desc) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for extern_desc"); set_error_buf_ex(error_buf, error_buf_size,
"Failed to allocate memory for extern_desc");
wasm_runtime_free(import_name); wasm_runtime_free(import_name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Initialize the struct to zero to avoid garbage data // Initialize the struct to zero to avoid garbage data
memset(extern_desc, 0, sizeof(WASMComponentExternDesc)); memset(extern_desc, 0, sizeof(WASMComponentExternDesc));
status = parse_extern_desc(&p, end, extern_desc, error_buf, error_buf_size); status = parse_extern_desc(&p, end, extern_desc, error_buf,
error_buf_size);
if (!status) { if (!status) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to parse extern_desc for import %u", i); set_error_buf_ex(error_buf, error_buf_size,
"Failed to parse extern_desc for import %u",
i);
wasm_runtime_free(extern_desc); wasm_runtime_free(extern_desc);
wasm_runtime_free(import_name); wasm_runtime_free(import_name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
@ -98,13 +129,17 @@ bool wasm_component_parse_imports_section(const uint8_t **payload, uint32_t payl
} }
} }
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return true; return true;
} }
// Individual section free functions // Individual section free functions
void wasm_component_free_imports_section(WASMComponentSection *section) { void
if (!section || !section->parsed.import_section) return; wasm_component_free_imports_section(WASMComponentSection *section)
{
if (!section || !section->parsed.import_section)
return;
WASMComponentImportSection *import_sec = section->parsed.import_section; WASMComponentImportSection *import_sec = section->parsed.import_section;
if (import_sec->imports) { if (import_sec->imports) {

View File

@ -14,12 +14,20 @@
// Section 5: instances section // Section 5: instances section
// Binary.md: instance ::= ie:<instanceexpr> => (instance ie) // Binary.md: instance ::= ie:<instanceexpr> => (instance ie)
// instanceexpr ::= 0x00 c:<componentidx> arg*:vec(<instantiatearg>) => (instantiate c arg*) // instanceexpr ::= 0x00 c:<componentidx> arg*:vec(<instantiatearg>) =>
// instantiatearg ::= n:<name> si:<sortidx> => (with n si) // (instantiate c arg*) instantiatearg ::= n:<name> si:<sortidx> => (with n si)
bool wasm_component_parse_instances_section(const uint8_t **payload, uint32_t payload_len, WASMComponentInstSection *out, char *error_buf, uint32_t error_buf_size, uint32_t *consumed_len) { bool
wasm_component_parse_instances_section(const uint8_t **payload,
uint32_t payload_len,
WASMComponentInstSection *out,
char *error_buf, uint32_t error_buf_size,
uint32_t *consumed_len)
{
if (!payload || !*payload || payload_len == 0 || !out) { if (!payload || !*payload || payload_len == 0 || !out) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid payload or output pointer"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = 0; "Invalid payload or output pointer");
if (consumed_len)
*consumed_len = 0;
return false; return false;
} }
@ -27,17 +35,22 @@ bool wasm_component_parse_instances_section(const uint8_t **payload, uint32_t pa
const uint8_t *end = *payload + payload_len; const uint8_t *end = *payload + payload_len;
uint64_t instance_count = 0; uint64_t instance_count = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &instance_count, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &instance_count, error_buf,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); error_buf_size)) {
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
out->count = (uint32_t)instance_count; out->count = (uint32_t)instance_count;
if (instance_count > 0) { if (instance_count > 0) {
out->instances = wasm_runtime_malloc(sizeof(WASMComponentInst) * instance_count); out->instances =
wasm_runtime_malloc(sizeof(WASMComponentInst) * instance_count);
if (!out->instances) { if (!out->instances) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for instances"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Failed to allocate memory for instances");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
@ -47,162 +60,248 @@ bool wasm_component_parse_instances_section(const uint8_t **payload, uint32_t pa
for (uint32_t i = 0; i < instance_count; ++i) { for (uint32_t i = 0; i < instance_count; ++i) {
// Check bounds before reading tag // Check bounds before reading tag
if (p >= end) { if (p >= end) {
set_error_buf_ex(error_buf, error_buf_size, "Buffer overflow when reading instance tag"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Buffer overflow when reading instance tag");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
uint8_t tag = *p++; uint8_t tag = *p++;
out->instances[i].instance_expression_tag = tag; out->instances[i].instance_expression_tag = tag;
switch (tag) { switch (tag) {
case WASM_COMP_INSTANCE_EXPRESSION_WITH_ARGS: { case WASM_COMP_INSTANCE_EXPRESSION_WITH_ARGS:
{
// 0x00 c:<componentidx> arg*:vec(<instantiatearg>) // 0x00 c:<componentidx> arg*:vec(<instantiatearg>)
uint64_t component_idx = 0; uint64_t component_idx = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &component_idx, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); &component_idx, error_buf, error_buf_size)) {
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
out->instances[i].expression.with_args.idx = (uint32_t)component_idx; out->instances[i].expression.with_args.idx =
(uint32_t)component_idx;
uint64_t arg_len = 0; uint64_t arg_len = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &arg_len, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &arg_len,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); error_buf, error_buf_size)) {
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
out->instances[i].expression.with_args.arg_len = (uint32_t)arg_len; out->instances[i].expression.with_args.arg_len =
(uint32_t)arg_len;
if (arg_len > 0) { if (arg_len > 0) {
out->instances[i].expression.with_args.args = wasm_runtime_malloc(sizeof(WASMComponentInstArg) * arg_len); out->instances[i].expression.with_args.args =
wasm_runtime_malloc(sizeof(WASMComponentInstArg)
* arg_len);
if (!out->instances[i].expression.with_args.args) { if (!out->instances[i].expression.with_args.args) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for component instantiate args"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Failed to allocate memory for "
"component instantiate args");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Initialize args to zero // Initialize args to zero
memset(out->instances[i].expression.with_args.args, 0, sizeof(WASMComponentInstArg) * arg_len); memset(out->instances[i].expression.with_args.args, 0,
sizeof(WASMComponentInstArg) * arg_len);
for (uint32_t j = 0; j < arg_len; ++j) { for (uint32_t j = 0; j < arg_len; ++j) {
// Parse core:name (LEB128 length + UTF-8 bytes) // Parse core:name (LEB128 length + UTF-8 bytes)
WASMComponentCoreName *core_name = NULL; WASMComponentCoreName *core_name = NULL;
if (!parse_core_name(&p, end, &core_name, error_buf, error_buf_size)) { if (!parse_core_name(&p, end, &core_name, error_buf,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); error_buf_size)) {
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Store the name in the instantiate arg structure // Store the name in the instantiate arg structure
out->instances[i].expression.with_args.args[j].name = core_name; out->instances[i]
.expression.with_args.args[j]
.name = core_name;
// si:<sortidx> - this is a component-level sort index (non-core) // si:<sortidx> - this is a component-level sort
out->instances[i].expression.with_args.args[j].idx.sort_idx = wasm_runtime_malloc(sizeof(WASMComponentSortIdx)); // index (non-core)
if (!out->instances[i].expression.with_args.args[j].idx.sort_idx) { out->instances[i]
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for component arg sort idx"); .expression.with_args.args[j]
.idx.sort_idx = wasm_runtime_malloc(
sizeof(WASMComponentSortIdx));
if (!out->instances[i]
.expression.with_args.args[j]
.idx.sort_idx) {
set_error_buf_ex(error_buf, error_buf_size,
"Failed to allocate memory "
"for component arg sort idx");
free_core_name(core_name); free_core_name(core_name);
wasm_runtime_free(core_name); wasm_runtime_free(core_name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Zero-initialize sort_idx // Zero-initialize sort_idx
memset(out->instances[i].expression.with_args.args[j].idx.sort_idx, 0, sizeof(WASMComponentSortIdx)); memset(out->instances[i]
.expression.with_args.args[j]
.idx.sort_idx,
0, sizeof(WASMComponentSortIdx));
// Parse component sort index // Parse component sort index
bool status = parse_sort_idx(&p, end, out->instances[i].expression.with_args.args[j].idx.sort_idx, error_buf, error_buf_size, false); bool status = parse_sort_idx(
&p, end,
out->instances[i]
.expression.with_args.args[j]
.idx.sort_idx,
error_buf, error_buf_size, false);
if (!status) { if (!status) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to parse component arg sort idx"); set_error_buf_ex(
error_buf, error_buf_size,
"Failed to parse component arg sort idx");
free_core_name(core_name); free_core_name(core_name);
wasm_runtime_free(core_name); wasm_runtime_free(core_name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
} }
} else { }
else {
out->instances[i].expression.with_args.args = NULL; out->instances[i].expression.with_args.args = NULL;
} }
break; break;
} }
case WASM_COMP_INSTANCE_EXPRESSION_WITHOUT_ARGS: { case WASM_COMP_INSTANCE_EXPRESSION_WITHOUT_ARGS:
{
// 0x01 e*:vec(<inlineexport>) => e* // 0x01 e*:vec(<inlineexport>) => e*
uint64_t inline_expr_len = 0; uint64_t inline_expr_len = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &inline_expr_len, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); &inline_expr_len, error_buf,
error_buf_size)) {
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
out->instances[i].expression.without_args.inline_expr_len = (uint32_t)inline_expr_len; out->instances[i].expression.without_args.inline_expr_len =
(uint32_t)inline_expr_len;
if (inline_expr_len > 0) { if (inline_expr_len > 0) {
out->instances[i].expression.without_args.inline_expr = wasm_runtime_malloc(sizeof(WASMComponentInlineExport) * inline_expr_len); out->instances[i].expression.without_args.inline_expr =
if (!out->instances[i].expression.without_args.inline_expr) { wasm_runtime_malloc(
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for component inline exports"); sizeof(WASMComponentInlineExport)
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); * inline_expr_len);
if (!out->instances[i]
.expression.without_args.inline_expr) {
set_error_buf_ex(error_buf, error_buf_size,
"Failed to allocate memory for "
"component inline exports");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Initialize inline exports to zero // Initialize inline exports to zero
memset(out->instances[i].expression.without_args.inline_expr, 0, sizeof(WASMComponentInlineExport) * inline_expr_len); memset(out->instances[i]
.expression.without_args.inline_expr,
0,
sizeof(WASMComponentInlineExport)
* inline_expr_len);
for (uint32_t j = 0; j < inline_expr_len; j++) { for (uint32_t j = 0; j < inline_expr_len; j++) {
// inlineexport ::= n:<exportname> si:<sortidx> // inlineexport ::= n:<exportname> si:<sortidx>
WASMComponentCoreName *name = wasm_runtime_malloc(sizeof(WASMComponentCoreName)); WASMComponentCoreName *name = wasm_runtime_malloc(
sizeof(WASMComponentCoreName));
if (!name) { if (!name) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for component export name"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Failed to allocate memory "
"for component export name");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Parse export name (component-level name) // Parse export name (component-level name)
bool name_parse_success = parse_core_name(&p, end, &name, error_buf, error_buf_size); bool name_parse_success = parse_core_name(
&p, end, &name, error_buf, error_buf_size);
if (!name_parse_success) { if (!name_parse_success) {
free_core_name(name); free_core_name(name);
wasm_runtime_free(name); wasm_runtime_free(name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
out->instances[i].expression.without_args.inline_expr[j].name = name; out->instances[i]
.expression.without_args.inline_expr[j]
.name = name;
// Parse component sort index // Parse component sort index
WASMComponentSortIdx *sort_idx = wasm_runtime_malloc(sizeof(WASMComponentSortIdx)); WASMComponentSortIdx *sort_idx =
wasm_runtime_malloc(
sizeof(WASMComponentSortIdx));
if (!sort_idx) { if (!sort_idx) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for component sort idx"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Failed to allocate memory "
"for component sort idx");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
// Zero-initialize sort_idx // Zero-initialize sort_idx
memset(sort_idx, 0, sizeof(WASMComponentSortIdx)); memset(sort_idx, 0, sizeof(WASMComponentSortIdx));
bool status = parse_sort_idx(&p, end, sort_idx, error_buf, error_buf_size, false); bool status =
parse_sort_idx(&p, end, sort_idx, error_buf,
error_buf_size, false);
if (!status) { if (!status) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to parse component sort idx"); set_error_buf_ex(
error_buf, error_buf_size,
"Failed to parse component sort idx");
wasm_runtime_free(sort_idx); wasm_runtime_free(sort_idx);
free_core_name(name); free_core_name(name);
wasm_runtime_free(name); wasm_runtime_free(name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
out->instances[i].expression.without_args.inline_expr[j].sort_idx = sort_idx; out->instances[i]
.expression.without_args.inline_expr[j]
.sort_idx = sort_idx;
} }
} else { }
out->instances[i].expression.without_args.inline_expr = NULL; else {
out->instances[i].expression.without_args.inline_expr =
NULL;
} }
break; break;
} }
default: { default:
set_error_buf_ex(error_buf, error_buf_size, "Unknown instance expression tag: 0x%02X", tag); {
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); set_error_buf_ex(error_buf, error_buf_size,
"Unknown instance expression tag: 0x%02X",
tag);
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
} }
} }
} }
if (consumed_len) *consumed_len = payload_len; if (consumed_len)
*consumed_len = payload_len;
return true; return true;
} }
// Individual section free functions // Individual section free functions
void wasm_component_free_instances_section(WASMComponentSection *section) { void
if (!section || !section->parsed.instance_section) return; wasm_component_free_instances_section(WASMComponentSection *section)
{
if (!section || !section->parsed.instance_section)
return;
WASMComponentInstSection *instance_sec = section->parsed.instance_section; WASMComponentInstSection *instance_sec = section->parsed.instance_section;
if (instance_sec->instances) { if (instance_sec->instances) {
@ -212,8 +311,10 @@ void wasm_component_free_instances_section(WASMComponentSection *section) {
switch (instance->instance_expression_tag) { switch (instance->instance_expression_tag) {
case WASM_COMP_INSTANCE_EXPRESSION_WITH_ARGS: case WASM_COMP_INSTANCE_EXPRESSION_WITH_ARGS:
if (instance->expression.with_args.args) { if (instance->expression.with_args.args) {
for (uint32_t k = 0; k < instance->expression.with_args.arg_len; ++k) { for (uint32_t k = 0;
WASMComponentInstArg *arg = &instance->expression.with_args.args[k]; k < instance->expression.with_args.arg_len; ++k) {
WASMComponentInstArg *arg =
&instance->expression.with_args.args[k];
// Free component name // Free component name
if (arg->name) { if (arg->name) {
@ -239,8 +340,13 @@ void wasm_component_free_instances_section(WASMComponentSection *section) {
case WASM_COMP_INSTANCE_EXPRESSION_WITHOUT_ARGS: case WASM_COMP_INSTANCE_EXPRESSION_WITHOUT_ARGS:
if (instance->expression.without_args.inline_expr) { if (instance->expression.without_args.inline_expr) {
for (uint32_t k = 0; k < instance->expression.without_args.inline_expr_len; ++k) { for (uint32_t k = 0;
WASMComponentInlineExport *inline_export = &instance->expression.without_args.inline_expr[k]; k < instance->expression.without_args
.inline_expr_len;
++k) {
WASMComponentInlineExport *inline_export =
&instance->expression.without_args
.inline_expr[k];
// Free component export name // Free component export name
if (inline_export->name) { if (inline_export->name) {
@ -252,14 +358,16 @@ void wasm_component_free_instances_section(WASMComponentSection *section) {
// Free component sort index // Free component sort index
if (inline_export->sort_idx) { if (inline_export->sort_idx) {
if (inline_export->sort_idx->sort) { if (inline_export->sort_idx->sort) {
wasm_runtime_free(inline_export->sort_idx->sort); wasm_runtime_free(
inline_export->sort_idx->sort);
inline_export->sort_idx->sort = NULL; inline_export->sort_idx->sort = NULL;
} }
wasm_runtime_free(inline_export->sort_idx); wasm_runtime_free(inline_export->sort_idx);
inline_export->sort_idx = NULL; inline_export->sort_idx = NULL;
} }
} }
wasm_runtime_free(instance->expression.without_args.inline_expr); wasm_runtime_free(
instance->expression.without_args.inline_expr);
instance->expression.without_args.inline_expr = NULL; instance->expression.without_args.inline_expr = NULL;
} }
break; break;

View File

@ -13,8 +13,15 @@
#include <stdio.h> #include <stdio.h>
// Section 9: start section // Section 9: start section
bool wasm_component_parse_start_section(const uint8_t **payload, uint32_t payload_len, WASMComponentStartSection *out, char *error_buf, uint32_t error_buf_size, uint32_t *consumed_len) { bool
if (consumed_len) *consumed_len = 0; wasm_component_parse_start_section(const uint8_t **payload,
uint32_t payload_len,
WASMComponentStartSection *out,
char *error_buf, uint32_t error_buf_size,
uint32_t *consumed_len)
{
if (consumed_len)
*consumed_len = 0;
if (!payload || !*payload || !out || payload_len == 0) { if (!payload || !*payload || !out || payload_len == 0) {
return false; return false;
} }
@ -29,15 +36,18 @@ bool wasm_component_parse_start_section(const uint8_t **payload, uint32_t payloa
out->result = 0; out->result = 0;
uint64_t func_idx = 0; uint64_t func_idx = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &func_idx, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &func_idx, error_buf,
error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to read func idx"); set_error_buf_ex(error_buf, error_buf_size, "Failed to read func idx");
return false; return false;
} }
out->func_idx = (uint32_t)func_idx; out->func_idx = (uint32_t)func_idx;
uint64_t args_count = 0; uint64_t args_count = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &args_count, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &args_count, error_buf,
set_error_buf_ex(error_buf, error_buf_size, "Failed to read args count"); error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size,
"Failed to read args count");
return false; return false;
} }
out->value_args_count = (uint32_t)args_count; out->value_args_count = (uint32_t)args_count;
@ -45,14 +55,17 @@ bool wasm_component_parse_start_section(const uint8_t **payload, uint32_t payloa
if (args_count > 0) { if (args_count > 0) {
out->value_args = wasm_runtime_malloc(sizeof(uint32_t) * args_count); out->value_args = wasm_runtime_malloc(sizeof(uint32_t) * args_count);
if (!out->value_args) { if (!out->value_args) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for value args"); set_error_buf_ex(error_buf, error_buf_size,
"Failed to allocate memory for value args");
return false; return false;
} }
for (uint64_t i = 0; i < args_count; i++) { for (uint64_t i = 0; i < args_count; i++) {
uint64_t value_idx = 0; uint64_t value_idx = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &value_idx, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &value_idx, error_buf,
set_error_buf_ex(error_buf, error_buf_size, "Failed to read value idx"); error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size,
"Failed to read value idx");
// cleanup // cleanup
wasm_runtime_free(out->value_args); wasm_runtime_free(out->value_args);
out->value_args = NULL; out->value_args = NULL;
@ -64,8 +77,10 @@ bool wasm_component_parse_start_section(const uint8_t **payload, uint32_t payloa
} }
uint64_t result_leb = 0; uint64_t result_leb = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &result_leb, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &result_leb, error_buf,
set_error_buf_ex(error_buf, error_buf_size, "Failed to read result count"); error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size,
"Failed to read result count");
if (out->value_args) { if (out->value_args) {
wasm_runtime_free(out->value_args); wasm_runtime_free(out->value_args);
out->value_args = NULL; out->value_args = NULL;
@ -75,12 +90,15 @@ bool wasm_component_parse_start_section(const uint8_t **payload, uint32_t payloa
} }
out->result = (uint32_t)result_leb; out->result = (uint32_t)result_leb;
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return true; return true;
} }
// Individual section free functions // Individual section free functions
void wasm_component_free_start_section(WASMComponentSection *section) { void
wasm_component_free_start_section(WASMComponentSection *section)
{
if (!section || !section->parsed.start_section) { if (!section || !section->parsed.start_section) {
return; return;
} }

File diff suppressed because it is too large Load Diff

View File

@ -20,9 +20,9 @@ typedef struct WASMComponentValidationContext {
uint32_t core_module_count; uint32_t core_module_count;
uint32_t core_instance_count; uint32_t core_instance_count;
uint32_t core_table_count; uint32_t core_table_count;
uint32_t core_memory_count; // needed for canon memory opts uint32_t core_memory_count; // needed for canon memory opts
uint32_t core_global_count; uint32_t core_global_count;
uint32_t core_func_count; // needed for canon realloc/post-return checks uint32_t core_func_count; // needed for canon realloc/post-return checks
struct WASMComponentValidationContext *parent; struct WASMComponentValidationContext *parent;
@ -30,27 +30,31 @@ typedef struct WASMComponentValidationContext {
HashMap *import_names; HashMap *import_names;
HashMap *export_names; HashMap *export_names;
// Flat type lookup array: types[i] is the WASMComponentTypes* for type index i // Flat type lookup array: types[i] is the WASMComponentTypes* for type
// NULL for types introduced via import or alias // index i NULL for types introduced via import or alias type_is_local[i] is
// type_is_local[i] is true if the type was defined in a local type section // true if the type was defined in a local type section
WASMComponentTypes **types; WASMComponentTypes **types;
bool *type_is_local; bool *type_is_local;
uint32_t types_capacity; uint32_t types_capacity;
// Consumption tracking: value_consumed[i] is true once value i has been consumed exactly once // Consumption tracking: value_consumed[i] is true once value i has been
// consumed exactly once
bool *value_consumed; bool *value_consumed;
uint32_t value_consumed_capacity; uint32_t value_consumed_capacity;
// Func-to-type tracking: func_type_indexes[i] is the type index for function i // Func-to-type tracking: func_type_indexes[i] is the type index for
// UINT32_MAX for functions whose type is unknown (e.g. aliased) // function i UINT32_MAX for functions whose type is unknown (e.g. aliased)
uint32_t *func_type_indexes; uint32_t *func_type_indexes;
uint32_t func_type_indexes_capacity; uint32_t func_type_indexes_capacity;
// Resource type names: tracks import/export names that introduce resource types // Resource type names: tracks import/export names that introduce resource
// Used for [static] annotation validation // types Used for [static] annotation validation
HashMap *resource_type_names; HashMap *resource_type_names;
} WASMComponentValidationContext; } WASMComponentValidationContext;
bool wasm_component_validate(WASMComponent *comp, WASMComponentValidationContext *parent, char *error_buf, uint32_t error_buf_size); bool
wasm_component_validate(WASMComponent *comp,
WASMComponentValidationContext *parent, char *error_buf,
uint32_t error_buf_size);
#endif #endif

View File

@ -14,26 +14,33 @@
// Helper function to parse a value // Helper function to parse a value
// Helper to check if f32 bytes represent canonical NaN // Helper to check if f32 bytes represent canonical NaN
static bool is_canonical_f32_nan(const uint8_t *bytes) { static bool
return bytes[0] == 0x00 && bytes[1] == 0x00 && is_canonical_f32_nan(const uint8_t *bytes)
bytes[2] == 0xC0 && bytes[3] == 0x7F; {
return bytes[0] == 0x00 && bytes[1] == 0x00 && bytes[2] == 0xC0
&& bytes[3] == 0x7F;
} }
// Helper to check if f64 bytes represent canonical NaN // Helper to check if f64 bytes represent canonical NaN
static bool is_canonical_f64_nan(const uint8_t *bytes) { static bool
return bytes[0] == 0x00 && bytes[1] == 0x00 && bytes[2] == 0x00 && is_canonical_f64_nan(const uint8_t *bytes)
bytes[3] == 0x00 && bytes[4] == 0x00 && bytes[5] == 0x00 && {
bytes[6] == 0xF8 && bytes[7] == 0x7F; return bytes[0] == 0x00 && bytes[1] == 0x00 && bytes[2] == 0x00
&& bytes[3] == 0x00 && bytes[4] == 0x00 && bytes[5] == 0x00
&& bytes[6] == 0xF8 && bytes[7] == 0x7F;
} }
// Helper to check if f32/f64 bytes represent any NaN (for rejection) // Helper to check if f32/f64 bytes represent any NaN (for rejection)
static bool is_any_nan(const uint8_t *bytes, bool is_f64) { static bool
is_any_nan(const uint8_t *bytes, bool is_f64)
{
if (is_f64) { if (is_f64) {
// Check f64 NaN pattern (exponent all 1s, mantissa non-zero) // Check f64 NaN pattern (exponent all 1s, mantissa non-zero)
uint64_t bits = 0; uint64_t bits = 0;
memcpy(&bits, bytes, 8); memcpy(&bits, bytes, 8);
return ((bits >> 52) & 0x7FF) == 0x7FF && (bits & 0xFFFFFFFFFFFFF) != 0; return ((bits >> 52) & 0x7FF) == 0x7FF && (bits & 0xFFFFFFFFFFFFF) != 0;
} else { }
else {
// Check f32 NaN pattern (exponent all 1s, mantissa non-zero) // Check f32 NaN pattern (exponent all 1s, mantissa non-zero)
uint32_t bits = 0; uint32_t bits = 0;
memcpy(&bits, bytes, 4); memcpy(&bits, bytes, 4);
@ -41,15 +48,20 @@ static bool is_any_nan(const uint8_t *bytes, bool is_f64) {
} }
} }
// value ::= t:<valtype> len:<core:u32> v:<val(t)> => (value t v) (where len = ||v||) // value ::= t:<valtype> len:<core:u32> v:<val(t)> => (value t v) (where len =
static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMComponentValue *out, char *error_buf, uint32_t error_buf_size) { // ||v||)
static bool
parse_value(const uint8_t **payload, const uint8_t *end,
WASMComponentValue *out, char *error_buf, uint32_t error_buf_size)
{
const uint8_t *p = *payload; const uint8_t *p = *payload;
// Parse the value type // Parse the value type
WASMComponentValueType *val_type = NULL; WASMComponentValueType *val_type = NULL;
val_type = wasm_runtime_malloc(sizeof(WASMComponentValueType)); val_type = wasm_runtime_malloc(sizeof(WASMComponentValueType));
if (!val_type) { if (!val_type) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for value type"); set_error_buf_ex(error_buf, error_buf_size,
"Failed to allocate memory for value type");
return false; return false;
} }
if (!parse_valtype(&p, end, val_type, error_buf, error_buf_size)) { if (!parse_valtype(&p, end, val_type, error_buf, error_buf_size)) {
@ -60,7 +72,8 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
out->val_type = val_type; out->val_type = val_type;
uint64_t core_data_len_u32_leb = 0; uint64_t core_data_len_u32_leb = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &core_data_len_u32_leb, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &core_data_len_u32_leb,
error_buf, error_buf_size)) {
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
@ -70,7 +83,10 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
// Now parse v:<val(t)> according to t. Advance `p` per case and ensure // Now parse v:<val(t)> according to t. Advance `p` per case and ensure
// the declared len matches the actual encoding size for handled cases. // the declared len matches the actual encoding size for handled cases.
if ((uint32_t)(end - p) < out->core_data_len) { if ((uint32_t)(end - p) < out->core_data_len) {
set_error_buf_ex(error_buf, error_buf_size, "Insufficient bytes for value payload: need %u, have %zu", out->core_data_len, (size_t)(end - p)); set_error_buf_ex(
error_buf, error_buf_size,
"Insufficient bytes for value payload: need %u, have %zu",
out->core_data_len, (size_t)(end - p));
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
@ -79,15 +95,19 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
if (val_type->type == WASM_COMP_VAL_TYPE_PRIMVAL) { if (val_type->type == WASM_COMP_VAL_TYPE_PRIMVAL) {
switch (val_type->type_specific.primval_type) { switch (val_type->type_specific.primval_type) {
case WASM_COMP_PRIMVAL_BOOL: { case WASM_COMP_PRIMVAL_BOOL:
{
if (out->core_data_len != 1) { if (out->core_data_len != 1) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid bool length: %u (expected 1)", out->core_data_len); set_error_buf_ex(error_buf, error_buf_size,
"Invalid bool length: %u (expected 1)",
out->core_data_len);
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
uint8_t b = *p; uint8_t b = *p;
if (b != 0x00 && b != 0x01) { if (b != 0x00 && b != 0x01) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid bool value byte: 0x%02x", b); set_error_buf_ex(error_buf, error_buf_size,
"Invalid bool value byte: 0x%02x", b);
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
@ -95,9 +115,12 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break; break;
} }
case WASM_COMP_PRIMVAL_U8: { case WASM_COMP_PRIMVAL_U8:
{
if (out->core_data_len != 1) { if (out->core_data_len != 1) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid u8 length: %u (expected 1)", out->core_data_len); set_error_buf_ex(error_buf, error_buf_size,
"Invalid u8 length: %u (expected 1)",
out->core_data_len);
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
@ -105,9 +128,12 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break; break;
} }
case WASM_COMP_PRIMVAL_S8: { case WASM_COMP_PRIMVAL_S8:
{
if (out->core_data_len != 1) { if (out->core_data_len != 1) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid s8 length: %u (expected 1)", out->core_data_len); set_error_buf_ex(error_buf, error_buf_size,
"Invalid s8 length: %u (expected 1)",
out->core_data_len);
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
@ -115,22 +141,30 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break; break;
} }
case WASM_COMP_PRIMVAL_S16: { case WASM_COMP_PRIMVAL_S16:
{
// signed LEB128 (1..3 bytes for 16-bit) // signed LEB128 (1..3 bytes for 16-bit)
if (out->core_data_len < 1 || out->core_data_len > 3) { if (out->core_data_len < 1 || out->core_data_len > 3) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid s16 LEB length: %u (expected 1..3)", out->core_data_len); set_error_buf_ex(
error_buf, error_buf_size,
"Invalid s16 LEB length: %u (expected 1..3)",
out->core_data_len);
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
uint64_t tmp = 0; uint64_t tmp = 0;
uint8_t *q = (uint8_t *)p; uint8_t *q = (uint8_t *)p;
const uint8_t *before = p; const uint8_t *before = p;
if (!read_leb(&q, end, 16, true, &tmp, error_buf, error_buf_size)) { if (!read_leb(&q, end, 16, true, &tmp, error_buf,
error_buf_size)) {
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
if ((uint32_t)(q - before) != out->core_data_len) { if ((uint32_t)(q - before) != out->core_data_len) {
set_error_buf_ex(error_buf, error_buf_size, "s16 len mismatch: declared %u, decoded %u", out->core_data_len, (uint32_t)(q - before)); set_error_buf_ex(
error_buf, error_buf_size,
"s16 len mismatch: declared %u, decoded %u",
out->core_data_len, (uint32_t)(q - before));
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
@ -138,22 +172,30 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break; break;
} }
case WASM_COMP_PRIMVAL_U16: { case WASM_COMP_PRIMVAL_U16:
{
// unsigned LEB128 (1..3 bytes for 16-bit) // unsigned LEB128 (1..3 bytes for 16-bit)
if (out->core_data_len < 1 || out->core_data_len > 3) { if (out->core_data_len < 1 || out->core_data_len > 3) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid u16 LEB length: %u (expected 1..3)", out->core_data_len); set_error_buf_ex(
error_buf, error_buf_size,
"Invalid u16 LEB length: %u (expected 1..3)",
out->core_data_len);
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
uint64_t tmp = 0; uint64_t tmp = 0;
uint8_t *q = (uint8_t *)p; uint8_t *q = (uint8_t *)p;
const uint8_t *before = p; const uint8_t *before = p;
if (!read_leb(&q, end, 16, false, &tmp, error_buf, error_buf_size)) { if (!read_leb(&q, end, 16, false, &tmp, error_buf,
error_buf_size)) {
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
if ((uint32_t)(q - before) != out->core_data_len) { if ((uint32_t)(q - before) != out->core_data_len) {
set_error_buf_ex(error_buf, error_buf_size, "u16 len mismatch: declared %u, decoded %u", out->core_data_len, (uint32_t)(q - before)); set_error_buf_ex(
error_buf, error_buf_size,
"u16 len mismatch: declared %u, decoded %u",
out->core_data_len, (uint32_t)(q - before));
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
@ -161,22 +203,30 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break; break;
} }
case WASM_COMP_PRIMVAL_S32: { case WASM_COMP_PRIMVAL_S32:
{
// signed LEB128 (1..5 bytes) // signed LEB128 (1..5 bytes)
if (out->core_data_len < 1 || out->core_data_len > 5) { if (out->core_data_len < 1 || out->core_data_len > 5) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid s32 LEB length: %u (expected 1..5)", out->core_data_len); set_error_buf_ex(
error_buf, error_buf_size,
"Invalid s32 LEB length: %u (expected 1..5)",
out->core_data_len);
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
uint64_t tmp = 0; uint64_t tmp = 0;
uint8_t *q = (uint8_t *)p; uint8_t *q = (uint8_t *)p;
const uint8_t *before = p; const uint8_t *before = p;
if (!read_leb(&q, end, 32, true, &tmp, error_buf, error_buf_size)) { if (!read_leb(&q, end, 32, true, &tmp, error_buf,
error_buf_size)) {
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
if ((uint32_t)(q - before) != out->core_data_len) { if ((uint32_t)(q - before) != out->core_data_len) {
set_error_buf_ex(error_buf, error_buf_size, "s32 len mismatch: declared %u, decoded %u", out->core_data_len, (uint32_t)(q - before)); set_error_buf_ex(
error_buf, error_buf_size,
"s32 len mismatch: declared %u, decoded %u",
out->core_data_len, (uint32_t)(q - before));
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
@ -184,22 +234,30 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break; break;
} }
case WASM_COMP_PRIMVAL_U32: { case WASM_COMP_PRIMVAL_U32:
{
// unsigned LEB128 (1..5 bytes) // unsigned LEB128 (1..5 bytes)
if (out->core_data_len < 1 || out->core_data_len > 5) { if (out->core_data_len < 1 || out->core_data_len > 5) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid u32 LEB length: %u (expected 1..5)", out->core_data_len); set_error_buf_ex(
error_buf, error_buf_size,
"Invalid u32 LEB length: %u (expected 1..5)",
out->core_data_len);
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
uint64_t tmp = 0; uint64_t tmp = 0;
uint8_t *q = (uint8_t *)p; uint8_t *q = (uint8_t *)p;
const uint8_t *before = p; const uint8_t *before = p;
if (!read_leb(&q, end, 32, false, &tmp, error_buf, error_buf_size)) { if (!read_leb(&q, end, 32, false, &tmp, error_buf,
error_buf_size)) {
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
if ((uint32_t)(q - before) != out->core_data_len) { if ((uint32_t)(q - before) != out->core_data_len) {
set_error_buf_ex(error_buf, error_buf_size, "u32 len mismatch: declared %u, decoded %u", out->core_data_len, (uint32_t)(q - before)); set_error_buf_ex(
error_buf, error_buf_size,
"u32 len mismatch: declared %u, decoded %u",
out->core_data_len, (uint32_t)(q - before));
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
@ -207,22 +265,30 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break; break;
} }
case WASM_COMP_PRIMVAL_S64: { case WASM_COMP_PRIMVAL_S64:
{
// signed LEB128 (1..10 bytes) // signed LEB128 (1..10 bytes)
if (out->core_data_len < 1 || out->core_data_len > 10) { if (out->core_data_len < 1 || out->core_data_len > 10) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid s64 LEB length: %u (expected 1..10)", out->core_data_len); set_error_buf_ex(
error_buf, error_buf_size,
"Invalid s64 LEB length: %u (expected 1..10)",
out->core_data_len);
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
uint64_t tmp = 0; uint64_t tmp = 0;
uint8_t *q = (uint8_t *)p; uint8_t *q = (uint8_t *)p;
const uint8_t *before = p; const uint8_t *before = p;
if (!read_leb(&q, end, 64, true, &tmp, error_buf, error_buf_size)) { if (!read_leb(&q, end, 64, true, &tmp, error_buf,
error_buf_size)) {
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
if ((uint32_t)(q - before) != out->core_data_len) { if ((uint32_t)(q - before) != out->core_data_len) {
set_error_buf_ex(error_buf, error_buf_size, "s64 len mismatch: declared %u, decoded %u", out->core_data_len, (uint32_t)(q - before)); set_error_buf_ex(
error_buf, error_buf_size,
"s64 len mismatch: declared %u, decoded %u",
out->core_data_len, (uint32_t)(q - before));
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
@ -230,22 +296,30 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break; break;
} }
case WASM_COMP_PRIMVAL_U64: { case WASM_COMP_PRIMVAL_U64:
{
// unsigned LEB128 (1..10 bytes) // unsigned LEB128 (1..10 bytes)
if (out->core_data_len < 1 || out->core_data_len > 10) { if (out->core_data_len < 1 || out->core_data_len > 10) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid u64 LEB length: %u (expected 1..10)", out->core_data_len); set_error_buf_ex(
error_buf, error_buf_size,
"Invalid u64 LEB length: %u (expected 1..10)",
out->core_data_len);
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
uint64_t tmp = 0; uint64_t tmp = 0;
uint8_t *q = (uint8_t *)p; uint8_t *q = (uint8_t *)p;
const uint8_t *before = p; const uint8_t *before = p;
if (!read_leb(&q, end, 64, false, &tmp, error_buf, error_buf_size)) { if (!read_leb(&q, end, 64, false, &tmp, error_buf,
error_buf_size)) {
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
if ((uint32_t)(q - before) != out->core_data_len) { if ((uint32_t)(q - before) != out->core_data_len) {
set_error_buf_ex(error_buf, error_buf_size, "u64 len mismatch: declared %u, decoded %u", out->core_data_len, (uint32_t)(q - before)); set_error_buf_ex(
error_buf, error_buf_size,
"u64 len mismatch: declared %u, decoded %u",
out->core_data_len, (uint32_t)(q - before));
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
@ -253,18 +327,23 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break; break;
} }
case WASM_COMP_PRIMVAL_F32: { case WASM_COMP_PRIMVAL_F32:
{
if (out->core_data_len != 4) { if (out->core_data_len != 4) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid f32 length: %u (expected 4)", out->core_data_len); set_error_buf_ex(error_buf, error_buf_size,
"Invalid f32 length: %u (expected 4)",
out->core_data_len);
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
if (is_canonical_f32_nan(p)) { if (is_canonical_f32_nan(p)) {
p += 4; p += 4;
break; break;
} else if (is_any_nan(p, false)) { }
else if (is_any_nan(p, false)) {
// Reject non-canonical NaN // Reject non-canonical NaN
set_error_buf_ex(error_buf, error_buf_size, "Non-canonical NaN not allowed"); set_error_buf_ex(error_buf, error_buf_size,
"Non-canonical NaN not allowed");
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
@ -272,18 +351,23 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break; break;
} }
case WASM_COMP_PRIMVAL_F64: { case WASM_COMP_PRIMVAL_F64:
{
if (out->core_data_len != 8) { if (out->core_data_len != 8) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid f64 length: %u (expected 8)", out->core_data_len); set_error_buf_ex(error_buf, error_buf_size,
"Invalid f64 length: %u (expected 8)",
out->core_data_len);
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
if (is_canonical_f64_nan(p)) { if (is_canonical_f64_nan(p)) {
p += 8; p += 8;
break; break;
} else if (is_any_nan(p, true)) { }
else if (is_any_nan(p, true)) {
// Reject non-canonical NaN // Reject non-canonical NaN
set_error_buf_ex(error_buf, error_buf_size, "Non-canonical NaN not allowed"); set_error_buf_ex(error_buf, error_buf_size,
"Non-canonical NaN not allowed");
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
@ -292,16 +376,21 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break; break;
} }
case WASM_COMP_PRIMVAL_CHAR: { case WASM_COMP_PRIMVAL_CHAR:
{
// val(char) ::= b*:<core:byte>* => c (where b* = core:utf8(c)) // val(char) ::= b*:<core:byte>* => c (where b* = core:utf8(c))
// Expect 1..4 bytes and ensure exactly one UTF-8 scalar // Expect 1..4 bytes and ensure exactly one UTF-8 scalar
if (out->core_data_len < 1 || out->core_data_len > 4) { if (out->core_data_len < 1 || out->core_data_len > 4) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid char length: %u (expected 1..4)", out->core_data_len); set_error_buf_ex(error_buf, error_buf_size,
"Invalid char length: %u (expected 1..4)",
out->core_data_len);
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
if (!wasm_component_validate_single_utf8_scalar(p, out->core_data_len)) { if (!wasm_component_validate_single_utf8_scalar(
set_error_buf_ex(error_buf, error_buf_size, "Invalid UTF-8 scalar for char"); p, out->core_data_len)) {
set_error_buf_ex(error_buf, error_buf_size,
"Invalid UTF-8 scalar for char");
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
@ -309,49 +398,63 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break; break;
} }
case WASM_COMP_PRIMVAL_STRING: { case WASM_COMP_PRIMVAL_STRING:
{
// val(string) ::= v:<core:name> => v // val(string) ::= v:<core:name> => v
// core:name = name_len_leb + name_bytes; require outer len == leb_len + name_len // core:name = name_len_leb + name_bytes; require outer len ==
// leb_len + name_len
const uint8_t *before = p; const uint8_t *before = p;
uint8_t *q = (uint8_t *)p; uint8_t *q = (uint8_t *)p;
uint64_t name_len = 0; uint64_t name_len = 0;
if (!read_leb(&q, end, 32, false, &name_len, error_buf, error_buf_size)) { if (!read_leb(&q, end, 32, false, &name_len, error_buf,
error_buf_size)) {
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
uint32_t leb_len = (uint32_t)(q - before); uint32_t leb_len = (uint32_t)(q - before);
if ((uint32_t)(end - q) < (uint32_t)name_len) { if ((uint32_t)(end - q) < (uint32_t)name_len) {
set_error_buf_ex(error_buf, error_buf_size, "Insufficient bytes for string payload: need %llu, have %zu", (unsigned long long)name_len, (size_t)(end - q)); set_error_buf_ex(error_buf, error_buf_size,
"Insufficient bytes for string payload: "
"need %llu, have %zu",
(unsigned long long)name_len,
(size_t)(end - q));
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
if ((uint32_t)name_len + leb_len != out->core_data_len) { if ((uint32_t)name_len + leb_len != out->core_data_len) {
set_error_buf_ex(error_buf, error_buf_size, "string len mismatch: declared %u, decoded %u", out->core_data_len, (uint32_t)name_len + leb_len); set_error_buf_ex(
error_buf, error_buf_size,
"string len mismatch: declared %u, decoded %u",
out->core_data_len, (uint32_t)name_len + leb_len);
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
if (!wasm_component_validate_utf8(q, (uint32_t)name_len)) { if (!wasm_component_validate_utf8(q, (uint32_t)name_len)) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid UTF-8 in string"); set_error_buf_ex(error_buf, error_buf_size,
"Invalid UTF-8 in string");
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
p = q + name_len; p = q + name_len;
break; break;
} }
default: { default:
{
set_error_buf_ex(error_buf, error_buf_size, set_error_buf_ex(error_buf, error_buf_size,
"Unknown primitive value type 0x%02x", "Unknown primitive value type 0x%02x",
val_type->type_specific.primval_type); val_type->type_specific.primval_type);
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
} }
} else { }
else {
// valtype in the values section must be either primval or typeidx // valtype in the values section must be either primval or typeidx
if (val_type->type != WASM_COMP_VAL_TYPE_IDX) { if (val_type->type != WASM_COMP_VAL_TYPE_IDX) {
set_error_buf_ex(error_buf, error_buf_size, set_error_buf_ex(error_buf, error_buf_size,
"Unsupported valtype tag %u in values section (expected typeidx)", "Unsupported valtype tag %u in values section "
(unsigned)val_type->type); "(expected typeidx)",
(unsigned)val_type->type);
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
@ -361,8 +464,9 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
// - just advance by the declared len and validate bounds // - just advance by the declared len and validate bounds
if ((uint32_t)(end - p) < out->core_data_len) { if ((uint32_t)(end - p) < out->core_data_len) {
set_error_buf_ex(error_buf, error_buf_size, set_error_buf_ex(error_buf, error_buf_size,
"Insufficient bytes for type-indexed value payload: need %u, have %zu", "Insufficient bytes for type-indexed value "
out->core_data_len, (size_t)(end - p)); "payload: need %u, have %zu",
out->core_data_len, (size_t)(end - p));
wasm_runtime_free(val_type); wasm_runtime_free(val_type);
return false; return false;
} }
@ -377,10 +481,18 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
} }
// Section 12: values section // Section 12: values section
bool wasm_component_parse_values_section(const uint8_t **payload, uint32_t payload_len, WASMComponentValueSection *out, char *error_buf, uint32_t error_buf_size, uint32_t *consumed_len) { bool
wasm_component_parse_values_section(const uint8_t **payload,
uint32_t payload_len,
WASMComponentValueSection *out,
char *error_buf, uint32_t error_buf_size,
uint32_t *consumed_len)
{
if (!payload || !*payload || payload_len == 0 || !out) { if (!payload || !*payload || payload_len == 0 || !out) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid payload or output pointer"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = 0; "Invalid payload or output pointer");
if (consumed_len)
*consumed_len = 0;
return false; return false;
} }
@ -390,8 +502,10 @@ bool wasm_component_parse_values_section(const uint8_t **payload, uint32_t paylo
// values ::= count:<count> value:<value> => (values count value) // values ::= count:<count> value:<value> => (values count value)
// Read the count of values (LEB128-encoded) // Read the count of values (LEB128-encoded)
uint64_t value_count_leb = 0; uint64_t value_count_leb = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &value_count_leb, error_buf, error_buf_size)) { if (!read_leb((uint8_t **)&p, end, 32, false, &value_count_leb, error_buf,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); error_buf_size)) {
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
@ -399,10 +513,13 @@ bool wasm_component_parse_values_section(const uint8_t **payload, uint32_t paylo
out->count = value_count; out->count = value_count;
if (value_count > 0) { if (value_count > 0) {
out->values = wasm_runtime_malloc(sizeof(WASMComponentValue) * value_count); out->values =
wasm_runtime_malloc(sizeof(WASMComponentValue) * value_count);
if (!out->values) { if (!out->values) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for values"); set_error_buf_ex(error_buf, error_buf_size,
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); "Failed to allocate memory for values");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
@ -410,20 +527,26 @@ bool wasm_component_parse_values_section(const uint8_t **payload, uint32_t paylo
memset(out->values, 0, sizeof(WASMComponentValue) * value_count); memset(out->values, 0, sizeof(WASMComponentValue) * value_count);
for (uint32_t i = 0; i < value_count; ++i) { for (uint32_t i = 0; i < value_count; ++i) {
if (!parse_value(&p, end, &out->values[i], error_buf, error_buf_size)) { if (!parse_value(&p, end, &out->values[i], error_buf,
set_error_buf_ex(error_buf, error_buf_size, "Failed to parse value %u", i); error_buf_size)) {
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); set_error_buf_ex(error_buf, error_buf_size,
"Failed to parse value %u", i);
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false; return false;
} }
} }
} }
if (consumed_len) *consumed_len = (uint32_t)(p - *payload); if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return true; return true;
} }
// Individual section free functions // Individual section free functions
void wasm_component_free_values_section(WASMComponentSection *section) { void
wasm_component_free_values_section(WASMComponentSection *section)
{
if (!section || !section->parsed.value_section) { if (!section || !section->parsed.value_section) {
return; return;
} }

View File

@ -652,17 +652,20 @@ wasm_runtime_init_internal(void)
return true; return true;
} }
bool wasm_decode_header(const uint8_t *buf, uint32_t size, WASMHeader *out_header) { bool
wasm_decode_header(const uint8_t *buf, uint32_t size, WASMHeader *out_header)
{
if (!buf || size < 8) { if (!buf || size < 8) {
return false; return false;
} }
// WASM binary is little-endian // WASM binary is little-endian
uint32_t magic = (uint32_t)buf[0] | ((uint32_t)buf[1] << 8) | ((uint32_t)buf[2] << 16) | ((uint32_t)buf[3] << 24); uint32_t magic = (uint32_t)buf[0] | ((uint32_t)buf[1] << 8)
| ((uint32_t)buf[2] << 16) | ((uint32_t)buf[3] << 24);
// Decode version and layer fields // Decode version and layer fields
// For Preview 1 modules: version=0x0001, layer=0x0000 (combined: 0x00000001) // For Preview 1 modules: version=0x0001, layer=0x0000 (combined:
// For Preview 2 components: version=0x000d, layer=0x0001 // 0x00000001) For Preview 2 components: version=0x000d, layer=0x0001
uint16_t version = (uint16_t)buf[4] | ((uint16_t)buf[5] << 8); uint16_t version = (uint16_t)buf[4] | ((uint16_t)buf[5] << 8);
uint16_t layer = (uint16_t)buf[6] | ((uint16_t)buf[7] << 8); uint16_t layer = (uint16_t)buf[6] | ((uint16_t)buf[7] << 8);
@ -673,13 +676,16 @@ bool wasm_decode_header(const uint8_t *buf, uint32_t size, WASMHeader *out_heade
return true; return true;
} }
bool is_wasm_module(WASMHeader header) { bool
is_wasm_module(WASMHeader header)
{
if (header.magic != WASM_MAGIC_NUMBER) { if (header.magic != WASM_MAGIC_NUMBER) {
return false; return false;
} }
// For Preview 1 modules, the combined version+layer should equal 0x00000001 // For Preview 1 modules, the combined version+layer should equal 0x00000001
uint32_t combined_version = ((uint32_t)header.layer << 16) | (uint32_t)header.version; uint32_t combined_version =
((uint32_t)header.layer << 16) | (uint32_t)header.version;
if (combined_version != WASM_CURRENT_VERSION) { if (combined_version != WASM_CURRENT_VERSION) {
return false; return false;
} }
@ -4556,7 +4562,6 @@ wasm_runtime_get_function_count(WASMModuleCommon *const module)
return -1; return -1;
} }
if (module->module_type == Wasm_Module_Bytecode) { if (module->module_type == Wasm_Module_Bytecode) {
const WASMModule *wasm_module = (const WASMModule *)module; const WASMModule *wasm_module = (const WASMModule *)module;
return (int32)wasm_module->function_count; return (int32)wasm_module->function_count;
@ -4573,7 +4578,6 @@ wasm_runtime_get_table_count(WASMModuleCommon *const module)
return -1; return -1;
} }
if (module->module_type == Wasm_Module_Bytecode) { if (module->module_type == Wasm_Module_Bytecode) {
const WASMModule *wasm_module = (const WASMModule *)module; const WASMModule *wasm_module = (const WASMModule *)module;
return (int32)wasm_module->table_count; return (int32)wasm_module->table_count;
@ -4590,7 +4594,6 @@ wasm_runtime_get_memories_count(WASMModuleCommon *const module)
return -1; return -1;
} }
if (module->module_type == Wasm_Module_Bytecode) { if (module->module_type == Wasm_Module_Bytecode) {
const WASMModule *wasm_module = (const WASMModule *)module; const WASMModule *wasm_module = (const WASMModule *)module;
return (int32)wasm_module->memory_count; return (int32)wasm_module->memory_count;
@ -4607,7 +4610,6 @@ wasm_runtime_get_globals_count(WASMModuleCommon *const module)
return -1; return -1;
} }
if (module->module_type == Wasm_Module_Bytecode) { if (module->module_type == Wasm_Module_Bytecode) {
const WASMModule *wasm_module = (const WASMModule *)module; const WASMModule *wasm_module = (const WASMModule *)module;
return (int32)wasm_module->global_count; return (int32)wasm_module->global_count;

View File

@ -92,9 +92,9 @@ typedef WASMMemoryType *wasm_memory_type_t;
// WASM Header Structure // WASM Header Structure
typedef struct WASMHeader { typedef struct WASMHeader {
uint32_t magic; // Magic number (0x6d736100 for both) uint32_t magic; // Magic number (0x6d736100 for both)
uint16_t version; // Version field uint16_t version; // Version field
uint16_t layer; // Layer field uint16_t layer; // Layer field
} WASMHeader; } WASMHeader;
typedef struct wasm_import_t { typedef struct wasm_import_t {
@ -374,14 +374,16 @@ typedef struct SharedHeapInitArgs {
* *
* @return true if success, false otherwise * @return true if success, false otherwise
*/ */
bool wasm_decode_header(const uint8_t *buf, uint32_t size, WASMHeader *out_header); bool
wasm_decode_header(const uint8_t *buf, uint32_t size, WASMHeader *out_header);
/** /**
* Check if header is a WASM Preview 1 * Check if header is a WASM Preview 1
* *
* @return true if success, false otherwise * @return true if success, false otherwise
*/ */
bool is_wasm_module(WASMHeader header); bool
is_wasm_module(WASMHeader header);
/** /**
* Initialize the WASM runtime environment, and also initialize * Initialize the WASM runtime environment, and also initialize

View File

@ -154,8 +154,8 @@ typedef void *table_elem_type_t;
#define WASM_MAGIC_NUMBER 0x6d736100 #define WASM_MAGIC_NUMBER 0x6d736100
#define WASM_CURRENT_VERSION 1 #define WASM_CURRENT_VERSION 1
#define WASM_COMPONENT_VERSION 0x000d // 0x0d 0x00 #define WASM_COMPONENT_VERSION 0x000d // 0x0d 0x00
#define WASM_COMPONENT_LAYER 0x0001 // 0x01 0x00 #define WASM_COMPONENT_LAYER 0x0001 // 0x01 0x00
#define SECTION_TYPE_USER 0 #define SECTION_TYPE_USER 0
#define SECTION_TYPE_TYPE 1 #define SECTION_TYPE_TYPE 1

View File

@ -7108,8 +7108,9 @@ load(const uint8 *buf, uint32 size, WASMModule *module,
module->package_version = version; module->package_version = version;
if (!create_sections(buf, size, &section_list, error_buf, error_buf_size) if (!create_sections(buf, size, &section_list, error_buf, error_buf_size)
|| !load_from_sections(module, section_list, false, wasm_binary_freeable, || !load_from_sections(module, section_list, false,
no_resolve, error_buf, error_buf_size)) { wasm_binary_freeable, no_resolve, error_buf,
error_buf_size)) {
destroy_sections(section_list); destroy_sections(section_list);
return false; return false;
} }
@ -7131,9 +7132,9 @@ check_wasi_abi_compatibility(const WASMModule *module,
bool main_module, bool main_module,
#endif #endif
#if WASM_ENABLE_COMPONENT_MODEL != 0 #if WASM_ENABLE_COMPONENT_MODEL != 0
bool is_component, bool is_component,
#endif #endif
char *error_buf, uint32 error_buf_size) char *error_buf, uint32 error_buf_size)
{ {
/** /**
* be careful with: * be careful with:
@ -7222,8 +7223,8 @@ check_wasi_abi_compatibility(const WASMModule *module,
/* should have one at least */ /* should have one at least */
if (module->import_wasi_api && !start && !initialize) { if (module->import_wasi_api && !start && !initialize) {
if (!is_component) if (!is_component)
LOG_WARNING("warning: a module with WASI apis should be either " LOG_WARNING("warning: a module with WASI apis should be either "
"a command or a reactor"); "a command or a reactor");
} }
#endif #endif
/* /*
@ -7301,9 +7302,9 @@ wasm_loader_load(uint8 *buf, uint32 size,
main_module, main_module,
#endif #endif
#if WASM_ENABLE_COMPONENT_MODEL != 0 #if WASM_ENABLE_COMPONENT_MODEL != 0
args->is_component, args->is_component,
#endif #endif
error_buf, error_buf_size)) { error_buf, error_buf_size)) {
goto fail; goto fail;
} }
#endif #endif

View File

@ -1507,9 +1507,9 @@ export_functions_instantiate(const WASMModule *module,
*/ */
static WASMExportTabInstance * static WASMExportTabInstance *
export_tables_instantiate(const WASMModule *module, export_tables_instantiate(const WASMModule *module,
WASMModuleInstance *module_inst, WASMModuleInstance *module_inst,
uint32 export_table_count, char *error_buf, uint32 export_table_count, char *error_buf,
uint32 error_buf_size) uint32 error_buf_size)
{ {
WASMExportTabInstance *export_tables, *export_table; WASMExportTabInstance *export_tables, *export_table;
WASMExport *export = module->exports; WASMExport *export = module->exports;
@ -1533,7 +1533,6 @@ export_tables_instantiate(const WASMModule *module,
return export_tables; return export_tables;
} }
#if WASM_ENABLE_TAGS != 0 #if WASM_ENABLE_TAGS != 0
/** /**
* Destroy export function instances. * Destroy export function instances.

View File

@ -17,15 +17,16 @@
#define HEAP_SIZE (100 * 1024 * 1024) // 100 MB #define HEAP_SIZE (100 * 1024 * 1024) // 100 MB
class ComponentHelper { class ComponentHelper
public: {
public:
RuntimeInitArgs init_args; RuntimeInitArgs init_args;
unsigned char *component_raw = NULL; unsigned char *component_raw = NULL;
WASMComponent *component = NULL; WASMComponent *component = NULL;
uint32_t wasm_file_size = 0; uint32_t wasm_file_size = 0;
uint32_t stack_size = 16 * 1024; // 16 KB uint32_t stack_size = 16 * 1024; // 16 KB
uint32_t heap_size = HEAP_SIZE; // 100 MB uint32_t heap_size = HEAP_SIZE; // 100 MB
char error_buf[128]; char error_buf[128];
char global_heap_buf[HEAP_SIZE]; // 100 MB char global_heap_buf[HEAP_SIZE]; // 100 MB
@ -49,9 +50,13 @@ public:
void do_setup(); void do_setup();
void do_teardown(); void do_teardown();
std::vector<WASMComponentSection*> get_section(WASMComponentSectionType section_id) const; std::vector<WASMComponentSection *> get_section(
WASMComponentSectionType section_id) const;
void load_memory_offsets(const std::string& filename); // Loading the memory offsets from text file void load_memory_offsets(
uint32_t get_memory_offsets(const std::string& key); // Get memory offsets from map const std::string
&filename); // Loading the memory offsets from text file
uint32_t get_memory_offsets(
const std::string &key); // Get memory offsets from map
}; };
#endif #endif

View File

@ -15,9 +15,9 @@ static std::vector<std::string> component_files = {
"add.wasm", "add.wasm",
"complex_with_host.wasm", "complex_with_host.wasm",
"complex.wasm", "complex.wasm",
"logging-service.component.wasm", "logging_service.component.wasm",
"processor_and_logging_merged_wac_plug.wasm", "processor_and_logging_merged_wac_plug.wasm",
"processor-service.component.wasm", "processor_service.component.wasm",
"sampletypes.wasm" "sampletypes.wasm"
}; };
@ -78,7 +78,7 @@ TEST_F(BinaryParserTest, TestLoadCorruptComponent)
TEST_F(BinaryParserTest, TestDecodeHeaderValid) TEST_F(BinaryParserTest, TestDecodeHeaderValid)
{ {
helper->reset_component(); helper->reset_component();
bool ret = helper->read_wasm_file("logging-service.component.wasm"); bool ret = helper->read_wasm_file("logging_service.component.wasm");
ASSERT_TRUE(ret); ASSERT_TRUE(ret);
ASSERT_TRUE(helper->component_raw != NULL); ASSERT_TRUE(helper->component_raw != NULL);
@ -95,7 +95,7 @@ TEST_F(BinaryParserTest, TestDecodeHeaderValid)
TEST_F(BinaryParserTest, TestDecodeHeaderInvalid) TEST_F(BinaryParserTest, TestDecodeHeaderInvalid)
{ {
helper->reset_component(); helper->reset_component();
bool ret = helper->read_wasm_file("logging-service.component.wasm"); bool ret = helper->read_wasm_file("logging_service.component.wasm");
ASSERT_TRUE(ret); ASSERT_TRUE(ret);
ASSERT_TRUE(helper->component_raw != NULL); ASSERT_TRUE(helper->component_raw != NULL);