protoverse

A metaverse protocol
git clone git://jb55.com/protoverse
Log | Files | Refs | README | LICENSE

commit da7f3ddb69721a7acde39c08030d8631cb39960a
parent 3ed8d231a81ec6ef4bd3ad4d2d6e17e8ce036952
Author: William Casarin <jb55@jb55.com>
Date:   Mon,  5 Jul 2021 10:21:09 -0700

fix limit parse, add table parser

Diffstat:
Msrc/wasm.c | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Msrc/wasm.h | 16++++++++++++++++
2 files changed, 106 insertions(+), 31 deletions(-)

diff --git a/src/wasm.c b/src/wasm.c @@ -707,6 +707,91 @@ static int parse_export_section(struct wasm_parser *p, return 1; } +static int is_valid_reftype(unsigned char reftype) +{ + switch ((enum reftype)reftype) { + case funcref: return 1; + case externref: return 1; + } + return 0; +} + +static int parse_limits(struct wasm_parser *p, struct limits *limits) +{ + unsigned char tag; + if (!pull_byte(&p->cur, &tag)) { + note_error(p, "oob"); + return 0; + } + + if (tag != limit_min && tag != limit_min_max) { + note_error(p, "invalid tag %02x", tag); + return 0; + } + + if (!leb128_read(&p->cur, &limits->min)) { + note_error(p, "min"); + return 0; + } + + if (tag == limit_min) + return 1; + + if (!leb128_read(&p->cur, &limits->max)) { + note_error(p, "max"); + return 0; + } + + return 1; +} + +static int parse_table(struct wasm_parser *p, struct table *table) +{ + unsigned char reftype; + if (!pull_byte(&p->cur, &reftype)) { + note_error(p, "reftype"); + return 0; + } + + if (!is_valid_reftype(reftype)) { + note_error(p, "invalid reftype: 0x%x", reftype); + return 0; + } + + table->reftype = (enum reftype)reftype; + + if (!parse_limits(p, &table->limits)) { + note_error(p, "limits"); + return 0; + } + + return 1; +} + +static int parse_table_section(struct wasm_parser *p, + struct tablesec *table_section) +{ + struct table *tables; + unsigned int elems, i; + + if (!parse_vector(p, sizeof(*tables), &elems, (void**)&tables)) { + note_error(p, "tables vector"); + return 0; + } + + for (i = 0; i < elems; i++) { + if (!parse_table(p, &tables[i])) { + note_error(p, "table #%d/%d", i+1, elems); + return 0; + } + } + + table_section->num_tables = elems; + table_section->tables = tables; + + return 1; +} + static int parse_function_section(struct wasm_parser *p, struct funcsec *funcsec) { @@ -757,35 +842,6 @@ static int parse_globaltype(struct wasm_parser *p, struct globaltype *g) return parse_mut(p, &g->mut); } -static int parse_limits(struct wasm_parser *p, struct limits *limits) -{ - unsigned char tag; - if (!pull_byte(&p->cur, &tag)) { - note_error(p, "oob"); - return 0; - } - - if (tag != limit_min || tag != limit_min_max) { - note_error(p, "invalid tag %02x", tag); - return 0; - } - - if (!leb128_read(&p->cur, &limits->min)) { - note_error(p, "min"); - return 0; - } - - if (tag == limit_min) - return 1; - - if (!leb128_read(&p->cur, &limits->max)) { - note_error(p, "max"); - return 0; - } - - return 1; -} - static int parse_import_table(struct wasm_parser *p, struct limits *limits) { if (!consume_byte(&p->cur, 0x70)) { @@ -941,8 +997,11 @@ static int parse_section_by_tag(struct wasm_parser *p, enum section_tag tag, } return 1; case section_table: - note_error(p, "section_table parse not implemented"); - return 0; + if (!parse_table_section(p, &p->module.table_section)) { + note_error(p, "table section"); + return 0; + } + return 1; case section_memory: note_error(p, "section_memory parse not implemented"); return 0; diff --git a/src/wasm.h b/src/wasm.h @@ -46,6 +46,11 @@ enum section_tag { num_sections, }; +enum reftype { + funcref = 0x70, + externref = 0x6F, +}; + struct resulttype { unsigned char *valtypes; /* enum valtype */ int num_valtypes; @@ -56,6 +61,16 @@ struct functype { struct resulttype result; }; +struct table { + enum reftype reftype; + struct limits limits; +}; + +struct tablesec { + struct table *tables; + int num_tables; +}; + struct funcsec { unsigned int *type_indices; int num_indices; @@ -288,6 +303,7 @@ struct module { struct importsec import_section; struct exportsec export_section; struct codesec code_section; + struct tablesec table_section; }; struct wasm_interp {