diff options
Diffstat (limited to 'src/section')
| -rw-r--r-- | src/section/CMakeLists.txt | 15 | ||||
| -rw-r--r-- | src/section/code.c | 235 | ||||
| -rw-r--r-- | src/section/common.c | 35 | ||||
| -rw-r--r-- | src/section/custom.c | 17 | ||||
| -rw-r--r-- | src/section/data.c | 8 | ||||
| -rw-r--r-- | src/section/element.c | 8 | ||||
| -rw-r--r-- | src/section/export.c | 147 | ||||
| -rw-r--r-- | src/section/function.c | 80 | ||||
| -rw-r--r-- | src/section/global.c | 110 | ||||
| -rw-r--r-- | src/section/import.c | 188 | ||||
| -rw-r--r-- | src/section/memory.c | 81 | ||||
| -rw-r--r-- | src/section/start.c | 8 | ||||
| -rw-r--r-- | src/section/table.c | 96 | ||||
| -rw-r--r-- | src/section/type.c | 126 |
14 files changed, 1154 insertions, 0 deletions
diff --git a/src/section/CMakeLists.txt b/src/section/CMakeLists.txt new file mode 100644 index 0000000..62d9cef --- /dev/null +++ b/src/section/CMakeLists.txt @@ -0,0 +1,15 @@ +target_sources(${PROJECT_NAME} PRIVATE + code.c + common.c + custom.c + data.c + element.c + export.c + function.c + global.c + import.c + memory.c + start.c + table.c + type.c +) diff --git a/src/section/code.c b/src/section/code.c new file mode 100644 index 0000000..6e131e7 --- /dev/null +++ b/src/section/code.c @@ -0,0 +1,235 @@ +#include <opcodes.h> +#include <interp.h> +#include <sections.h> +#include <wasm_types.h> +#include <errno.h> +#include <inttypes.h> +#include <stdint.h> +#include <string.h> + +static int check_body(FILE *const f, const unsigned long n) +{ + unsigned long rem = n; + + while (rem) + { + const long before = ftell(f); + uint8_t byte; + + if (before < 0) + { + fprintf(stderr, "%s: ftell(3) before: %s\n", __func__, + strerror(errno)); + return -1; + } + else if (!fread(&byte, sizeof byte, 1, f)) + { + fprintf(stderr, "%s: fread(3) failed, feof=%d, ferror=%d\n", + __func__, feof(f), ferror(f)); + return -1; + } + else if (rem == 1 && byte != OP_END) + { + fprintf(stderr, "%s: unexpected opcode %#" PRIx8 " at body end\n", + __func__, byte); + return -1; + } + else if (interp_check_opcode(byte, f)) + { + fprintf(stderr, "%s: interp_check_opcode failed\n", __func__); + return -1; + } + + const long after = ftell(f); + + if (after < 0) + { + fprintf(stderr, "%s: ftell(3) after: %s\n", __func__, + strerror(errno)); + return -1; + } + + rem -= after - before; + } + + return 0; +} + +static int check_type(FILE *const f) +{ + varint7 type; + + if (varint7_read(f, &type)) + { + fprintf(stderr, "%s: varint7_read failed\n", __func__); + return -1; + } + + return 0; +} + +static int check_local(FILE *const f) +{ + varuint32 count; + + if (varuint32_read(f, &count)) + { + fprintf(stderr, "%s: varuint32_read failed\n", __func__); + return -1; + } + else if (check_type(f)) + { + fprintf(stderr, "%s: check_type failed\n", __func__); + return -1; + } + + return 0; +} + +static int check_locals(FILE *const f) +{ + varuint32 local_count; + + if (varuint32_read(f, &local_count)) + { + fprintf(stderr, "%s: varuint32_read local_count failed\n", __func__); + return -1; + } + + for (varuint32 i = 0; i < local_count; i++) + if (check_local(f)) + { + fprintf(stderr, "%s: check_local failed\n", __func__); + return -1; + } + + return 0; +} + +static int check_function_body(FILE *const f) +{ + varuint32 body_size; + + if (varuint32_read(f, &body_size)) + { + fprintf(stderr, "%s: varuint32_read body_size failed\n", __func__); + return -1; + } + + const long start = ftell(f); + + if (start < 0) + { + fprintf(stderr, "%s: ftell(3) start: %s\n", __func__, strerror(errno)); + return -1; + } + else if (check_locals(f)) + { + fprintf(stderr, "%s: check_locals failed\n", __func__); + return -1; + } + + const long end = ftell(f); + + if (end < 0) + { + fprintf(stderr, "%s: ftell(3) end: %s\n", __func__, strerror(errno)); + return -1; + } + + const unsigned long consumed = end - start; + + if (consumed > body_size) + { + fprintf(stderr, "%s: exceeded function body size\n", __func__); + return -1; + } + else if (check_body(f, body_size - consumed)) + { + fprintf(stderr, "%s: check_body failed\n", __func__); + return -1; + } + + return 0; +} + +static int check_function_bodies(FILE *const f) +{ + varuint32 count; + + if (varuint32_read(f, &count)) + { + fprintf(stderr, "%s: varuint32_read failed\n", __func__); + return -1; + } + + for (varuint32 i = 0; i < count; i++) + if (check_function_body(f)) + { + fprintf(stderr, "%s: check_function_body failed\n", __func__); + return -1; + } + + return 0; +} + +static int check(FILE *const f, const unsigned long len) +{ + const long start = ftell(f); + + if (start < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + else if (check_function_bodies(f)) + { + fprintf(stderr, "%s: check_function_bodies failed\n", __func__); + return -1; + } + + const long end = ftell(f); + + if (end < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + + const unsigned long size = end - start; + + if (size != len) + { + fprintf(stderr, "%s: size exceeded (%lu expected, got %lu)\n", + __func__, len, size); + return -1; + } + + return 0; +} + +int section_code(struct wasmfs *const w, FILE *const f, + const unsigned long len) +{ + if (w->sections.code) + { + fprintf(stderr, "%s: ignoring duplicate section\n", __func__); + return 0; + } + + const long offset = ftell(f); + + if (offset < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + else if (check(f, len)) + { + fprintf(stderr, "%s: check failed\n", __func__); + return -1; + } + + w->sections.code = offset; + return 0; +} diff --git a/src/section/common.c b/src/section/common.c new file mode 100644 index 0000000..58ddddb --- /dev/null +++ b/src/section/common.c @@ -0,0 +1,35 @@ +#include <sections.h> +#include <wasm_types.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +int check_resizable_limits(FILE *const f) +{ + varuint1 flags; + varuint32 initial; + + if (varuint1_read(f, &flags)) + { + fprintf(stderr, "%s: varuint1_read failed\n", __func__); + return -1; + } + else if (varuint32_read(f, &initial)) + { + fprintf(stderr, "%s: varuint32_read failed\n", __func__); + return -1; + } + + if (flags) + { + varuint32 maximum; + + if (varuint32_read(f, &maximum)) + { + fprintf(stderr, "%s: varuint32_read failed\n", __func__); + return -1; + } + } + + return 0; +} diff --git a/src/section/custom.c b/src/section/custom.c new file mode 100644 index 0000000..9544f17 --- /dev/null +++ b/src/section/custom.c @@ -0,0 +1,17 @@ +#include <sections.h> +#include <wasm_types.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +int section_custom(struct wasmfs *const w, FILE *const f, + const unsigned long len) +{ + if (fseek(f, len, SEEK_CUR)) + { + fprintf(stderr, "%s: fseek(3): %s\n", __func__, strerror(errno)); + return -1; + } + + return 0; +} diff --git a/src/section/data.c b/src/section/data.c new file mode 100644 index 0000000..5a04d7b --- /dev/null +++ b/src/section/data.c @@ -0,0 +1,8 @@ +#include <sections.h> +#include <wasm_types.h> + +int section_data(struct wasmfs *const w, FILE *const f, + const unsigned long len) +{ + return -1; +} diff --git a/src/section/element.c b/src/section/element.c new file mode 100644 index 0000000..370a952 --- /dev/null +++ b/src/section/element.c @@ -0,0 +1,8 @@ +#include <sections.h> +#include <wasm_types.h> + +int section_element(struct wasmfs *const w, FILE *const f, + const unsigned long len) +{ + return -1; +} diff --git a/src/section/export.c b/src/section/export.c new file mode 100644 index 0000000..9ca8de5 --- /dev/null +++ b/src/section/export.c @@ -0,0 +1,147 @@ +#include <sections.h> +#include <wasm_types.h> +#include <errno.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> + +static int check_string(FILE *const f) +{ + varuint32 len; + + if (varuint32_read(f, &len)) + { + fprintf(stderr, "%s: varuint32_read failed\n", __func__); + return -1; + } + + for (varuint32 i = 0; i < len; i++) + { + uint8_t byte; + + if (!fread(&byte, sizeof byte, 1, f)) + { + fprintf(stderr, "%s: fread(3) failed, feof=%d, ferror=%d\n", + __func__, feof(f), ferror(f)); + return -1; + } + } + + return 0; +} + +static int check_kind(FILE *const f) +{ + varuint32 type; + + if (varuint32_read(f, &type)) + { + fprintf(stderr, "%s: varuint32_read failed\n", __func__); + return -1; + } + + return 0; +} + +static int check_index(FILE *const f) +{ + varuint32 index; + + if (varuint32_read(f, &index)) + { + fprintf(stderr, "%s: varuint32_read failed\n", __func__); + return -1; + } + + return 0; +} + +static int check_export_entry(FILE *const f) +{ + if (check_string(f)) + { + fprintf(stderr, "%s: check_string failed\n", __func__); + return -1; + } + else if (check_kind(f)) + { + fprintf(stderr, "%s: check_kind failed\n", __func__); + return -1; + } + else if (check_index(f)) + { + fprintf(stderr, "%s: check_index failed\n", __func__); + return -1; + } + + return 0; +} + +static int check(FILE *const f, const unsigned long len) +{ + const long start = ftell(f); + varuint32 count; + + if (start < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + else if (varuint32_read(f, &count)) + { + fprintf(stderr, "%s: varuint32_read failed\n", __func__); + return -1; + } + + for (varuint32 i = 0; i < count; i++) + if (check_export_entry(f)) + { + fprintf(stderr, "%s: check_export_entry failed\n", __func__); + return -1; + } + + const long end = ftell(f); + + if (end < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + + const unsigned long size = end - start; + + if (size != len) + { + fprintf(stderr, "%s: size exceeded (%lu expected, got %lu)\n", + __func__, len, size); + return -1; + } + + return 0; +} + +int section_export(struct wasmfs *const w, FILE *const f, + const unsigned long len) +{ + if (w->sections.export) + { + fprintf(stderr, "%s: ignoring duplicate section\n", __func__); + return 0; + } + + const long offset = ftell(f); + + if (offset < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + else if (check(f, len)) + { + fprintf(stderr, "%s: check failed\n", __func__); + return -1; + } + + w->sections.export = offset; + return 0; +} diff --git a/src/section/function.c b/src/section/function.c new file mode 100644 index 0000000..f03971c --- /dev/null +++ b/src/section/function.c @@ -0,0 +1,80 @@ +#include <sections.h> +#include <wasm_types.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +static int check(FILE *const f, const unsigned long len) +{ + const long start = ftell(f); + + if (start < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + + varuint32 count; + + if (varuint32_read(f, &count)) + { + fprintf(stderr, "%s: varuint32_read count failed\n", __func__); + return -1; + } + + for (varuint32 i = 0; i < count; i++) + { + varuint32 type; + + if (varuint32_read(f, &type)) + { + fprintf(stderr, "%s: varuint32_read type failed\n", __func__); + return -1; + } + } + + const long end = ftell(f); + + if (end < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + + const unsigned long size = end - start; + + if (size != len) + { + fprintf(stderr, "%s: size exceeded (%lu expected, got %lu)\n", + __func__, len, size); + return -1; + } + + return 0; +} + +int section_function(struct wasmfs *const w, FILE *const f, + const unsigned long len) +{ + if (w->sections.function) + { + fprintf(stderr, "%s: ignoring duplicate section\n", __func__); + return 0; + } + + const long offset = ftell(f); + + if (offset < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + else if (check(f, len)) + { + fprintf(stderr, "%s: check failed\n", __func__); + return -1; + } + + w->sections.function = offset; + return 0; +} diff --git a/src/section/global.c b/src/section/global.c new file mode 100644 index 0000000..5616e21 --- /dev/null +++ b/src/section/global.c @@ -0,0 +1,110 @@ +#include <sections.h> +#include <interp.h> +#include <wasm_types.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +struct global_type +{ + varint7 value_type; + varuint1 mutability; +}; + +static int check_global_type(FILE *const f, struct global_type *const g) +{ + if (varint7_read(f, &g->value_type)) + { + fprintf(stderr, "%s: varint7_read failed\n", __func__); + return -1; + } + else if (varuint1_read(f, &g->mutability)) + { + fprintf(stderr, "%s: varuint1_read failed\n", __func__); + return -1; + } + + return 0; +} + +static int check(FILE *const f, const unsigned long len) +{ + int ret = -1; + struct global_type g; + struct interp *i = NULL; + const long start = ftell(f); + const struct interp_cfg cfg = + { + .f = f + }; + + if (start < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + else if (check_global_type(f, &g)) + { + fprintf(stderr, "%s: check_global_type\n", __func__); + goto end; + } + else if (!(i = interp_alloc(&cfg))) + { + fprintf(stderr, "%s: interp_alloc failed\n", __func__); + goto end; + } + else if (interp_run_limited(i, &interp_initexpr_set)) + { + fprintf(stderr, "%s: interp_run failed\n", __func__); + goto end; + } + + const long end = ftell(f); + + if (end < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + + const unsigned long size = end - start; + + if (size != len) + { + fprintf(stderr, "%s: size exceeded (%lu expected, got %lu)\n", + __func__, len, size); + return -1; + } + + ret = 0; + +end: + interp_free(i); + return ret; +} + +int section_global(struct wasmfs *const w, FILE *const f, + const unsigned long len) +{ + if (w->sections.global) + { + fprintf(stderr, "%s: ignoring duplicate section\n", __func__); + return 0; + } + + const long offset = ftell(f); + + if (offset < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + else if (check(f, len)) + { + fprintf(stderr, "%s: check failed\n", __func__); + return -1; + } + + w->sections.global = offset; + return 0; +} diff --git a/src/section/import.c b/src/section/import.c new file mode 100644 index 0000000..06df4e1 --- /dev/null +++ b/src/section/import.c @@ -0,0 +1,188 @@ +#include <sections.h> +#include <wasm_types.h> +#include <errno.h> +#include <inttypes.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +static int check_string(FILE *const f) +{ + varuint32 len; + + if (varuint32_read(f, &len)) + { + fprintf(stderr, "%s: varuint32_read failed\n", __func__); + return -1; + } + + for (varuint32 i = 0; i < len; i++) + { + uint8_t byte; + + if (!fread(&byte, sizeof byte, 1, f)) + { + fprintf(stderr, "%s: fread(3) failed, feof=%d, ferror=%d\n", + __func__, feof(f), ferror(f)); + return -1; + } + } + + return 0; +} + +static int check_function_kind(FILE *const f) +{ + varuint32 type; + + if (varuint32_read(f, &type)) + { + fprintf(stderr, "%s: varuint32_read failed\n", __func__); + return -1; + } + + return 0; +} + +static int check_table_kind(FILE *const f) +{ + varint7 type; + + if (varint7_read(f, &type)) + { + fprintf(stderr, "%s: varint7_read failed\n", __func__); + return -1; + } + + return 0; +} + +static int check_memory_kind(FILE *const f) +{ + /* TODO. */ + return -1; +} + +static int check_global_kind(FILE *const f) +{ + /* TODO. */ + return -1; +} + +static int check_import_entry(FILE *const f) +{ + if (check_string(f)) + { + fprintf(stderr, "%s: check_string module failed\n", __func__); + return -1; + } + else if (check_string(f)) + { + fprintf(stderr, "%s: check_string field failed\n", __func__); + return -1; + } + + uint8_t kind; + + enum + { + FUNCTION, + TABLE, + MEMORY, + GLOBAL + }; + + if (!fread(&kind, sizeof kind, 1, f)) + { + fprintf(stderr, "%s: fread(3) failed, feof=%d, ferror=%d\n", + __func__, feof(f), ferror(f)); + return -1; + } + + static int (*const fn[])(FILE *) = + { + [FUNCTION] = check_function_kind, + [TABLE] = check_table_kind, + [MEMORY] = check_memory_kind, + [GLOBAL] = check_global_kind + }; + + if (kind >= sizeof fn / sizeof *fn) + { + fprintf(stderr, "%s: unexpected kind %#" PRIx8 "\n", __func__, kind); + return -1; + } + + return fn[kind](f); +} + +static int check(FILE *const f, const unsigned long len) +{ + const long start = ftell(f); + + if (start < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + + varuint32 count; + + if (varuint32_read(f, &count)) + { + fprintf(stderr, "%s: varuint32_read failed\n", __func__); + return -1; + } + + for (varuint32 i = 0; i < count; i++) + if (check_import_entry(f)) + { + fprintf(stderr, "%s: check_import_entry failed\n", __func__); + return -1; + } + + const long end = ftell(f); + + if (end < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + + const unsigned long size = end - start; + + if (size != len) + { + fprintf(stderr, "%s: size exceeded (%lu expected, got %lu)\n", + __func__, len, size); + return -1; + } + + return 0; +} + +int section_import(struct wasmfs *const w, FILE *const f, + const unsigned long len) +{ + if (w->sections.import) + { + fprintf(stderr, "%s: ignoring duplicate section\n", __func__); + return 0; + } + + const long offset = ftell(f); + + if (offset < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + else if (check(f, len)) + { + fprintf(stderr, "%s: check failed\n", __func__); + return -1; + } + + w->sections.import = offset; + return 0; +} diff --git a/src/section/memory.c b/src/section/memory.c new file mode 100644 index 0000000..aba461a --- /dev/null +++ b/src/section/memory.c @@ -0,0 +1,81 @@ +#include <sections.h> +#include <wasm_types.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +static int check_memory_type(FILE *const f) +{ + return check_resizable_limits(f); +} + +static int check(FILE *const f, const unsigned long len) +{ + const long start = ftell(f); + + if (start < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + + varuint32 count; + + if (varuint32_read(f, &count)) + { + fprintf(stderr, "%s: varuint32_read failed\n", __func__); + return -1; + } + + for (varuint32 i = 0; i < count; i++) + if (check_memory_type(f)) + { + fprintf(stderr, "%s: check_memory_type failed\n", __func__); + return -1; + } + + const long end = ftell(f); + + if (end < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + + const unsigned long size = end - start; + + if (size != len) + { + fprintf(stderr, "%s: size exceeded (%lu expected, got %lu)\n", + __func__, len, size); + return -1; + } + + return 0; +} + +int section_memory(struct wasmfs *const w, FILE *const f, + const unsigned long len) +{ + if (w->sections.memory) + { + fprintf(stderr, "%s: ignoring duplicate section\n", __func__); + return 0; + } + + const long offset = ftell(f); + + if (offset < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + else if (check(f, len)) + { + fprintf(stderr, "%s: check failed\n", __func__); + return -1; + } + + w->sections.memory = offset; + return 0; +} diff --git a/src/section/start.c b/src/section/start.c new file mode 100644 index 0000000..821525d --- /dev/null +++ b/src/section/start.c @@ -0,0 +1,8 @@ +#include <sections.h> +#include <wasm_types.h> + +int section_start(struct wasmfs *const w, FILE *const f, + const unsigned long len) +{ + return -1; +} diff --git a/src/section/table.c b/src/section/table.c new file mode 100644 index 0000000..9f793c7 --- /dev/null +++ b/src/section/table.c @@ -0,0 +1,96 @@ +#include <sections.h> +#include <wasm_types.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +static int check_table_type(FILE *const f) +{ + enum {ANYFUNC = 0x70}; + varint7 elem_type; + + if (varint7_read(f, &elem_type)) + { + fprintf(stderr, "%s: varint7_read failed\n", __func__); + return -1; + } + else if (elem_type != ANYFUNC) + { + fprintf(stderr, "%s: expected %x, got %x", __func__, ANYFUNC, + (int)elem_type); + return -1; + } + + return check_resizable_limits(f); +} + +static int check(FILE *const f, const unsigned long len) +{ + const long start = ftell(f); + + if (start < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + + varuint32 count; + + if (varuint32_read(f, &count)) + { + fprintf(stderr, "%s: varuint32_read failed\n", __func__); + return -1; + } + + for (varuint32 i = 0; i < count; i++) + if (check_table_type(f)) + { + fprintf(stderr, "%s: check_table_type failed\n", __func__); + return -1; + } + + const long end = ftell(f); + + if (end < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + + const unsigned long size = end - start; + + if (size != len) + { + fprintf(stderr, "%s: size exceeded (%lu expected, got %lu)\n", + __func__, len, size); + return -1; + } + + return 0; +} + +int section_table(struct wasmfs *const w, FILE *const f, + const unsigned long len) +{ + if (w->sections.table) + { + fprintf(stderr, "%s: ignoring duplicate section\n", __func__); + return 0; + } + + const long offset = ftell(f); + + if (offset < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + else if (check(f, len)) + { + fprintf(stderr, "%s: check failed\n", __func__); + return -1; + } + + w->sections.table = offset; + return 0; +} diff --git a/src/section/type.c b/src/section/type.c new file mode 100644 index 0000000..fad2208 --- /dev/null +++ b/src/section/type.c @@ -0,0 +1,126 @@ +#include <sections.h> +#include <wasm_types.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +static int check_value_type(FILE *const f) +{ + varint7 value_type; + + if (varint7_read(f, &value_type)) + { + fprintf(stderr, "%s: varint7_read failed\n", __func__); + return -1; + } + + return 0; +} + +static int check_func_type(FILE *const f) +{ + varint7 form; + varuint32 param_count; + + if (varint7_read(f, &form)) + { + fprintf(stderr, "%s: varint7_read failed\n", __func__); + return -1; + } + else if (varuint32_read(f, ¶m_count)) + { + fprintf(stderr, "%s: varuint32_read failed\n", __func__); + return -1; + } + + for (varuint32 i = 0; i < param_count; i++) + if (check_value_type(f)) + { + fprintf(stderr, "%s: check_value_type failed\n", __func__); + return -1; + } + + varuint1 return_count; + + if (varuint1_read(f, &return_count)) + { + fprintf(stderr, "%s: varuint1_read failed\n", __func__); + return -1; + } + else if (return_count && check_value_type(f)) + { + fprintf(stderr, "%s: check_value_type 2 failed\n", __func__); + return -1; + } + + return 0; +} + +static int check(FILE *const f, const unsigned long len) +{ + const long start = ftell(f); + varuint32 count; + + if (start < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + else if (varuint32_read(f, &count)) + { + fprintf(stderr, "%s: varuint32_read failed\n", __func__); + return -1; + } + + for (varuint32 i = 0; i < count; i++) + if (check_func_type(f)) + { + fprintf(stderr, "%s: check_func_type failed\n", __func__); + return -1; + } + + const long end = ftell(f); + + if (end < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + + const unsigned long size = end - start; + + if (size != len) + { + fprintf(stderr, "%s: size exceeded (%lu expected, got %lu)\n", + __func__, len, size); + return -1; + } + + return 0; +} + +int section_type(struct wasmfs *const w, FILE *const f, + const unsigned long len) +{ + if (w->sections.type) + { + fprintf(stderr, "%s: ignoring duplicate section\n", __func__); + return 0; + } + + const long offset = ftell(f); + + if (offset < 0) + { + fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno)); + return -1; + } + else if (check(f, len)) + { + fprintf(stderr, "%s: check failed\n", __func__); + return -1; + } + + w->sections.type = offset; + return 0; +} |
