srctree

Robin Linden parent 26e7d10e e26fa719
wasm: Implement parsing custom sections

inlinesplit
wasm/byte_code_parser.cpp added: 70, removed: 6, total 64
@@ -471,6 +471,28 @@ tl::expected<Module, ModuleParseError> ByteCodeParser::parse_module(std::istream
 
auto id = static_cast<SectionId>(id_byte);
switch (id) {
case SectionId::Custom: {
auto before = static_cast<std::int64_t>(is.tellg());
auto name = parse<std::string>(is);
if (!name) {
return tl::unexpected{ModuleParseError::InvalidCustomSection};
}
 
auto consumed_by_name = static_cast<int64_t>(is.tellg()) - before;
auto remaining_size = static_cast<int64_t>(*size) - consumed_by_name;
 
std::vector<std::uint8_t> data;
data.resize(remaining_size);
if (!is.read(reinterpret_cast<char *>(data.data()), data.size())) {
return tl::unexpected{ModuleParseError::InvalidCustomSection};
}
 
module.custom_sections.push_back(CustomSection{
.name = *std::move(name),
.data = std::move(data),
});
break;
}
case SectionId::Type:
module.type_section = parse_type_section(is);
if (!module.type_section) {
 
wasm/byte_code_parser.h added: 70, removed: 6, total 64
@@ -19,6 +19,7 @@ enum class ModuleParseError {
UnsupportedVersion,
InvalidSectionId,
InvalidSize,
InvalidCustomSection,
InvalidTypeSection,
InvalidImportSection,
InvalidFunctionSection,
@@ -43,6 +44,8 @@ constexpr std::string_view to_string(ModuleParseError e) {
return "Invalid section id";
case ModuleParseError::InvalidSize:
return "Invalid section size";
case ModuleParseError::InvalidCustomSection:
return "Invalid custom section";
case ModuleParseError::InvalidTypeSection:
return "Invalid type section";
case ModuleParseError::InvalidImportSection:
 
wasm/byte_code_parser_test.cpp added: 70, removed: 6, total 64
@@ -64,6 +64,7 @@ void parse_error_to_string_tests() {
expect_eq(wasm::to_string(ModuleParseError::UnsupportedVersion), "Unsupported version");
expect_eq(wasm::to_string(ModuleParseError::InvalidSectionId), "Invalid section id");
expect_eq(wasm::to_string(ModuleParseError::InvalidSize), "Invalid section size");
expect_eq(wasm::to_string(ModuleParseError::InvalidCustomSection), "Invalid custom section");
expect_eq(wasm::to_string(ModuleParseError::InvalidTypeSection), "Invalid type section");
expect_eq(wasm::to_string(ModuleParseError::InvalidImportSection), "Invalid import section");
expect_eq(wasm::to_string(ModuleParseError::InvalidFunctionSection), "Invalid function section");
@@ -80,6 +81,35 @@ void parse_error_to_string_tests() {
});
}
 
void custom_section_tests() {
etest::test("custom section", [] {
std::vector<std::uint8_t> content{2, 'h', 'i', 1, 2, 3};
auto module = ByteCodeParser::parse_module(make_module_bytes(SectionId::Custom, content)).value();
expect_eq(module.custom_sections.at(0),
wasm::CustomSection{
.name = "hi",
.data = {1, 2, 3},
});
});
 
etest::test("custom section, eof in name", [] {
std::vector<std::uint8_t> content{2, 'h'};
auto module = ByteCodeParser::parse_module(make_module_bytes(SectionId::Custom, content));
expect_eq(module, tl::unexpected{wasm::ModuleParseError::InvalidCustomSection});
});
 
etest::test("custom section, eof in data", [] {
std::stringstream wasm_bytes;
wasm_bytes << "\0asm\1\0\0\0"sv;
wasm_bytes << static_cast<std::uint8_t>(SectionId::Custom);
wasm_bytes << static_cast<std::uint8_t>(100);
wasm_bytes << "\2hi";
wasm_bytes << "123";
auto module = ByteCodeParser::parse_module(wasm_bytes);
expect_eq(module, tl::unexpected{wasm::ModuleParseError::InvalidCustomSection});
});
}
 
void export_section_tests() {
etest::test("export section, missing export count", [] {
auto module = ByteCodeParser::parse_module(make_module_bytes(SectionId::Export, {}));
@@ -658,11 +688,12 @@ int main() {
});
 
etest::test("unhandled section", [] {
expect_eq(ByteCodeParser::parse_module(make_module_bytes(SectionId::Custom, {})),
expect_eq(ByteCodeParser::parse_module(make_module_bytes(SectionId::DataCount, {})),
tl::unexpected{wasm::ModuleParseError::UnhandledSection});
});
 
parse_error_to_string_tests();
custom_section_tests();
type_section_tests();
import_section_tests();
function_section_tests();
 
wasm/wasm.h added: 70, removed: 6, total 64
@@ -16,6 +16,13 @@
 
namespace wasm {
 
struct CustomSection {
std::string name{};
std::vector<std::uint8_t> data{};
 
[[nodiscard]] bool operator==(CustomSection const &) const = default;
};
 
// https://webassembly.github.io/spec/core/binary/types.html#binary-globaltype
struct GlobalType {
enum class Mutability {
@@ -134,7 +141,8 @@ struct CodeSection {
 
// https://webassembly.github.io/spec/core/syntax/modules.html
struct Module {
// TODO(robinlinden): custom_sections
std::vector<CustomSection> custom_sections{};
 
std::optional<TypeSection> type_section{};
std::optional<ImportSection> import_section{};
std::optional<FunctionSection> function_section{};