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

@ -14,8 +14,13 @@
#include <stdio.h>
// Parse all sections in a WASM component binary
// Each section is dispatched to its own parser and stored in the output structure
bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMComponent *out_component, LoadArgs *args, unsigned int depth) {
// Each section is dispatched to its own parser and stored in the output
// 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) {
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;
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) {
return false;
}
@ -43,8 +49,8 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
// Read payload length
uint64 payload_len = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &payload_len,
error_buf, sizeof(error_buf))) {
if (!read_leb((uint8_t **)&p, end, 32, false, &payload_len, error_buf,
sizeof(error_buf))) {
wasm_runtime_free(sections);
return false; // Error handling
}
@ -57,7 +63,8 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
// Store section info
if (section_count == section_capacity) {
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) {
wasm_runtime_free(sections);
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_len = (uint32_t)payload_len;
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++;
uint32_t consumed_len = 0;
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) {
// Section 0: custom section
case WASM_COMP_SECTION_CORE_CUSTOM: {
case WASM_COMP_SECTION_CORE_CUSTOM:
{
// Parse custom section (name + data)
WASMComponentCoreCustomSection *custom = wasm_runtime_malloc(sizeof(WASMComponentCoreCustomSection));
if (custom) memset(custom, 0, sizeof(WASMComponentCoreCustomSection));
WASMComponentCoreCustomSection *custom =
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 (custom) {
wasm_runtime_free(custom);
}
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) {
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);
return false;
}
} else {
}
else {
sections[current_section_index].parsed.core_custom = custom;
}
break;
}
// Section 1: module section
case WASM_COMP_SECTION_CORE_MODULE: {
case WASM_COMP_SECTION_CORE_MODULE:
{
// Parse and load the embedded core wasm module
WASMComponentCoreModuleWrapper *module = wasm_runtime_malloc(sizeof(WASMComponentCoreModuleWrapper));
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);
WASMComponentCoreModuleWrapper *module =
wasm_runtime_malloc(sizeof(WASMComponentCoreModuleWrapper));
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 (module) {
wasm_runtime_free(module);
}
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) {
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);
return false;
}
} else {
}
else {
sections[current_section_index].parsed.core_module = module;
}
break;
}
// Section 2: instance section
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));
parse_success = wasm_component_parse_core_instance_section(&payload_start, (uint32_t)payload_len, core_instance_section, error_buf, sizeof(error_buf), &consumed_len);
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));
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) {
sections[current_section_index].parsed.core_instance_section = core_instance_section;
} else {
sections[current_section_index]
.parsed.core_instance_section = core_instance_section;
}
else {
if (core_instance_section) {
wasm_runtime_free(core_instance_section);
}
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) {
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);
return false;
}
@ -148,21 +187,32 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
break;
}
// Section 3: core types section
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));
parse_success = wasm_component_parse_core_type_section(&payload_start, (uint32_t)payload_len, core_type_section, error_buf, sizeof(error_buf), &consumed_len);
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));
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) {
sections[current_section_index].parsed.core_type_section = core_type_section;
} else {
sections[current_section_index].parsed.core_type_section =
core_type_section;
}
else {
if (core_type_section) {
wasm_runtime_free(core_type_section);
}
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) {
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);
return false;
}
@ -170,11 +220,14 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
break;
}
// Section 4: component section
case WASM_COMP_SECTION_COMPONENT: {
case WASM_COMP_SECTION_COMPONENT:
{
// Parse and load the embedded component
WASMComponent *component = wasm_runtime_malloc(sizeof(WASMComponent));
WASMComponent *component =
wasm_runtime_malloc(sizeof(WASMComponent));
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);
return false;
}
@ -182,37 +235,56 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
memset(component, 0, sizeof(WASMComponent));
// 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
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);
LOG_DEBUG("Error parsing sub component section\n");
wasm_runtime_free(sections);
return false;
} else {
LOG_DEBUG(" Successfully parsed nested component at %p\n", component);
sections[current_section_index].parsed.component = component;
}
else {
LOG_DEBUG(
" Successfully parsed nested component at %p\n",
component);
sections[current_section_index].parsed.component =
component;
}
break;
}
// Section 5: instances section
case WASM_COMP_SECTION_INSTANCES: {
WASMComponentInstSection *instance_section = 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);
case WASM_COMP_SECTION_INSTANCES:
{
WASMComponentInstSection *instance_section =
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) {
sections[current_section_index].parsed.instance_section = instance_section;
} else {
sections[current_section_index].parsed.instance_section =
instance_section;
}
else {
if (instance_section) {
wasm_runtime_free(instance_section);
}
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) {
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);
return false;
}
@ -220,22 +292,32 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
break;
}
// Section 6: aliases section for imports/exports
case WASM_COMP_SECTION_ALIASES: {
case WASM_COMP_SECTION_ALIASES:
{
// Parse alias definitions for imports/exports
WASMComponentAliasSection *alias_section = wasm_runtime_malloc(sizeof(WASMComponentAliasSection));
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);
WASMComponentAliasSection *alias_section =
wasm_runtime_malloc(sizeof(WASMComponentAliasSection));
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) {
sections[current_section_index].parsed.alias_section = alias_section;
} else {
sections[current_section_index].parsed.alias_section =
alias_section;
}
else {
if (alias_section) {
wasm_runtime_free(alias_section);
}
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) {
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);
return false;
}
@ -243,21 +325,31 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
break;
}
// Section 7: types section
case WASM_COMP_SECTION_TYPE: {
WASMComponentTypeSection *type_section = 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);
case WASM_COMP_SECTION_TYPE:
{
WASMComponentTypeSection *type_section =
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) {
sections[current_section_index].parsed.type_section = type_section;
} else {
sections[current_section_index].parsed.type_section =
type_section;
}
else {
if (type_section) {
wasm_runtime_free(type_section);
}
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) {
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);
return false;
}
@ -265,21 +357,31 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
break;
}
// Section 8: canons section
case WASM_COMP_SECTION_CANONS: {
WASMComponentCanonSection *canon_section = 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);
case WASM_COMP_SECTION_CANONS:
{
WASMComponentCanonSection *canon_section =
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) {
sections[current_section_index].parsed.canon_section = canon_section;
} else {
sections[current_section_index].parsed.canon_section =
canon_section;
}
else {
if (canon_section) {
wasm_runtime_free(canon_section);
}
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) {
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);
return false;
}
@ -287,21 +389,31 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
break;
}
// Section 9: start section
case WASM_COMP_SECTION_START: {
WASMComponentStartSection *start_section = 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);
case WASM_COMP_SECTION_START:
{
WASMComponentStartSection *start_section =
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) {
sections[current_section_index].parsed.start_section = start_section;
} else {
sections[current_section_index].parsed.start_section =
start_section;
}
else {
if (start_section) {
wasm_runtime_free(start_section);
}
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) {
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);
return false;
}
@ -309,22 +421,34 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
break;
}
// Section 10: imports section (component model 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));
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);
case WASM_COMP_SECTION_IMPORTS:
{
// Parse all imports: name (simple/versioned) and externdesc
// (all 6 types)
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) {
sections[current_section_index].parsed.import_section = import_section;
} else {
sections[current_section_index].parsed.import_section =
import_section;
}
else {
if (import_section) {
wasm_runtime_free(import_section);
}
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) {
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);
return false;
}
@ -332,21 +456,32 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
break;
}
// Section 11: exports section
case WASM_COMP_SECTION_EXPORTS: {
WASMComponentExportSection *export_section = 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);
case WASM_COMP_SECTION_EXPORTS:
{
WASMComponentExportSection *export_section =
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) {
sections[current_section_index].parsed.export_section = export_section;
} else {
sections[current_section_index].parsed.export_section =
export_section;
}
else {
if (export_section) {
wasm_runtime_free(export_section);
}
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) {
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);
return false;
}
@ -354,21 +489,31 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
break;
}
// Section 12: values section
case WASM_COMP_SECTION_VALUES: {
WASMComponentValueSection *value_section = 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);
case WASM_COMP_SECTION_VALUES:
{
WASMComponentValueSection *value_section =
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) {
sections[current_section_index].parsed.value_section = value_section;
} else {
sections[current_section_index].parsed.value_section =
value_section;
}
else {
if (value_section) {
wasm_runtime_free(value_section);
}
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) {
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);
return false;
}
@ -377,12 +522,13 @@ bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMCompon
}
default:
// 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);
return false;
}
// Advance the main parser by the consumed amount
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
bool is_wasm_component(WASMHeader header) {
if (header.magic != WASM_MAGIC_NUMBER ||
header.version != WASM_COMPONENT_VERSION ||
header.layer != WASM_COMPONENT_LAYER) {
bool
is_wasm_component(WASMHeader header)
{
if (header.magic != WASM_MAGIC_NUMBER
|| header.version != WASM_COMPONENT_VERSION
|| header.layer != WASM_COMPONENT_LAYER) {
return false;
}
@ -410,8 +558,11 @@ bool is_wasm_component(WASMHeader header) {
}
// Main component free function
void wasm_component_free(WASMComponent *component) {
if (!component || !component->sections) return;
void
wasm_component_free(WASMComponent *component)
{
if (!component || !component->sections)
return;
for (uint32_t i = 0; i < component->section_count; ++i) {
WASMComponentSection *sec = &component->sections[i];

View File

@ -82,7 +82,8 @@ typedef enum WASMComponentSortValues {
WASM_COMP_SORT_INSTANCE = 0x05 // instance
} WASMComponentSortValues;
// Component Model Primitive Value Types - Those are different from Core WebAssembly
// Component Model Primitive Value Types - Those are different from Core
// WebAssembly
// -----------------------------------------------------------------------------
typedef enum WASMComponentPrimValType {
WASM_COMP_PRIMVAL_BOOL = 0x7f, // 0x7f => bool
@ -234,7 +235,8 @@ typedef enum WASMComponentTypesTag {
// -----------------------------------------------------------------------------
// Instance Expression Tag - Distinguishes with/without args
// instanceexpr ::= 0x00 c:<componentidx> arg*:vec(<instantiatearg>) => (instantiate c arg*)
// instanceexpr ::= 0x00 c:<componentidx> arg*:vec(<instantiatearg>) =>
// (instantiate c arg*)
// | 0x01 e*:vec(<inlineexport>) => e*
// -----------------------------------------------------------------------------
typedef enum WASMComponentInstExpressionTag {
@ -244,7 +246,8 @@ typedef enum WASMComponentInstExpressionTag {
// -----------------------------------------------------------------------------
// Result List Tag - Distinguishes with/without type
// instanceexpr ::= 0x00 c:<componentidx> arg*:vec(<instantiatearg>) => (instantiate c arg*)
// instanceexpr ::= 0x00 c:<componentidx> arg*:vec(<instantiatearg>) =>
// (instantiate c arg*)
// | 0x01 e*:vec(<inlineexport>) => e*
// -----------------------------------------------------------------------------
typedef enum WASMComponentResultListTag {
@ -361,7 +364,8 @@ typedef struct WASMComponentCoreName {
// -----------------------------------------------------------------------------
typedef struct WASMComponentSort {
uint8_t sort; // Main sort byte (0x00 for core sorts, 0x01..0x05 for others)
uint8_t core_sort; // If sort==0x00, this is the core sort; otherwise is ignored
uint8_t
core_sort; // If sort==0x00, this is the core sort; otherwise is ignored
} WASMComponentSort;
// -----------------------------------------------------------------------------
@ -421,12 +425,25 @@ typedef struct WASMComponentTypeBound {
typedef struct WASMComponentExternDesc {
WASMComponentExternDescType type;
union {
struct { uint8_t type_specific; uint32_t type_idx; } core_module;
struct { uint32_t type_idx; } func;
struct { WASMComponentValueBound *value_bound; } value;
struct { WASMComponentTypeBound *type_bound; } type;
struct { uint32_t type_idx; } component;
struct { uint32_t type_idx; } instance;
struct {
uint8_t type_specific;
uint32_t type_idx;
} core_module;
struct {
uint32_t type_idx;
} func;
struct {
WASMComponentValueBound *value_bound;
} value;
struct {
WASMComponentTypeBound *type_bound;
} type;
struct {
uint32_t type_idx;
} component;
struct {
uint32_t type_idx;
} instance;
} extern_desc;
} WASMComponentExternDesc;
@ -438,8 +455,13 @@ typedef struct WASMComponentExternDesc {
typedef struct WASMComponentImportName {
WASMComponentImportExportTypeTag tag;
union {
struct { WASMComponentCoreName *name; } simple;
struct { WASMComponentCoreName *name; WASMComponentCoreName *version; } versioned;
struct {
WASMComponentCoreName *name;
} simple;
struct {
WASMComponentCoreName *name;
WASMComponentCoreName *version;
} versioned;
} imported;
} WASMComponentImportName;
@ -451,8 +473,13 @@ typedef struct WASMComponentImportName {
typedef struct WASMComponentExportName {
WASMComponentImportExportTypeTag tag;
union {
struct { WASMComponentCoreName *name; } simple;
struct { WASMComponentCoreName *name; WASMComponentCoreName *version; } versioned;
struct {
WASMComponentCoreName *name;
} simple;
struct {
WASMComponentCoreName *name;
WASMComponentCoreName *version;
} versioned;
} exported;
} WASMComponentExportName;
@ -495,8 +522,15 @@ typedef struct WASMComponentInstArg {
} WASMComponentInstArg;
typedef union WASMInstExpr {
struct { uint32_t idx; uint32_t arg_len; WASMComponentInstArg *args; } with_args;
struct { uint32_t inline_expr_len; WASMComponentInlineExport *inline_expr; } without_args;
struct {
uint32_t idx;
uint32_t arg_len;
WASMComponentInstArg *args;
} with_args;
struct {
uint32_t inline_expr_len;
WASMComponentInlineExport *inline_expr;
} without_args;
} WASMInstExpr;
typedef struct WASMComponentCoreInst {
@ -537,7 +571,8 @@ typedef enum WASMCorePackedTypeTag {
} WASMCorePackedTypeTag;
// Core Abstract Heap Types - From WebAssembly Core spec
// absheaptype ::= 0x73 => nofunc | 0x72 => noextern | 0x71 => none | 0x70 => func
// absheaptype ::= 0x73 => nofunc | 0x72 => noextern | 0x71 => none | 0x70 =>
// func
// | 0x6F => extern | 0x6E => any | 0x6D => eq | 0x6C => i31
// | 0x6B => struct | 0x6A => array
typedef enum WASMCoreAbsHeapTypeTag {
@ -665,7 +700,8 @@ typedef struct WASMComponentCoreCompType {
typedef struct WASMComponentCoreSubType {
bool is_final;
uint32_t supertype_count;
uint32_t *supertypes; // Vector of type indices (can be empty for final with no supertypes)
uint32_t *supertypes; // Vector of type indices (can be empty for final with
// no supertypes)
WASMComponentCoreCompType comptype;
} WASMComponentCoreSubType;
@ -679,20 +715,22 @@ typedef struct WASMComponentCoreRecType {
// Core Module Type Structure
// Core Import and Import Description Structures
// Based on WebAssembly specification: https://webassembly.github.io/gc/core/binary/types.html
// core:import ::= nm:<core:name> d:<core:importdesc> => (import nm d)
// core:importdesc ::= 0x00 ft:<core:functype> => (func (type ft))
// Based on WebAssembly specification:
// https://webassembly.github.io/gc/core/binary/types.html core:import ::=
// nm:<core:name> d:<core:importdesc> => (import nm d) core:importdesc ::= 0x00
// ft:<core:functype> => (func (type ft))
// | 0x01 tt:<core:tabletype> => (table tt)
// | 0x02 mt:<core:memtype> => (memory mt)
// | 0x03 gt:<core:globaltype> => (global gt)
typedef enum WASMComponentCoreImportDescType {
WASM_CORE_IMPORTDESC_FUNC = 0x00, // 0x00 ft:<core:functype> => (func (type ft))
WASM_CORE_IMPORTDESC_FUNC =
0x00, // 0x00 ft:<core:functype> => (func (type ft))
WASM_CORE_IMPORTDESC_TABLE = 0x01, // 0x01 tt:<core:tabletype> => (table tt)
WASM_CORE_IMPORTDESC_MEMORY = 0x02, // 0x02 mt:<core:memtype> => (memory mt)
WASM_CORE_IMPORTDESC_GLOBAL = 0x03 // 0x03 gt:<core:globaltype> => (global gt)
WASM_CORE_IMPORTDESC_GLOBAL =
0x03 // 0x03 gt:<core:globaltype> => (global gt)
} WASMComponentCoreImportDescType;
typedef enum WASMComponentCoreLimitsTag {
@ -703,8 +741,13 @@ typedef enum WASMComponentCoreLimitsTag {
typedef struct WASMComponentCoreLimits {
WASMComponentCoreLimitsTag tag;
union {
struct { uint32_t min; } limits;
struct { uint32_t min; uint32_t max; } limits_max;
struct {
uint32_t min;
} limits;
struct {
uint32_t min;
uint32_t max;
} limits_max;
} lim;
} WASMComponentCoreLimits;
@ -751,10 +794,14 @@ typedef struct WASMComponentCoreExportDecl {
// | 0x03 x:<core:outeridx> n:<core:name> => (alias outer x n)
typedef enum WASMComponentCoreAliasType {
WASM_CORE_ALIAS_FUNC = 0x00, // 0x00 x:<core:outeridx> n:<core:name> => (alias outer x n)
WASM_CORE_ALIAS_TABLE = 0x01, // 0x01 x:<core:outeridx> n:<core:name> => (alias outer x n)
WASM_CORE_ALIAS_MEMORY = 0x02, // 0x02 x:<core:outeridx> n:<core:name> => (alias outer x n)
WASM_CORE_ALIAS_GLOBAL = 0x03 // 0x03 x:<core:outeridx> n:<core:name> => (alias outer x n)
WASM_CORE_ALIAS_FUNC =
0x00, // 0x00 x:<core:outeridx> n:<core:name> => (alias outer x n)
WASM_CORE_ALIAS_TABLE =
0x01, // 0x01 x:<core:outeridx> n:<core:name> => (alias outer x n)
WASM_CORE_ALIAS_MEMORY =
0x02, // 0x02 x:<core:outeridx> n:<core:name> => (alias outer x n)
WASM_CORE_ALIAS_GLOBAL =
0x03 // 0x03 x:<core:outeridx> n:<core:name> => (alias outer x n)
} WASMComponentCoreAliasType;
typedef struct WASMComponentCoreAliasTarget {
@ -805,8 +852,8 @@ typedef struct WASMComponentCoreModuleType {
// Core DefType Structure
// core:deftype ::= rt:<core:rectype> => rt (WebAssembly 3.0)
// | 0x00 0x50 x*:vec(<core:typeidx>) ct:<core:comptype> => sub x* ct (WebAssembly 3.0)
// | mt:<core:moduletype> => mt
// | 0x00 0x50 x*:vec(<core:typeidx>) ct:<core:comptype> => sub x*
// ct (WebAssembly 3.0) | mt:<core:moduletype> => mt
typedef enum WASMComponentCoreDefTypeTag {
WASM_CORE_DEFTYPE_RECTYPE,
WASM_CORE_DEFTYPE_SUBTYPE,
@ -1216,7 +1263,8 @@ typedef enum WASMComponentCanonType {
WASM_COMP_CANON_FUTURE_DROP_READABLE = 0x1a, // canon future.drop-readable
WASM_COMP_CANON_FUTURE_DROP_WRITABLE = 0x1b, // canon future.drop-writable
WASM_COMP_CANON_ERROR_CONTEXT_NEW = 0x1c, // canon error-context.new
WASM_COMP_CANON_ERROR_CONTEXT_DEBUG = 0x1d, // canon error-context.debug-message
WASM_COMP_CANON_ERROR_CONTEXT_DEBUG =
0x1d, // canon error-context.debug-message
WASM_COMP_CANON_ERROR_CONTEXT_DROP = 0x1e, // canon error-context.drop
WASM_COMP_CANON_WAITABLE_SET_NEW = 0x1f, // canon waitable-set.new
WASM_COMP_CANON_WAITABLE_SET_WAIT = 0x20, // canon waitable-set.wait
@ -1225,14 +1273,16 @@ typedef enum WASMComponentCanonType {
WASM_COMP_CANON_WAITABLE_JOIN = 0x23, // canon waitable.join
WASM_COMP_CANON_THREAD_SPAWN_REF = 0x40, // canon thread.spawn_ref
WASM_COMP_CANON_THREAD_SPAWN_INDIRECT = 0x41, // canon thread.spawn_indirect
WASM_COMP_CANON_THREAD_AVAILABLE_PAR = 0x42 // canon thread.available_parallelism
WASM_COMP_CANON_THREAD_AVAILABLE_PAR =
0x42 // canon thread.available_parallelism
} WASMComponentCanonType;
// Canonical options for lift/lower operations
typedef enum WASMComponentCanonOptTag {
WASM_COMP_CANON_OPT_STRING_UTF8 = 0x00, // string-encoding=utf8
WASM_COMP_CANON_OPT_STRING_UTF16 = 0x01, // string-encoding=utf16
WASM_COMP_CANON_OPT_STRING_LATIN1_UTF16 = 0x02, // string-encoding=latin1+utf16
WASM_COMP_CANON_OPT_STRING_LATIN1_UTF16 =
0x02, // string-encoding=latin1+utf16
WASM_COMP_CANON_OPT_MEMORY = 0x03, // (memory m)
WASM_COMP_CANON_OPT_REALLOC = 0x04, // (realloc f)
WASM_COMP_CANON_OPT_POST_RETURN = 0x05, // (post-return f)
@ -1240,7 +1290,8 @@ typedef enum WASMComponentCanonOptTag {
WASM_COMP_CANON_OPT_CALLBACK = 0x07 // (callback f)
} WASMComponentCanonOptTag;
// Canon option with payload, opts := vec<canonopt> where some options carry an immediate:
// Canon option with payload, opts := vec<canonopt> where some options carry an
// immediate:
// - 0x03 (memory m) -> core:memidx (u32)
// - 0x04 (realloc f) -> core:funcidx (u32)
// - 0x05 (post-return f) -> core:funcidx (u32)
@ -1249,14 +1300,26 @@ typedef enum WASMComponentCanonOptTag {
typedef struct WASMComponentCanonOpt {
WASMComponentCanonOptTag tag;
union {
struct { /* no payload */ } string_utf8; /* 0x00 */
struct { /* no payload */ } string_utf16; /* 0x01 */
struct { /* no payload */ } string_latin1_utf16; /* 0x02 */
struct { uint32_t mem_idx; } memory; /* 0x03 */
struct { uint32_t func_idx; } realloc_opt; /* 0x04 */
struct { uint32_t func_idx; } post_return; /* 0x05 */
struct { /* no payload */ } async; /* 0x06 */
struct { uint32_t func_idx; } callback; /* 0x07 */
struct { /* no payload */
} string_utf8; /* 0x00 */
struct { /* no payload */
} string_utf16; /* 0x01 */
struct { /* no payload */
} string_latin1_utf16; /* 0x02 */
struct {
uint32_t mem_idx;
} memory; /* 0x03 */
struct {
uint32_t func_idx;
} realloc_opt; /* 0x04 */
struct {
uint32_t func_idx;
} post_return; /* 0x05 */
struct { /* no payload */
} async; /* 0x06 */
struct {
uint32_t func_idx;
} callback; /* 0x07 */
} payload;
} WASMComponentCanonOpt;
@ -1370,7 +1433,8 @@ typedef struct WASMComponentCanon {
struct {
// No parameters
} waitable_set_new;
// 0x20 cancel?:<cancel?> m:<core:memidx> or 0x21 cancel?:<cancel?> m:<core:memidx>
// 0x20 cancel?:<cancel?> m:<core:memidx> or 0x21 cancel?:<cancel?>
// m:<core:memidx>
struct {
bool cancellable;
uint32_t mem_idx;
@ -1506,88 +1570,253 @@ typedef struct WASMComponent {
#ifdef __cplusplus
extern "C" {
#endif
void set_error_buf_ex(char *error_buf, uint32_t error_buf_size, const char *format, ...);
void
set_error_buf_ex(char *error_buf, uint32_t error_buf_size, const char *format,
...);
bool parse_valtype(const uint8_t **payload, const uint8_t *end, WASMComponentValueType *out, char *error_buf, uint32_t error_buf_size);
bool parse_labelvaltype(const uint8_t **payload, const uint8_t *end, WASMComponentLabelValType *out, char *error_buf, uint32_t error_buf_size);
bool parse_case(const uint8_t **payload, const uint8_t *end, WASMComponentCaseValType *out, char *error_buf, uint32_t error_buf_size);
void free_labelvaltype(WASMComponentLabelValType *labelvaltype);
void free_case(WASMComponentCaseValType *case_valtype);
bool parse_sort(const uint8_t **payload, const uint8_t *end, WASMComponentSort *out, char *error_buf, uint32_t error_buf_size, bool is_core);
bool parse_sort_idx(const uint8_t **payload, const uint8_t *end, WASMComponentSortIdx *out, char *error_buf, uint32_t error_buf_size, bool is_core);
bool parse_extern_desc(const uint8_t **payload, const uint8_t *end, WASMComponentExternDesc *out, char *error_buf, uint32_t error_buf_size);
void free_extern_desc(WASMComponentExternDesc *desc);
bool parse_core_name(const uint8_t **payload, const uint8_t *end, WASMComponentCoreName **out, char *error_buf, uint32_t error_buf_size);
void free_core_name(WASMComponentCoreName *core_name);
bool parse_component_import_name(const uint8_t **payload, const uint8_t *end, WASMComponentImportName *out, char *error_buf, uint32_t error_buf_size);
bool parse_component_export_name(const uint8_t **payload, const uint8_t *end, WASMComponentExportName *out, char *error_buf, uint32_t error_buf_size);
void free_component_import_name(WASMComponentImportName *name_struct);
void free_component_export_name(WASMComponentExportName *name_struct);
bool parse_label_prime(const uint8_t **payload, const uint8_t *end, WASMComponentCoreName **out, char *error_buf, uint32_t error_buf_size);
bool parse_label_prime_vector(const uint8_t **payload, const uint8_t *end, WASMComponentCoreName **out_labels, uint32_t *out_count, char *error_buf, uint32_t error_buf_size);
void free_label_prime(WASMComponentCoreName *label);
void free_label_prime_vector(WASMComponentCoreName *labels, uint32_t count);
bool
parse_valtype(const uint8_t **payload, const uint8_t *end,
WASMComponentValueType *out, char *error_buf,
uint32_t error_buf_size);
bool
parse_labelvaltype(const uint8_t **payload, const uint8_t *end,
WASMComponentLabelValType *out, char *error_buf,
uint32_t error_buf_size);
bool
parse_case(const uint8_t **payload, const uint8_t *end,
WASMComponentCaseValType *out, char *error_buf,
uint32_t error_buf_size);
void
free_labelvaltype(WASMComponentLabelValType *labelvaltype);
void
free_case(WASMComponentCaseValType *case_valtype);
bool
parse_sort(const uint8_t **payload, const uint8_t *end, WASMComponentSort *out,
char *error_buf, uint32_t error_buf_size, bool is_core);
bool
parse_sort_idx(const uint8_t **payload, const uint8_t *end,
WASMComponentSortIdx *out, char *error_buf,
uint32_t error_buf_size, bool is_core);
bool
parse_extern_desc(const uint8_t **payload, const uint8_t *end,
WASMComponentExternDesc *out, char *error_buf,
uint32_t error_buf_size);
void
free_extern_desc(WASMComponentExternDesc *desc);
bool
parse_core_name(const uint8_t **payload, const uint8_t *end,
WASMComponentCoreName **out, char *error_buf,
uint32_t error_buf_size);
void
free_core_name(WASMComponentCoreName *core_name);
bool
parse_component_import_name(const uint8_t **payload, const uint8_t *end,
WASMComponentImportName *out, char *error_buf,
uint32_t error_buf_size);
bool
parse_component_export_name(const uint8_t **payload, const uint8_t *end,
WASMComponentExportName *out, char *error_buf,
uint32_t error_buf_size);
void
free_component_import_name(WASMComponentImportName *name_struct);
void
free_component_export_name(WASMComponentExportName *name_struct);
bool
parse_label_prime(const uint8_t **payload, const uint8_t *end,
WASMComponentCoreName **out, char *error_buf,
uint32_t error_buf_size);
bool
parse_label_prime_vector(const uint8_t **payload, const uint8_t *end,
WASMComponentCoreName **out_labels,
uint32_t *out_count, char *error_buf,
uint32_t error_buf_size);
void
free_label_prime(WASMComponentCoreName *label);
void
free_label_prime_vector(WASMComponentCoreName *labels, uint32_t count);
// UTF-8 validation helpers for component values
// Validates that the given byte slice is well-formed UTF-8 (no overlongs, no surrogates, <= U+10FFFF)
bool wasm_component_validate_utf8(const uint8_t *bytes, uint32_t len);
// Validates that the given byte slice is well-formed UTF-8 (no overlongs, no
// surrogates, <= U+10FFFF)
bool
wasm_component_validate_utf8(const uint8_t *bytes, uint32_t len);
// Validates that the given byte slice encodes exactly one UTF-8 scalar value
bool wasm_component_validate_single_utf8_scalar(const uint8_t *bytes, uint32_t len);
bool
wasm_component_validate_single_utf8_scalar(const uint8_t *bytes, uint32_t len);
bool parse_single_type(const uint8_t **payload, const uint8_t *end, WASMComponentTypes *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);
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_alias_target(const uint8_t **payload, const uint8_t *end, WASMComponentCoreAliasTarget *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);
bool parse_component_decl(const uint8_t **payload, const uint8_t *end, WASMComponentComponentDecl **out, char *error_buf, uint32_t error_buf_size);
bool parse_component_type(const uint8_t **payload, const uint8_t *end, WASMComponentComponentType **out, char *error_buf, uint32_t error_buf_size);
bool parse_result_list(const uint8_t **payload, const uint8_t *end, WASMComponentResultList **out, char *error_buf, uint32_t error_buf_size);
bool
parse_single_type(const uint8_t **payload, const uint8_t *end,
WASMComponentTypes *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);
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_alias_target(const uint8_t **payload, const uint8_t *end,
WASMComponentCoreAliasTarget *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);
bool
parse_component_decl(const uint8_t **payload, const uint8_t *end,
WASMComponentComponentDecl **out, char *error_buf,
uint32_t error_buf_size);
bool
parse_component_type(const uint8_t **payload, const uint8_t *end,
WASMComponentComponentType **out, char *error_buf,
uint32_t error_buf_size);
bool
parse_result_list(const uint8_t **payload, const uint8_t *end,
WASMComponentResultList **out, char *error_buf,
uint32_t error_buf_size);
// Core Type Parsing Functions
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_valtype(const uint8_t **payload, const uint8_t *end, WASMComponentCoreValType *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);
bool
parse_core_valtype(const uint8_t **payload, const uint8_t *end,
WASMComponentCoreValType *out, char *error_buf,
uint32_t error_buf_size);
bool is_wasm_component(WASMHeader header);
bool wasm_component_parse_sections(const uint8_t *buf, uint32_t size, WASMComponent *out_component, LoadArgs *args, unsigned int depth);
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_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 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);
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);
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 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_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_types_section(const uint8_t **payload, uint32_t payload_len, WASMComponentTypeSection *out, char *error_buf, uint32_t error_buf_size, uint32_t *consumed_len);
bool wasm_component_parse_canons_section(const uint8_t **payload, uint32_t payload_len, WASMComponentCanonSection *out, char *error_buf, uint32_t error_buf_size, uint32_t *consumed_len);
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 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_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_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
is_wasm_component(WASMHeader header);
bool
wasm_component_parse_sections(const uint8_t *buf, uint32_t size,
WASMComponent *out_component, LoadArgs *args,
unsigned int depth);
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_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
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);
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);
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
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_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_types_section(const uint8_t **payload,
uint32_t payload_len,
WASMComponentTypeSection *out,
char *error_buf, uint32_t error_buf_size,
uint32_t *consumed_len);
bool
wasm_component_parse_canons_section(const uint8_t **payload,
uint32_t payload_len,
WASMComponentCanonSection *out,
char *error_buf, uint32_t error_buf_size,
uint32_t *consumed_len);
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
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_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_values_section(const uint8_t **payload,
uint32_t payload_len,
WASMComponentValueSection *out,
char *error_buf, uint32_t error_buf_size,
uint32_t *consumed_len);
// Free functions for each section
void wasm_component_free_start_section(WASMComponentSection *section);
void wasm_component_free_values_section(WASMComponentSection *section);
void wasm_component_free_core_custom_section(WASMComponentSection *section);
void wasm_component_free_core_module_section(WASMComponentSection *section);
void wasm_component_free_core_instance_section(WASMComponentSection *section);
void wasm_component_free_core_type_section(WASMComponentSection *section);
void wasm_component_free_component_section(WASMComponentSection *section);
void wasm_component_free_instances_section(WASMComponentSection *section);
void wasm_component_free_alias_section(WASMComponentSection *section);
void wasm_component_free_types_section(WASMComponentSection *section);
void wasm_component_free_canons_section(WASMComponentSection *section);
void wasm_component_free_imports_section(WASMComponentSection *section);
void wasm_component_free_exports_section(WASMComponentSection *section);
void
wasm_component_free_start_section(WASMComponentSection *section);
void
wasm_component_free_values_section(WASMComponentSection *section);
void
wasm_component_free_core_custom_section(WASMComponentSection *section);
void
wasm_component_free_core_module_section(WASMComponentSection *section);
void
wasm_component_free_core_instance_section(WASMComponentSection *section);
void
wasm_component_free_core_type_section(WASMComponentSection *section);
void
wasm_component_free_component_section(WASMComponentSection *section);
void
wasm_component_free_instances_section(WASMComponentSection *section);
void
wasm_component_free_alias_section(WASMComponentSection *section);
void
wasm_component_free_types_section(WASMComponentSection *section);
void
wasm_component_free_canons_section(WASMComponentSection *section);
void
wasm_component_free_imports_section(WASMComponentSection *section);
void
wasm_component_free_exports_section(WASMComponentSection *section);
void wasm_component_free(WASMComponent *component);
void
wasm_component_free(WASMComponent *component);
#ifdef __cplusplus
}
#endif
// Utility functions
static inline bool is_primitive_type(uint8_t value) {
static inline bool
is_primitive_type(uint8_t value)
{
// Component-model primitive value types
// 0x7f=bool, 0x7e=s8, 0x7d=u8, 0x7c=s16, 0x7b=u16, 0x7a=s32, 0x79=u32,
// 0x78=s64, 0x77=u64, 0x76=f32, 0x75=f64, 0x74=char, 0x73=string, 0x64=error-context
// 0x78=s64, 0x77=u64, 0x76=f32, 0x75=f64, 0x74=char, 0x73=string,
// 0x64=error-context
switch (value) {
case WASM_COMP_PRIMVAL_BOOL:
case WASM_COMP_PRIMVAL_S8:
@ -1610,51 +1839,70 @@ static inline bool is_primitive_type(uint8_t value) {
}
// Core type utility functions
static inline bool is_core_numtype(uint8_t value) {
static inline bool
is_core_numtype(uint8_t value)
{
// numtype ::= 0x7F => i32 | 0x7E => i64 | 0x7D => f32 | 0x7C => f64
return (value >= WASM_CORE_NUM_TYPE_F64 && value <= WASM_CORE_NUM_TYPE_I32);
}
static inline bool is_core_vectype(uint8_t value) {
static inline bool
is_core_vectype(uint8_t value)
{
// vectype ::= 0x7B => v128
return (value == WASM_CORE_VECTOR_TYPE_V128);
}
static inline bool is_core_reftype(uint8_t value) {
// reftype ::= 0x63 ht:heaptype => (ref ht) | 0x64 ht:heaptype => (ref null ht)
// heaptype ::= ht:absheaptype => ht | x:s33 => x (if x >= 0)
// absheaptype ::= 0x73 => nofunc | 0x72 => noextern | 0x71 => none | 0x70 => func
static inline bool
is_core_reftype(uint8_t value)
{
// reftype ::= 0x63 ht:heaptype => (ref ht) | 0x64 ht:heaptype => (ref null
// ht) heaptype ::= ht:absheaptype => ht | x:s33 => x (if x >= 0)
// absheaptype ::= 0x73 => nofunc | 0x72 => noextern | 0x71 => none | 0x70
// => func
// | 0x6F => extern | 0x6E => any | 0x6D => eq | 0x6C => i31
// | 0x6B => struct | 0x6A => array
return (value == 0x63 || value == 0x64) ||
(value >= WASM_CORE_ABS_HEAP_TYPE_ARRAY && value <= WASM_CORE_ABS_HEAP_TYPE_NOFUNC);
return (value == 0x63 || value == 0x64)
|| (value >= WASM_CORE_ABS_HEAP_TYPE_ARRAY
&& value <= WASM_CORE_ABS_HEAP_TYPE_NOFUNC);
}
static inline bool is_core_absheaptype(uint8_t value) {
// absheaptype ::= 0x73 => nofunc | 0x72 => noextern | 0x71 => none | 0x70 => func
static inline bool
is_core_absheaptype(uint8_t value)
{
// absheaptype ::= 0x73 => nofunc | 0x72 => noextern | 0x71 => none | 0x70
// => func
// | 0x6F => extern | 0x6E => any | 0x6D => eq | 0x6C => i31
// | 0x6B => struct | 0x6A => array
return (value >= WASM_CORE_ABS_HEAP_TYPE_ARRAY && value <= WASM_CORE_ABS_HEAP_TYPE_NOFUNC);
return (value >= WASM_CORE_ABS_HEAP_TYPE_ARRAY
&& value <= WASM_CORE_ABS_HEAP_TYPE_NOFUNC);
}
static inline bool is_core_packedtype(uint8_t value) {
static inline bool
is_core_packedtype(uint8_t value)
{
// packedtype ::= 0x78 => i8 | 0x77 => i16
return (value == WASM_CORE_PACKED_TYPE_I16 || value == WASM_CORE_PACKED_TYPE_I8);
return (value == WASM_CORE_PACKED_TYPE_I16
|| value == WASM_CORE_PACKED_TYPE_I8);
}
static inline bool is_core_storagetype(uint8_t value) {
static inline bool
is_core_storagetype(uint8_t value)
{
// storagetype ::= t:valtype => t | t:packedtype => t
return is_core_numtype(value) || is_core_vectype(value) ||
is_core_reftype(value) || is_core_packedtype(value);
return is_core_numtype(value) || is_core_vectype(value)
|| is_core_reftype(value) || is_core_packedtype(value);
}
static inline bool is_core_comptype(uint8_t value) {
static inline bool
is_core_comptype(uint8_t value)
{
// comptype ::= 0x5E at:arraytype => array at
// | 0x5F st:structtype => struct st
// | 0x60 ft:functype => func ft
return (value == WASM_CORE_COMPTYPE_ARRAY ||
value == WASM_CORE_COMPTYPE_STRUCT ||
value == WASM_CORE_COMPTYPE_FUNC);
return (value == WASM_CORE_COMPTYPE_ARRAY
|| value == WASM_CORE_COMPTYPE_STRUCT
|| value == WASM_CORE_COMPTYPE_FUNC);
}
// Core type parsing constants
@ -1676,51 +1924,79 @@ typedef enum WASMCoreTypeParsingTag {
} WASMCoreTypeParsingTag;
// Core type parsing helper functions
static inline bool is_core_subtype_tag(uint8_t value) {
return value == WASM_CORE_TYPE_SUBTYPE_FINAL || value == WASM_CORE_TYPE_SUBTYPE_NONFINAL;
static inline bool
is_core_subtype_tag(uint8_t value)
{
return value == WASM_CORE_TYPE_SUBTYPE_FINAL
|| value == WASM_CORE_TYPE_SUBTYPE_NONFINAL;
}
static inline bool is_core_rectype_tag(uint8_t value) {
static inline bool
is_core_rectype_tag(uint8_t value)
{
return value == WASM_CORE_TYPE_REC_GROUP;
}
static inline bool is_core_moduletype_tag(uint8_t value) {
static inline bool
is_core_moduletype_tag(uint8_t value)
{
return value == WASM_CORE_TYPE_MODULE;
}
// Core type validation functions
static inline bool is_valid_core_type_index(uint32_t index, uint32_t max_types) {
static inline bool
is_valid_core_type_index(uint32_t index, uint32_t max_types)
{
return index < max_types;
}
static inline bool is_valid_core_heap_type_index(uint64_t index) {
static inline bool
is_valid_core_heap_type_index(uint64_t index)
{
// s33 validation - check if it's a valid signed 33-bit value
return index <= 0x1FFFFFFFF; // 2^33 - 1
}
// Additional utility functions for component model
bool is_defvaltype_tag(uint8_t byte);
WASMComponentTypesTag get_type_tag(uint8_t first_byte);
bool
is_defvaltype_tag(uint8_t byte);
WASMComponentTypesTag
get_type_tag(uint8_t first_byte);
// Additional helper functions for core type validation
// Core type memory management functions
void free_core_resulttype(WASMComponentCoreResultType *resulttype);
void free_core_structtype(WASMComponentCoreStructType *structtype);
void free_core_type(WASMComponentCoreType *type);
void free_core_type_section(WASMComponentCoreTypeSection *section);
void
free_core_resulttype(WASMComponentCoreResultType *resulttype);
void
free_core_structtype(WASMComponentCoreStructType *structtype);
void
free_core_type(WASMComponentCoreType *type);
void
free_core_type_section(WASMComponentCoreTypeSection *section);
// Additional helper functions for freeing core structures
void free_core_import_desc(WASMComponentCoreImportDesc *import_desc);
void free_core_import(WASMComponentCoreImport *import);
void free_core_export_decl(WASMComponentCoreExportDecl *export_decl);
void free_core_module_decl(WASMComponentCoreModuleDecl *module_decl);
void free_core_moduletype(WASMComponentCoreModuleType *moduletype);
void free_core_deftype(WASMComponentCoreDefType *deftype);
void free_core_functype(WASMComponentCoreFuncType *functype);
void free_core_rectype(WASMComponentCoreRecType *rectype);
void free_core_subtype(WASMComponentCoreSubType *subtype);
void free_core_module_subtype(WASMComponentCoreModuleSubType *module_subtype);
void free_core_comptype(WASMComponentCoreCompType *comptype);
void
free_core_import_desc(WASMComponentCoreImportDesc *import_desc);
void
free_core_import(WASMComponentCoreImport *import);
void
free_core_export_decl(WASMComponentCoreExportDecl *export_decl);
void
free_core_module_decl(WASMComponentCoreModuleDecl *module_decl);
void
free_core_moduletype(WASMComponentCoreModuleType *moduletype);
void
free_core_deftype(WASMComponentCoreDefType *deftype);
void
free_core_functype(WASMComponentCoreFuncType *functype);
void
free_core_rectype(WASMComponentCoreRecType *rectype);
void
free_core_subtype(WASMComponentCoreSubType *subtype);
void
free_core_module_subtype(WASMComponentCoreModuleSubType *module_subtype);
void
free_core_comptype(WASMComponentCoreCompType *comptype);
#endif // WASM_COMPONENT_H

View File

@ -12,12 +12,17 @@
#include "wasm_export.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;
out->sort = wasm_runtime_malloc(sizeof(WASMComponentSort));
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;
}
@ -31,9 +36,11 @@ bool parse_single_alias(const uint8_t **payload, const uint8_t *end, WASMCompone
// Parse alias target using switch
switch (tag) {
case WASM_COMP_ALIAS_TARGET_EXPORT: {
case WASM_COMP_ALIAS_TARGET_EXPORT:
{
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;
}
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;
break;
}
case WASM_COMP_ALIAS_TARGET_CORE_EXPORT: {
case WASM_COMP_ALIAS_TARGET_CORE_EXPORT:
{
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;
}
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;
}
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;
break;
}
case WASM_COMP_ALIAS_TARGET_OUTER: {
case WASM_COMP_ALIAS_TARGET_OUTER:
{
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;
}
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;
}
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->core_sort == WASM_COMP_CORE_SORT_MODULE);
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;
}
break;
}
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;
}
@ -93,10 +110,18 @@ bool parse_single_alias(const uint8_t **payload, const uint8_t *end, WASMCompone
}
// 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) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid payload or output pointer");
if (consumed_len) *consumed_len = 0;
set_error_buf_ex(error_buf, error_buf_size,
"Invalid payload or output pointer");
if (consumed_len)
*consumed_len = 0;
return false;
}
@ -106,8 +131,10 @@ bool wasm_component_parse_alias_section(const uint8_t **payload, uint32_t payloa
// Read alias count
uint64_t alias_count_leb = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &alias_count_leb, error_buf, error_buf_size)) {
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
if (!read_leb((uint8_t **)&p, end, 32, false, &alias_count_leb, error_buf,
error_buf_size)) {
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false;
}
@ -115,33 +142,43 @@ bool wasm_component_parse_alias_section(const uint8_t **payload, uint32_t payloa
out->count = alias_count;
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 (consumed_len) *consumed_len = (uint32_t)(p - *payload);
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false;
}
// 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) {
// Allocate memory for the sort field
if (!parse_single_alias(&p, end, &out->aliases[i], error_buf, error_buf_size)) {
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
set_error_buf_ex(error_buf, error_buf_size, "Failed to parse alias %d", i);
if (!parse_single_alias(&p, end, &out->aliases[i], error_buf,
error_buf_size)) {
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;
}
}
}
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.
return true;
}
// Individual section free functions
void wasm_component_free_alias_section(WASMComponentSection *section) {
if (!section || !section->parsed.alias_section) return;
void
wasm_component_free_alias_section(WASMComponentSection *section)
{
if (!section || !section->parsed.alias_section)
return;
WASMComponentAliasSection *alias_sec = section->parsed.alias_section;
if (alias_sec->aliases) {

View File

@ -13,16 +13,26 @@
#include <stdio.h>
// 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) {
if (consumed_len) *consumed_len = 0;
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)
{
if (consumed_len)
*consumed_len = 0;
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;
}
// Check depth limit BEFORE recursive call
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;
}
@ -30,19 +40,26 @@ bool wasm_component_parse_component_section(const uint8_t **payload, uint32_t pa
unsigned int new_depth = depth + 1;
// 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) {
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;
}
if (consumed_len) *consumed_len = payload_len;
if (consumed_len)
*consumed_len = payload_len;
return true;
}
// Individual section free functions
void wasm_component_free_component_section(WASMComponentSection *section) {
if (!section || !section->parsed.component) return;
void
wasm_component_free_component_section(WASMComponentSection *section)
{
if (!section || !section->parsed.component)
return;
// Recursively free nested components
wasm_component_free(section->parsed.component);

View File

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

View File

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

View File

@ -13,30 +13,46 @@
#include <stdio.h>
// 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) {
if (consumed_len) *consumed_len = 0;
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)
{
if (consumed_len)
*consumed_len = 0;
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;
}
LOG_DEBUG(" Module section: embedded Core WebAssembly module\n");
// 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) {
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;
}
// Print some basic info about the embedded module
LOG_DEBUG(" Types: %u function types\n", wasm_runtime_get_import_count(mod));
LOG_DEBUG(" Exports: %u exports\n", wasm_runtime_get_export_count(mod));
LOG_DEBUG(" Types: %u function types\n",
wasm_runtime_get_import_count(mod));
LOG_DEBUG(" Exports: %u exports\n",
wasm_runtime_get_export_count(mod));
#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(" Memories: %u memories\n", wasm_runtime_get_memories_count(mod));
LOG_DEBUG(" Globals: %u globals\n", wasm_runtime_get_globals_count(mod));
LOG_DEBUG(" Memories: %u memories\n",
wasm_runtime_get_memories_count(mod));
LOG_DEBUG(" Globals: %u globals\n",
wasm_runtime_get_globals_count(mod));
#endif
// 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++) {
wasm_import_t import;
wasm_runtime_get_import_type(mod, i, &import);
LOG_DEBUG(" Import %u: module=\"%s\", name=\"%s\", kind=%u\n",
i,
LOG_DEBUG(
" Import %u: module=\"%s\", name=\"%s\", kind=%u\n", i,
import.module_name ? import.module_name : "<null>",
import.name ? import.name : "<null>",
import.kind);
import.name ? import.name : "<null>", import.kind);
// Print more details about the import
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) {
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,14 +86,13 @@ bool wasm_component_parse_core_module_section(const uint8_t **payload, uint32_t
for (int32_t i = 0; i < export_count; i++) {
wasm_export_t export;
wasm_runtime_get_export_type(mod, i, &export);
LOG_DEBUG(" Export %u: name=\"%s\", kind= %u\n",
i,
export.name ? export.name : "<null>",
export.kind);
LOG_DEBUG(" Export %u: name=\"%s\", kind= %u\n", i,
export.name ? export.name : "<null>", export.kind);
// Print more details about the export
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");
}
}
}
@ -84,17 +100,22 @@ bool wasm_component_parse_core_module_section(const uint8_t **payload, uint32_t
// Store the module pointer directly instead of copying
out->module_handle = (void *)mod;
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;
}
// Individual section free functions
void wasm_component_free_core_module_section(WASMComponentSection *section) {
if (!section || !section->parsed.core_module) return;
void
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
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;
}
wasm_runtime_free(section->parsed.core_module);

View File

@ -12,14 +12,20 @@
#include "wasm_export.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;
uint8_t tag = *p++;
switch (tag) {
case WASM_CORE_LIMITS_MIN: {
case WASM_CORE_LIMITS_MIN:
{
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;
}
@ -27,14 +33,17 @@ bool parse_core_limits(const uint8_t **payload, const uint8_t *end, WASMComponen
out->lim.limits.min = (uint32_t)min;
break;
}
case WASM_CORE_LIMITS_MAX: {
case WASM_CORE_LIMITS_MAX:
{
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;
}
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;
}
@ -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;
break;
}
default: {
set_error_buf_ex(error_buf, error_buf_size, "Invalid limits tag: %02x", tag);
default:
{
set_error_buf_ex(error_buf, error_buf_size,
"Invalid limits tag: %02x", tag);
return false;
}
}
@ -53,11 +64,15 @@ bool parse_core_limits(const uint8_t **payload, const uint8_t *end, WASMComponen
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;
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;
}
@ -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
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;
}
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;
}
@ -87,7 +105,11 @@ static bool parse_core_heaptype(const uint8_t **payload, const uint8_t *end, WAS
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;
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)
if (tag == 0x63 || tag == 0x64) {
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;
}
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->type.ref_type = WASM_CORE_REFTYPE_FUNC_REF;
*payload = p;
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->type.ref_type = WASM_CORE_REFTYPE_EXTERN_REF;
*payload = p;
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;
}
// 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) {
out->tag = WASM_CORE_VALTYPE_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;
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;
}
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;
}
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;
uint8_t tag = *p++;
switch (tag) {
case WASM_CORE_IMPORTDESC_FUNC: {
case WASM_CORE_IMPORTDESC_FUNC:
{
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;
}
@ -172,25 +208,33 @@ bool parse_core_import_desc(const uint8_t **payload, const uint8_t *end, WASMCom
break;
}
case WASM_CORE_IMPORTDESC_TABLE: {
case WASM_CORE_IMPORTDESC_TABLE:
{
uint8_t ref_type_tag = *p++;
if (ref_type_tag == WASM_CORE_REFTYPE_FUNC_REF) {
out->type = WASM_CORE_IMPORTDESC_TABLE;
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->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;
}
WASMComponentCoreLimits *limits = wasm_runtime_malloc(sizeof(WASMComponentCoreLimits));
WASMComponentCoreLimits *limits =
wasm_runtime_malloc(sizeof(WASMComponentCoreLimits));
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;
}
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);
return false;
}
@ -200,13 +244,17 @@ bool parse_core_import_desc(const uint8_t **payload, const uint8_t *end, WASMCom
break;
}
case WASM_CORE_IMPORTDESC_MEMORY: {
WASMComponentCoreLimits *limits = wasm_runtime_malloc(sizeof(WASMComponentCoreLimits));
case WASM_CORE_IMPORTDESC_MEMORY:
{
WASMComponentCoreLimits *limits =
wasm_runtime_malloc(sizeof(WASMComponentCoreLimits));
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;
}
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);
return false;
}
@ -216,8 +264,10 @@ bool parse_core_import_desc(const uint8_t **payload, const uint8_t *end, WASMCom
break;
}
case WASM_CORE_IMPORTDESC_GLOBAL: {
if (!parse_core_valtype(&p, end, &out->desc.global_type.val_type, error_buf, error_buf_size)) {
case WASM_CORE_IMPORTDESC_GLOBAL:
{
if (!parse_core_valtype(&p, end, &out->desc.global_type.val_type,
error_buf, error_buf_size)) {
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++;
if (mutable_tag == WASM_CORE_GLOBAL_MUTABLE) {
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;
} 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;
}
break;
}
default: {
set_error_buf_ex(error_buf, error_buf_size, "Invalid import descriptor tag: %02x", tag);
default:
{
set_error_buf_ex(error_buf, error_buf_size,
"Invalid import descriptor tag: %02x", tag);
return false;
}
}
@ -244,7 +299,11 @@ bool parse_core_import_desc(const uint8_t **payload, const uint8_t *end, WASMCom
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;
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;
WASMComponentCoreImportDesc *import_desc = wasm_runtime_malloc(sizeof(WASMComponentCoreImportDesc));
WASMComponentCoreImportDesc *import_desc =
wasm_runtime_malloc(sizeof(WASMComponentCoreImportDesc));
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;
}
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);
return false;
}
@ -277,26 +339,34 @@ bool parse_core_import(const uint8_t **payload, const uint8_t *end, WASMComponen
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;
uint8_t tag = *p++;
if (tag == 0x01) {
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;
}
out->ct = (uint32_t)ct_leb;
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;
}
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;
}
@ -304,7 +374,11 @@ bool parse_alias_target(const uint8_t **payload, const uint8_t *end, WASMCompone
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;
/* 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;
}
if (!parse_alias_target(&p, end, &out->alias_target, error_buf, error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to parse alias target");
if (!parse_alias_target(&p, end, &out->alias_target, error_buf,
error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size,
"Failed to parse alias target");
return false;
}
@ -321,7 +397,11 @@ bool parse_core_alias(const uint8_t **payload, const uint8_t *end, WASMComponent
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;
/* core:exportdecl ::= nm:<core:name> d:<core:exportdesc> */
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;
WASMComponentCoreImportDesc *export_desc = wasm_runtime_malloc(sizeof(WASMComponentCoreImportDesc));
WASMComponentCoreImportDesc *export_desc =
wasm_runtime_malloc(sizeof(WASMComponentCoreImportDesc));
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;
}
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);
return false;
}
@ -346,69 +429,98 @@ bool parse_core_export_decl(const uint8_t **payload, const uint8_t *end, WASMCom
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;
uint8_t tag = *p++;
out->tag = tag;
switch (tag) {
case WASM_CORE_MODULEDECL_IMPORT: {
out->decl.import_decl.import = wasm_runtime_malloc(sizeof(WASMComponentCoreImport));
case WASM_CORE_MODULEDECL_IMPORT:
{
out->decl.import_decl.import =
wasm_runtime_malloc(sizeof(WASMComponentCoreImport));
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;
}
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;
}
break;
}
case WASM_CORE_MODULEDECL_TYPE: {
out->decl.type_decl.type = wasm_runtime_malloc(sizeof(WASMComponentCoreType));
case WASM_CORE_MODULEDECL_TYPE:
{
out->decl.type_decl.type =
wasm_runtime_malloc(sizeof(WASMComponentCoreType));
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;
}
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) {
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;
}
if (!parse_single_core_type(&p, end, 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");
if (!parse_single_core_type(&p, end,
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;
}
break;
}
case WASM_CORE_MODULEDECL_ALIAS: {
out->decl.alias_decl.alias = wasm_runtime_malloc(sizeof(WASMComponentCoreAlias));
case WASM_CORE_MODULEDECL_ALIAS:
{
out->decl.alias_decl.alias =
wasm_runtime_malloc(sizeof(WASMComponentCoreAlias));
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;
}
if (!parse_core_alias(&p, end, out->decl.alias_decl.alias, error_buf, error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to parse alias declaration");
if (!parse_core_alias(&p, end, out->decl.alias_decl.alias,
error_buf, error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size,
"Failed to parse alias declaration");
return false;
}
break;
}
case WASM_CORE_MODULEDECL_EXPORT: {
out->decl.export_decl.export_decl = wasm_runtime_malloc(sizeof(WASMComponentCoreExportDecl));
case WASM_CORE_MODULEDECL_EXPORT:
{
out->decl.export_decl.export_decl =
wasm_runtime_malloc(sizeof(WASMComponentCoreExportDecl));
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;
}
if (!parse_core_export_decl(&p, end, 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");
if (!parse_core_export_decl(&p, end,
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;
}
break;
}
default: {
set_error_buf_ex(error_buf, error_buf_size, "Invalid module declaration tag: %02x", tag);
default:
{
set_error_buf_ex(error_buf, error_buf_size,
"Invalid module declaration tag: %02x", tag);
return false;
}
}
@ -416,11 +528,16 @@ bool parse_core_module_decl(const uint8_t **payload, const uint8_t *end, WASMCom
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;
// Expect vec(moduledecl): count then that many moduledecl
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;
}
@ -428,16 +545,20 @@ bool parse_core_moduletype(const uint8_t **payload, const uint8_t *end, WASMComp
out->decl_count = count;
if (count > 0) {
out->declarations = wasm_runtime_malloc(sizeof(WASMComponentCoreModuleDecl) * count);
out->declarations =
wasm_runtime_malloc(sizeof(WASMComponentCoreModuleDecl) * count);
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;
}
// 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++) {
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;
}
}
@ -447,10 +568,15 @@ bool parse_core_moduletype(const uint8_t **payload, const uint8_t *end, WASMComp
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;
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;
}
@ -460,12 +586,15 @@ bool parse_single_core_type(const uint8_t **payload, const uint8_t *end, WASMCom
if (b0 == 0x50) {
p++; // consume 0x50
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) {
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;
}
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;
}
*payload = p;
@ -474,42 +603,57 @@ bool parse_single_core_type(const uint8_t **payload, const uint8_t *end, WASMCom
// 2) rectype (GC): 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;
}
// 3) subtype (GC): 0x00 followed by {0x50,0x4F,0x5E,0x5F,0x60}
if (b0 == 0x00) {
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;
}
uint8_t b1 = *(p + 1);
if (b1 == 0x50 || b1 == 0x4F || b1 == 0x5E || b1 == 0x5F || b1 == 0x60) {
set_error_buf_ex(error_buf, error_buf_size, "WebAssembly 3.0 core:subtype (0x00 0x%02x ...) not supported", b1);
if (b1 == 0x50 || b1 == 0x4F || b1 == 0x5E || b1 == 0x5F
|| b1 == 0x60) {
set_error_buf_ex(
error_buf, error_buf_size,
"WebAssembly 3.0 core:subtype (0x00 0x%02x ...) not supported",
b1);
return false;
}
}
// 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;
}
// Section 3: type section (component model type section, not the core wasm type 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) {
// Section 3: type section (component model type section, not the core wasm type
// 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) {
return false;
}
if (consumed_len) *consumed_len = 0;
if (consumed_len)
*consumed_len = 0;
const uint8_t *p = *payload;
const uint8_t *end = *payload + payload_len;
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;
}
@ -519,19 +663,23 @@ bool wasm_component_parse_core_type_section(const uint8_t **payload, uint32_t pa
if (count > 0) {
out->types = wasm_runtime_malloc(sizeof(WASMComponentCoreType) * count);
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;
}
memset(out->types, 0, sizeof(WASMComponentCoreType) * count);
for (uint32_t i = 0; i < count; i++) {
WASMComponentCoreDefType *dt = wasm_runtime_malloc(sizeof(WASMComponentCoreDefType));
WASMComponentCoreDefType *dt =
wasm_runtime_malloc(sizeof(WASMComponentCoreDefType));
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;
}
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);
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;
}
// 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) {
return;
}
WASMComponentCoreTypeSection *core_type_section = section->parsed.core_type_section;
WASMComponentCoreTypeSection *core_type_section =
section->parsed.core_type_section;
if (core_type_section->types) {
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
void free_core_import_desc(WASMComponentCoreImportDesc *import_desc) {
void
free_core_import_desc(WASMComponentCoreImportDesc *import_desc)
{
if (!import_desc) {
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) {
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) {
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) {
return;
}
@ -654,14 +814,17 @@ void free_core_module_decl(WASMComponentCoreModuleDecl *module_decl) {
break;
case WASM_CORE_MODULEDECL_EXPORT:
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);
}
break;
}
}
void free_core_moduletype(WASMComponentCoreModuleType *moduletype) {
void
free_core_moduletype(WASMComponentCoreModuleType *moduletype)
{
if (!moduletype) {
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) {
return;
}
@ -701,7 +866,9 @@ void free_core_deftype(WASMComponentCoreDefType *deftype) {
}
}
void free_core_type(WASMComponentCoreType *type) {
void
free_core_type(WASMComponentCoreType *type)
{
if (!type) {
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) {
return;
}
@ -726,7 +895,9 @@ void free_core_type_section(WASMComponentCoreTypeSection *section) {
}
// Additional helper functions for freeing core structures
void free_core_functype(WASMComponentCoreFuncType *functype) {
void
free_core_functype(WASMComponentCoreFuncType *functype)
{
if (!functype) {
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) {
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) {
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) {
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) {
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) {
return;
}
@ -806,7 +987,9 @@ void free_core_subtype(WASMComponentCoreSubType *subtype) {
free_core_comptype(&subtype->comptype);
}
void free_core_module_subtype(WASMComponentCoreModuleSubType *module_subtype) {
void
free_core_module_subtype(WASMComponentCoreModuleSubType *module_subtype)
{
if (!module_subtype) {
return;
}

View File

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

View File

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

View File

@ -13,10 +13,18 @@
#include <stdio.h>
// 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) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid payload or output pointer");
if (consumed_len) *consumed_len = 0;
set_error_buf_ex(error_buf, error_buf_size,
"Invalid payload or output pointer");
if (consumed_len)
*consumed_len = 0;
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;
if (p >= end) {
set_error_buf_ex(error_buf, error_buf_size, "Unexpected end of buffer when reading exports count");
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
set_error_buf_ex(error_buf, error_buf_size,
"Unexpected end of buffer when reading exports count");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false;
}
uint64_t export_count_leb = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &export_count_leb, error_buf, error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to read exports count");
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
if (!read_leb((uint8_t **)&p, end, 32, false, &export_count_leb, error_buf,
error_buf_size)) {
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;
}
@ -39,111 +52,156 @@ bool wasm_component_parse_exports_section(const uint8_t **payload, uint32_t payl
out->count = export_count;
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) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for exports");
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
set_error_buf_ex(error_buf, error_buf_size,
"Failed to allocate memory for exports");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
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);
// Parsing every export
for (uint32_t i = 0; i < export_count; i++) {
// Parsing 'exportname'
if (p >= end) {
set_error_buf_ex(error_buf, error_buf_size, "Unexpected end of buffer when reading export name for export %u", i);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
set_error_buf_ex(error_buf, error_buf_size,
"Unexpected end of buffer when reading export "
"name for export %u",
i);
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false;
}
WASMComponentExportName *export_name = wasm_runtime_malloc(sizeof(WASMComponentExportName));
WASMComponentExportName *export_name =
wasm_runtime_malloc(sizeof(WASMComponentExportName));
if (!export_name) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for export_name");
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
set_error_buf_ex(error_buf, error_buf_size,
"Failed to allocate memory for export_name");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
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) {
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);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false;
}
out->exports[i].export_name = export_name;
// 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) {
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);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
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) {
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(export_name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
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)
if (p >= end) {
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);
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;
}
uint8_t opt_extern_desc = *p++;
if (opt_extern_desc == WASM_COMP_OPTIONAL_TRUE) {
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);
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;
}
WASMComponentExternDesc *extern_desc = wasm_runtime_malloc(sizeof(WASMComponentExternDesc));
bool extern_status = parse_extern_desc(&p, end, extern_desc, error_buf, error_buf_size);
WASMComponentExternDesc *extern_desc =
wasm_runtime_malloc(sizeof(WASMComponentExternDesc));
bool extern_status = parse_extern_desc(
&p, end, extern_desc, error_buf, error_buf_size);
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(out->exports[i].sort_idx->sort);
wasm_runtime_free(out->exports[i].sort_idx);
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;
}
out->exports[i].extern_desc = extern_desc;
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
out->exports[i].extern_desc = NULL;
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;
}
}
}
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return true;
}
// Individual section free functions
void wasm_component_free_exports_section(WASMComponentSection *section) {
if (!section || !section->parsed.export_section) return;
void
wasm_component_free_exports_section(WASMComponentSection *section)
{
if (!section || !section->parsed.export_section)
return;
WASMComponentExportSection *export_sec = section->parsed.export_section;
if (export_sec->exports) {

File diff suppressed because it is too large Load Diff

View File

@ -13,10 +13,18 @@
#include <stdio.h>
// 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) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid payload or output pointer");
if (consumed_len) *consumed_len = 0;
set_error_buf_ex(error_buf, error_buf_size,
"Invalid payload or output pointer");
if (consumed_len)
*consumed_len = 0;
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)
// Read the count of imports (LEB128-encoded)
uint64_t import_count_leb = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &import_count_leb, error_buf, error_buf_size)) {
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
if (!read_leb((uint8_t **)&p, end, 32, false, &import_count_leb, error_buf,
error_buf_size)) {
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false;
}
@ -35,10 +45,13 @@ bool wasm_component_parse_imports_section(const uint8_t **payload, uint32_t payl
out->count = import_count;
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) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for imports");
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
set_error_buf_ex(error_buf, error_buf_size,
"Failed to allocate memory for imports");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
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);
for (uint32_t i = 0; i < import_count; ++i) {
// importname' ::= 0x00 len:<u32> in:<importname> => in (if len = |in|)
// | 0x01 len:<u32> in:<importname> vs:<versionsuffix'> => in vs (if len = |in|)
// importname' ::= 0x00 len:<u32> in:<importname> => in (if len =
// |in|)
// | 0x01 len:<u32> in:<importname> vs:<versionsuffix'>
// => in vs (if len = |in|)
// 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) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for import_name");
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
set_error_buf_ex(error_buf, error_buf_size,
"Failed to allocate memory for import_name");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false;
}
// Initialize the struct to zero to avoid garbage data
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) {
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);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
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))
// | 0x02 b:<valuebound> => (value b)
// | 0x03 b:<typebound> => (type b)
// | 0x04 i:<typeidx> => (component (type i))
// | 0x05 i:<typeidx> => (instance (type i))
// Parse externdesc (core module, func, value, type, component, instance)
WASMComponentExternDesc *extern_desc = wasm_runtime_malloc(sizeof(WASMComponentExternDesc));
// Parse externdesc (core module, func, value, type, component,
// instance)
WASMComponentExternDesc *extern_desc =
wasm_runtime_malloc(sizeof(WASMComponentExternDesc));
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);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false;
}
// Initialize the struct to zero to avoid garbage data
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) {
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(import_name);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
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;
}
// Individual section free functions
void wasm_component_free_imports_section(WASMComponentSection *section) {
if (!section || !section->parsed.import_section) return;
void
wasm_component_free_imports_section(WASMComponentSection *section)
{
if (!section || !section->parsed.import_section)
return;
WASMComponentImportSection *import_sec = section->parsed.import_section;
if (import_sec->imports) {

View File

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

View File

@ -13,8 +13,15 @@
#include <stdio.h>
// 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) {
if (consumed_len) *consumed_len = 0;
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)
{
if (consumed_len)
*consumed_len = 0;
if (!payload || !*payload || !out || payload_len == 0) {
return false;
}
@ -29,15 +36,18 @@ bool wasm_component_parse_start_section(const uint8_t **payload, uint32_t payloa
out->result = 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");
return false;
}
out->func_idx = (uint32_t)func_idx;
uint64_t args_count = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &args_count, error_buf, error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to read args count");
if (!read_leb((uint8_t **)&p, end, 32, false, &args_count, error_buf,
error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size,
"Failed to read args count");
return false;
}
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) {
out->value_args = wasm_runtime_malloc(sizeof(uint32_t) * args_count);
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;
}
for (uint64_t i = 0; i < args_count; i++) {
uint64_t value_idx = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &value_idx, error_buf, error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to read value idx");
if (!read_leb((uint8_t **)&p, end, 32, false, &value_idx, error_buf,
error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size,
"Failed to read value idx");
// cleanup
wasm_runtime_free(out->value_args);
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;
if (!read_leb((uint8_t **)&p, end, 32, false, &result_leb, error_buf, error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to read result count");
if (!read_leb((uint8_t **)&p, end, 32, false, &result_leb, error_buf,
error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size,
"Failed to read result count");
if (out->value_args) {
wasm_runtime_free(out->value_args);
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;
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return true;
}
// 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) {
return;
}

File diff suppressed because it is too large Load Diff

View File

@ -30,27 +30,31 @@ typedef struct WASMComponentValidationContext {
HashMap *import_names;
HashMap *export_names;
// Flat type lookup array: types[i] is the WASMComponentTypes* for type index i
// NULL for types introduced via import or alias
// type_is_local[i] is true if the type was defined in a local type section
// Flat type lookup array: types[i] is the WASMComponentTypes* for type
// index i NULL for types introduced via import or alias type_is_local[i] is
// true if the type was defined in a local type section
WASMComponentTypes **types;
bool *type_is_local;
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;
uint32_t value_consumed_capacity;
// Func-to-type tracking: func_type_indexes[i] is the type index for function i
// UINT32_MAX for functions whose type is unknown (e.g. aliased)
// Func-to-type tracking: func_type_indexes[i] is the type index for
// function i UINT32_MAX for functions whose type is unknown (e.g. aliased)
uint32_t *func_type_indexes;
uint32_t func_type_indexes_capacity;
// Resource type names: tracks import/export names that introduce resource types
// Used for [static] annotation validation
// Resource type names: tracks import/export names that introduce resource
// types Used for [static] annotation validation
HashMap *resource_type_names;
} 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

View File

@ -14,26 +14,33 @@
// Helper function to parse a value
// Helper to check if f32 bytes represent canonical NaN
static bool is_canonical_f32_nan(const uint8_t *bytes) {
return bytes[0] == 0x00 && bytes[1] == 0x00 &&
bytes[2] == 0xC0 && bytes[3] == 0x7F;
static bool
is_canonical_f32_nan(const uint8_t *bytes)
{
return bytes[0] == 0x00 && bytes[1] == 0x00 && bytes[2] == 0xC0
&& bytes[3] == 0x7F;
}
// Helper to check if f64 bytes represent canonical NaN
static bool is_canonical_f64_nan(const uint8_t *bytes) {
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;
static bool
is_canonical_f64_nan(const uint8_t *bytes)
{
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)
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) {
// Check f64 NaN pattern (exponent all 1s, mantissa non-zero)
uint64_t bits = 0;
memcpy(&bits, bytes, 8);
return ((bits >> 52) & 0x7FF) == 0x7FF && (bits & 0xFFFFFFFFFFFFF) != 0;
} else {
}
else {
// Check f32 NaN pattern (exponent all 1s, mantissa non-zero)
uint32_t bits = 0;
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||)
static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMComponentValue *out, char *error_buf, uint32_t error_buf_size) {
// value ::= t:<valtype> len:<core:u32> v:<val(t)> => (value t v) (where len =
// ||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;
// Parse the value type
WASMComponentValueType *val_type = NULL;
val_type = wasm_runtime_malloc(sizeof(WASMComponentValueType));
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;
}
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;
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);
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
// the declared len matches the actual encoding size for handled cases.
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);
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) {
switch (val_type->type_specific.primval_type) {
case WASM_COMP_PRIMVAL_BOOL: {
case WASM_COMP_PRIMVAL_BOOL:
{
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);
return false;
}
uint8_t b = *p;
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);
return false;
}
@ -95,9 +115,12 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break;
}
case WASM_COMP_PRIMVAL_U8: {
case WASM_COMP_PRIMVAL_U8:
{
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);
return false;
}
@ -105,9 +128,12 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break;
}
case WASM_COMP_PRIMVAL_S8: {
case WASM_COMP_PRIMVAL_S8:
{
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);
return false;
}
@ -115,22 +141,30 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break;
}
case WASM_COMP_PRIMVAL_S16: {
case WASM_COMP_PRIMVAL_S16:
{
// signed LEB128 (1..3 bytes for 16-bit)
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);
return false;
}
uint64_t tmp = 0;
uint8_t *q = (uint8_t *)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);
return false;
}
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);
return false;
}
@ -138,22 +172,30 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break;
}
case WASM_COMP_PRIMVAL_U16: {
case WASM_COMP_PRIMVAL_U16:
{
// unsigned LEB128 (1..3 bytes for 16-bit)
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);
return false;
}
uint64_t tmp = 0;
uint8_t *q = (uint8_t *)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);
return false;
}
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);
return false;
}
@ -161,22 +203,30 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break;
}
case WASM_COMP_PRIMVAL_S32: {
case WASM_COMP_PRIMVAL_S32:
{
// signed LEB128 (1..5 bytes)
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);
return false;
}
uint64_t tmp = 0;
uint8_t *q = (uint8_t *)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);
return false;
}
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);
return false;
}
@ -184,22 +234,30 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break;
}
case WASM_COMP_PRIMVAL_U32: {
case WASM_COMP_PRIMVAL_U32:
{
// unsigned LEB128 (1..5 bytes)
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);
return false;
}
uint64_t tmp = 0;
uint8_t *q = (uint8_t *)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);
return false;
}
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);
return false;
}
@ -207,22 +265,30 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break;
}
case WASM_COMP_PRIMVAL_S64: {
case WASM_COMP_PRIMVAL_S64:
{
// signed LEB128 (1..10 bytes)
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);
return false;
}
uint64_t tmp = 0;
uint8_t *q = (uint8_t *)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);
return false;
}
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);
return false;
}
@ -230,22 +296,30 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break;
}
case WASM_COMP_PRIMVAL_U64: {
case WASM_COMP_PRIMVAL_U64:
{
// unsigned LEB128 (1..10 bytes)
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);
return false;
}
uint64_t tmp = 0;
uint8_t *q = (uint8_t *)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);
return false;
}
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);
return false;
}
@ -253,18 +327,23 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break;
}
case WASM_COMP_PRIMVAL_F32: {
case WASM_COMP_PRIMVAL_F32:
{
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);
return false;
}
if (is_canonical_f32_nan(p)) {
p += 4;
break;
} else if (is_any_nan(p, false)) {
}
else if (is_any_nan(p, false)) {
// 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);
return false;
}
@ -272,18 +351,23 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break;
}
case WASM_COMP_PRIMVAL_F64: {
case WASM_COMP_PRIMVAL_F64:
{
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);
return false;
}
if (is_canonical_f64_nan(p)) {
p += 8;
break;
} else if (is_any_nan(p, true)) {
}
else if (is_any_nan(p, true)) {
// 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);
return false;
}
@ -292,16 +376,21 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break;
}
case WASM_COMP_PRIMVAL_CHAR: {
case WASM_COMP_PRIMVAL_CHAR:
{
// val(char) ::= b*:<core:byte>* => c (where b* = core:utf8(c))
// Expect 1..4 bytes and ensure exactly one UTF-8 scalar
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);
return false;
}
if (!wasm_component_validate_single_utf8_scalar(p, out->core_data_len)) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid UTF-8 scalar for char");
if (!wasm_component_validate_single_utf8_scalar(
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);
return false;
}
@ -309,36 +398,48 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
break;
}
case WASM_COMP_PRIMVAL_STRING: {
case WASM_COMP_PRIMVAL_STRING:
{
// 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;
uint8_t *q = (uint8_t *)p;
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);
return false;
}
uint32_t leb_len = (uint32_t)(q - before);
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);
return false;
}
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);
return false;
}
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);
return false;
}
p = q + name_len;
break;
}
default: {
default:
{
set_error_buf_ex(error_buf, error_buf_size,
"Unknown primitive value type 0x%02x",
val_type->type_specific.primval_type);
@ -346,11 +447,13 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
return false;
}
}
} else {
}
else {
// valtype in the values section must be either primval or typeidx
if (val_type->type != WASM_COMP_VAL_TYPE_IDX) {
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 "
"(expected typeidx)",
(unsigned)val_type->type);
wasm_runtime_free(val_type);
return false;
@ -361,7 +464,8 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
// - just advance by the declared len and validate bounds
if ((uint32_t)(end - p) < out->core_data_len) {
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 "
"payload: need %u, have %zu",
out->core_data_len, (size_t)(end - p));
wasm_runtime_free(val_type);
return false;
@ -377,10 +481,18 @@ static bool parse_value(const uint8_t **payload, const uint8_t *end, WASMCompone
}
// 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) {
set_error_buf_ex(error_buf, error_buf_size, "Invalid payload or output pointer");
if (consumed_len) *consumed_len = 0;
set_error_buf_ex(error_buf, error_buf_size,
"Invalid payload or output pointer");
if (consumed_len)
*consumed_len = 0;
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)
// Read the count of values (LEB128-encoded)
uint64_t value_count_leb = 0;
if (!read_leb((uint8_t **)&p, end, 32, false, &value_count_leb, error_buf, error_buf_size)) {
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
if (!read_leb((uint8_t **)&p, end, 32, false, &value_count_leb, error_buf,
error_buf_size)) {
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return false;
}
@ -399,10 +513,13 @@ bool wasm_component_parse_values_section(const uint8_t **payload, uint32_t paylo
out->count = value_count;
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) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to allocate memory for values");
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
set_error_buf_ex(error_buf, error_buf_size,
"Failed to allocate memory for values");
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
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);
for (uint32_t i = 0; i < value_count; ++i) {
if (!parse_value(&p, end, &out->values[i], error_buf, error_buf_size)) {
set_error_buf_ex(error_buf, error_buf_size, "Failed to parse value %u", i);
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
if (!parse_value(&p, end, &out->values[i], error_buf,
error_buf_size)) {
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;
}
}
}
if (consumed_len) *consumed_len = (uint32_t)(p - *payload);
if (consumed_len)
*consumed_len = (uint32_t)(p - *payload);
return true;
}
// 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) {
return;
}

View File

@ -652,17 +652,20 @@ wasm_runtime_init_internal(void)
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) {
return false;
}
// 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
// For Preview 1 modules: version=0x0001, layer=0x0000 (combined: 0x00000001)
// For Preview 2 components: version=0x000d, layer=0x0001
// For Preview 1 modules: version=0x0001, layer=0x0000 (combined:
// 0x00000001) For Preview 2 components: version=0x000d, layer=0x0001
uint16_t version = (uint16_t)buf[4] | ((uint16_t)buf[5] << 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;
}
bool is_wasm_module(WASMHeader header) {
bool
is_wasm_module(WASMHeader header)
{
if (header.magic != WASM_MAGIC_NUMBER) {
return false;
}
// 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) {
return false;
}
@ -4556,7 +4562,6 @@ wasm_runtime_get_function_count(WASMModuleCommon *const module)
return -1;
}
if (module->module_type == Wasm_Module_Bytecode) {
const WASMModule *wasm_module = (const WASMModule *)module;
return (int32)wasm_module->function_count;
@ -4573,7 +4578,6 @@ wasm_runtime_get_table_count(WASMModuleCommon *const module)
return -1;
}
if (module->module_type == Wasm_Module_Bytecode) {
const WASMModule *wasm_module = (const WASMModule *)module;
return (int32)wasm_module->table_count;
@ -4590,7 +4594,6 @@ wasm_runtime_get_memories_count(WASMModuleCommon *const module)
return -1;
}
if (module->module_type == Wasm_Module_Bytecode) {
const WASMModule *wasm_module = (const WASMModule *)module;
return (int32)wasm_module->memory_count;
@ -4607,7 +4610,6 @@ wasm_runtime_get_globals_count(WASMModuleCommon *const module)
return -1;
}
if (module->module_type == Wasm_Module_Bytecode) {
const WASMModule *wasm_module = (const WASMModule *)module;
return (int32)wasm_module->global_count;

View File

@ -374,14 +374,16 @@ typedef struct SharedHeapInitArgs {
*
* @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
*
* @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

View File

@ -7108,8 +7108,9 @@ load(const uint8 *buf, uint32 size, WASMModule *module,
module->package_version = version;
if (!create_sections(buf, size, &section_list, error_buf, error_buf_size)
|| !load_from_sections(module, section_list, false, wasm_binary_freeable,
no_resolve, error_buf, error_buf_size)) {
|| !load_from_sections(module, section_list, false,
wasm_binary_freeable, no_resolve, error_buf,
error_buf_size)) {
destroy_sections(section_list);
return false;
}

View File

@ -1533,7 +1533,6 @@ export_tables_instantiate(const WASMModule *module,
return export_tables;
}
#if WASM_ENABLE_TAGS != 0
/**
* Destroy export function instances.

View File

@ -17,7 +17,8 @@
#define HEAP_SIZE (100 * 1024 * 1024) // 100 MB
class ComponentHelper {
class ComponentHelper
{
public:
RuntimeInitArgs init_args;
unsigned char *component_raw = NULL;
@ -49,9 +50,13 @@ public:
void do_setup();
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
uint32_t get_memory_offsets(const std::string& key); // Get memory offsets from map
void load_memory_offsets(
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

View File

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